<commit_before>'use strict';

var path     = require('path');
var fs       = require('fs');
var which    = require('which');
var expect   = require('expect.js');
var buffered = require('./util/buffered');
var spawn    = require('../');

var isWin    = process.platform === 'win32';

// Fix AppVeyor tests because Git bin folder is in PATH and it has a "echo" program there
if (isWin) {
    process.env.PATH = process.env.PATH
    .split(path.delimiter)
    .filter(function (entry) {
        return /\\git\\bin$/i.test(path.normalize(entry));
    })
    .join(path.delimiter);
}

describe('cross-spawn', function () {
    it('should support shebang in executables (with /usr/bin/env)', function (next) {
        buffered(__dirname + '/fixtures/shebang', function (err, data, code) {
            var envPath;

            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('shebang works!');

            // Test if the actual shebang file is resolved against the PATH
            envPath = process.env.PATH;
            process.env.PATH = path.normalize(__dirname + '/fixtures/') + path.delimiter + process.env.PATH;

            buffered('shebang', function (err, data, code) {
                process.env.PATH = envPath;

                expect(err).to.not.be.ok();
                expect(code).to.be(0);
                expect(data).to.equal('shebang works!');

                next();
            });
        });
    });

    it('should support shebang in executables (without /usr/bin/env)', function (next) {
        var nodejs = which.sync('node');
        var file = __dirname + '/fixtures/shebang_noenv';

        fs.writeFileSync(file, '#!' + nodejs + '\n\nprocess.stdout.write(\'shebang works!\');', {
            mode: parseInt('0777', 8)
        });

        buffered(file, function (err, data, code) {
            var envPath;

            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('shebang works!');

            // Test if the actual shebang file is resolved against the PATH
            envPath = process.env.PATH;
            process.env.PATH = path.normalize(__dirname + '/fixtures/') + path.delimiter + process.env.PATH;

            buffered('shebang_noenv', function (err, data, code) {
                process.env.PATH = envPath;

                expect(err).to.not.be.ok();
                expect(code).to.be(0);
                expect(data).to.equal('shebang works!');

                next();
            });
        });
    });

    it('should expand using PATHEXT properly', function (next) {
        buffered(__dirname + '/fixtures/foo', function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data.trim()).to.equal('foo');

            next();
        });
    });

    it('should handle commands with spaces', function (next) {
        buffered(__dirname + '/fixtures/bar space', function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data.trim()).to.equal('bar');

            next();
        });
    });

    it('should handle commands with special shell chars', function (next) {
        buffered(__dirname + '/fixtures/()%!^&;, ', function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data.trim()).to.equal('special');

            next();
        });
    });

    it('should handle empty arguments', function (next) {
        buffered('node', [
            __dirname + '/fixtures/echo',
            'foo',
            '',
            'bar'
        ], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('foo\n\nbar');

            buffered('echo', [
                'foo',
                '',
                'bar'
            ], function (err, data, code) {
                expect(err).to.not.be.ok();
                expect(code).to.be(0);
                expect(data.trim()).to.equal('foo  bar');

                next();
            });
        });
    });

    it('should handle non-string arguments', function (next) {
        buffered('node', [
            __dirname + '/fixtures/echo',
            1234
        ], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('1234');

            next();
        });
    });

    it('should handle arguments with spaces', function (next) {
        buffered('node', [
            __dirname + '/fixtures/echo',
            'I am',
            'André Cruz'
        ], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('I am\nAndré Cruz');

            next();
        });
    });

    it('should handle arguments with \\"', function (next) {
        buffered('node', [
            __dirname + '/fixtures/echo',
            'foo',
            '\\"',
            'bar'
        ], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('foo\n\\"\nbar');

            next();
        });
    });

    it('should handle arguments that end with \\', function (next) {
        buffered('node', [
            __dirname + '/fixtures/echo',
            'foo',
            'bar\\',
            'baz'
        ], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('foo\nbar\\\nbaz');

            next();
        });
    });

    it('should handle arguments that contain shell special chars', function (next) {
        buffered('node', [
            __dirname + '/fixtures/echo',
            'foo',
            '()',
            'foo',
            '%!',
            'foo',
            '^<',
            'foo',
            '>&',
            'foo',
            '|;',
            'foo',
            ', ',
            'foo'
        ], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('foo\n()\nfoo\n%!\nfoo\n^<\nfoo\n>&\nfoo\n|;\nfoo\n, \nfoo');

            next();
        });
    });

    it('should handle special arguments when using echo', function (next) {
        buffered('echo', ['foo\\"foo\\foo&bar"foo\'bar'], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data.trim()).to.equal('foo\\"foo\\foo&bar"foo\'bar');

            buffered('echo', [
                'foo',
                '()',
                'foo',
                '%!',
                'foo',
                '^<',
                'foo',
                '>&',
                'foo',
                '|;',
                'foo',
                ', ',
                'foo'
            ], function (err, data, code) {
                expect(err).to.not.be.ok();
                expect(code).to.be(0);
                expect(data.trim()).to.equal('foo () foo %! foo ^< foo >& foo |; foo ,  foo');

                next();
            });
        });
    });

    it('should handle optional args correctly', function (next) {
        buffered(__dirname + '/fixtures/foo', function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);

            buffered(__dirname + '/fixtures/foo', {
                stdio: ['pipe', 'ignore', 'pipe'],
            }, function (err, data, code) {
                expect(err).to.not.be.ok();
                expect(code).to.be(0);
                expect(data).to.be(null);

                buffered(__dirname + '/fixtures/foo', null, {
                    stdio: ['pipe', 'ignore', 'pipe'],
                }, function (err, data, code) {
                    expect(err).to.not.be.ok();
                    expect(code).to.be(0);
                    expect(data).to.be(null);

                    next();
                });
            });
        });
    });

    it('should not mutate args nor options', function (next) {
        var args = [];
        var options = {};

        buffered(__dirname + '/fixtures/foo', function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);

            expect(args).to.have.length(0);
            expect(Object.keys(options)).to.have.length(0);

            next();
        });
    });

    it('should give correct exit code', function (next) {
        buffered('node', [__dirname + '/fixtures/exit'], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(25);

            next();
        });
    });

    it('should work with a relative command', function (next) {
        buffered(path.relative(process.cwd(), __dirname + '/fixtures/foo'), function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data.trim()).to.equal('foo');

            if (!isWin) {
                return next();
            }

            buffered(path.relative(process.cwd(), __dirname + '/fixtures/foo.bat'), function (err, data, code) {
                expect(err).to.not.be.ok();
                expect(code).to.be(0);
                expect(data.trim()).to.equal('foo');

                next();
            });
        });
    });

    it('should emit "error" and "close" if command does not exist', function (next) {
        var spawned;
        var errors = [];
        var timeout;

        this.timeout(5000);

        spawned = spawn('somecommandthatwillneverexist')
        .on('error', function (err) {
            errors.push(err);
        })
        .on('exit', function () {
            spawned.removeAllListeners();
            clearTimeout(timeout);
            next(new Error('Should not emit exit'));
        })
        .on('close', function (code, signal) {
            expect(code).to.not.be(0);
            expect(signal).to.be(null);

            timeout = setTimeout(function () {
                var err;

                expect(errors).to.have.length(1);

                err = errors[0];
                expect(err).to.be.an(Error);
                expect(err.message).to.contain('spawn');
                expect(err.message).to.contain('ENOENT');
                expect(err.message).to.not.contain('undefined');
                expect(err.code).to.be('ENOENT');
                expect(err.errno).to.be('ENOENT');
                expect(err.syscall).to.contain('spawn');
                expect(err.syscall).to.not.contain('undefined');

                next();
            }, 1000);
        });
    });

    it('should NOT emit "error" if shebang command does not exist', function (next) {
        var spawned;
        var exited;
        var timeout;

        this.timeout(5000);

        spawned = spawn(__dirname + '/fixtures/shebang_enoent')
        .on('error', function (err) {
            spawned.removeAllListeners();
            clearTimeout(timeout);
            next(new Error('Should not emit error'));
        })
        .on('exit', function () {
            exited = true;
        })
        .on('close', function (code, signal) {
            expect(code).to.not.be(0);
            expect(signal).to.be(null);
            expect(exited).to.be(true);

            timeout = setTimeout(next, 1000);
        });
    });

    it('should NOT emit "error" if the command actual exists but exited with 1', function (next) {
        var spawned;
        var exited;
        var timeout;

        this.timeout(5000);

        spawned = spawn(__dirname + '/fixtures/exit1')
        .on('error', function (err) {
            spawned.removeAllListeners();
            clearTimeout(timeout);
            next(new Error('Should not emit error'));
        })
        .on('exit', function () {
            exited = true;
        })
        .on('close', function (code, signal) {
            expect(code).to.not.be(0);
            expect(signal).to.be(null);
            expect(exited).to.be(true);

            timeout = setTimeout(next, 1000);
        });
    });
});
<commit_msg>Attempt to fix tests again, third try.<commit_after>'use strict';

var path     = require('path');
var fs       = require('fs');
var which    = require('which');
var expect   = require('expect.js');
var buffered = require('./util/buffered');
var spawn    = require('../');

var isWin    = process.platform === 'win32';

// Fix AppVeyor tests because Git bin folder is in PATH and it has a "echo" program there
if (isWin) {
    process.env.PATH = process.env.PATH
    .split(path.delimiter)
    .filter(function (entry) {
        return !/\\git\\bin$/i.test(path.normalize(entry));
    })
    .join(path.delimiter);
}

describe('cross-spawn', function () {
    it('should support shebang in executables (with /usr/bin/env)', function (next) {
        buffered(__dirname + '/fixtures/shebang', function (err, data, code) {
            var envPath;

            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('shebang works!');

            // Test if the actual shebang file is resolved against the PATH
            envPath = process.env.PATH;
            process.env.PATH = path.normalize(__dirname + '/fixtures/') + path.delimiter + process.env.PATH;

            buffered('shebang', function (err, data, code) {
                process.env.PATH = envPath;

                expect(err).to.not.be.ok();
                expect(code).to.be(0);
                expect(data).to.equal('shebang works!');

                next();
            });
        });
    });

    it('should support shebang in executables (without /usr/bin/env)', function (next) {
        var nodejs = which.sync('node');
        var file = __dirname + '/fixtures/shebang_noenv';

        fs.writeFileSync(file, '#!' + nodejs + '\n\nprocess.stdout.write(\'shebang works!\');', {
            mode: parseInt('0777', 8)
        });

        buffered(file, function (err, data, code) {
            var envPath;

            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('shebang works!');

            // Test if the actual shebang file is resolved against the PATH
            envPath = process.env.PATH;
            process.env.PATH = path.normalize(__dirname + '/fixtures/') + path.delimiter + process.env.PATH;

            buffered('shebang_noenv', function (err, data, code) {
                process.env.PATH = envPath;

                expect(err).to.not.be.ok();
                expect(code).to.be(0);
                expect(data).to.equal('shebang works!');

                next();
            });
        });
    });

    it('should expand using PATHEXT properly', function (next) {
        buffered(__dirname + '/fixtures/foo', function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data.trim()).to.equal('foo');

            next();
        });
    });

    it('should handle commands with spaces', function (next) {
        buffered(__dirname + '/fixtures/bar space', function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data.trim()).to.equal('bar');

            next();
        });
    });

    it('should handle commands with special shell chars', function (next) {
        buffered(__dirname + '/fixtures/()%!^&;, ', function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data.trim()).to.equal('special');

            next();
        });
    });

    it('should handle empty arguments', function (next) {
        buffered('node', [
            __dirname + '/fixtures/echo',
            'foo',
            '',
            'bar'
        ], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('foo\n\nbar');

            buffered('echo', [
                'foo',
                '',
                'bar'
            ], function (err, data, code) {
                expect(err).to.not.be.ok();
                expect(code).to.be(0);
                expect(data.trim()).to.equal('foo  bar');

                next();
            });
        });
    });

    it('should handle non-string arguments', function (next) {
        buffered('node', [
            __dirname + '/fixtures/echo',
            1234
        ], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('1234');

            next();
        });
    });

    it('should handle arguments with spaces', function (next) {
        buffered('node', [
            __dirname + '/fixtures/echo',
            'I am',
            'André Cruz'
        ], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('I am\nAndré Cruz');

            next();
        });
    });

    it('should handle arguments with \\"', function (next) {
        buffered('node', [
            __dirname + '/fixtures/echo',
            'foo',
            '\\"',
            'bar'
        ], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('foo\n\\"\nbar');

            next();
        });
    });

    it('should handle arguments that end with \\', function (next) {
        buffered('node', [
            __dirname + '/fixtures/echo',
            'foo',
            'bar\\',
            'baz'
        ], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('foo\nbar\\\nbaz');

            next();
        });
    });

    it('should handle arguments that contain shell special chars', function (next) {
        buffered('node', [
            __dirname + '/fixtures/echo',
            'foo',
            '()',
            'foo',
            '%!',
            'foo',
            '^<',
            'foo',
            '>&',
            'foo',
            '|;',
            'foo',
            ', ',
            'foo'
        ], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data).to.equal('foo\n()\nfoo\n%!\nfoo\n^<\nfoo\n>&\nfoo\n|;\nfoo\n, \nfoo');

            next();
        });
    });

    it('should handle special arguments when using echo', function (next) {
        buffered('echo', ['foo\\"foo\\foo&bar"foo\'bar'], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data.trim()).to.equal('foo\\"foo\\foo&bar"foo\'bar');

            buffered('echo', [
                'foo',
                '()',
                'foo',
                '%!',
                'foo',
                '^<',
                'foo',
                '>&',
                'foo',
                '|;',
                'foo',
                ', ',
                'foo'
            ], function (err, data, code) {
                expect(err).to.not.be.ok();
                expect(code).to.be(0);
                expect(data.trim()).to.equal('foo () foo %! foo ^< foo >& foo |; foo ,  foo');

                next();
            });
        });
    });

    it('should handle optional args correctly', function (next) {
        buffered(__dirname + '/fixtures/foo', function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);

            buffered(__dirname + '/fixtures/foo', {
                stdio: ['pipe', 'ignore', 'pipe'],
            }, function (err, data, code) {
                expect(err).to.not.be.ok();
                expect(code).to.be(0);
                expect(data).to.be(null);

                buffered(__dirname + '/fixtures/foo', null, {
                    stdio: ['pipe', 'ignore', 'pipe'],
                }, function (err, data, code) {
                    expect(err).to.not.be.ok();
                    expect(code).to.be(0);
                    expect(data).to.be(null);

                    next();
                });
            });
        });
    });

    it('should not mutate args nor options', function (next) {
        var args = [];
        var options = {};

        buffered(__dirname + '/fixtures/foo', function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);

            expect(args).to.have.length(0);
            expect(Object.keys(options)).to.have.length(0);

            next();
        });
    });

    it('should give correct exit code', function (next) {
        buffered('node', [__dirname + '/fixtures/exit'], function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(25);

            next();
        });
    });

    it('should work with a relative command', function (next) {
        buffered(path.relative(process.cwd(), __dirname + '/fixtures/foo'), function (err, data, code) {
            expect(err).to.not.be.ok();
            expect(code).to.be(0);
            expect(data.trim()).to.equal('foo');

            if (!isWin) {
                return next();
            }

            buffered(path.relative(process.cwd(), __dirname + '/fixtures/foo.bat'), function (err, data, code) {
                expect(err).to.not.be.ok();
                expect(code).to.be(0);
                expect(data.trim()).to.equal('foo');

                next();
            });
        });
    });

    it('should emit "error" and "close" if command does not exist', function (next) {
        var spawned;
        var errors = [];
        var timeout;

        this.timeout(5000);

        spawned = spawn('somecommandthatwillneverexist')
        .on('error', function (err) {
            errors.push(err);
        })
        .on('exit', function () {
            spawned.removeAllListeners();
            clearTimeout(timeout);
            next(new Error('Should not emit exit'));
        })
        .on('close', function (code, signal) {
            expect(code).to.not.be(0);
            expect(signal).to.be(null);

            timeout = setTimeout(function () {
                var err;

                expect(errors).to.have.length(1);

                err = errors[0];
                expect(err).to.be.an(Error);
                expect(err.message).to.contain('spawn');
                expect(err.message).to.contain('ENOENT');
                expect(err.message).to.not.contain('undefined');
                expect(err.code).to.be('ENOENT');
                expect(err.errno).to.be('ENOENT');
                expect(err.syscall).to.contain('spawn');
                expect(err.syscall).to.not.contain('undefined');

                next();
            }, 1000);
        });
    });

    it('should NOT emit "error" if shebang command does not exist', function (next) {
        var spawned;
        var exited;
        var timeout;

        this.timeout(5000);

        spawned = spawn(__dirname + '/fixtures/shebang_enoent')
        .on('error', function (err) {
            spawned.removeAllListeners();
            clearTimeout(timeout);
            next(new Error('Should not emit error'));
        })
        .on('exit', function () {
            exited = true;
        })
        .on('close', function (code, signal) {
            expect(code).to.not.be(0);
            expect(signal).to.be(null);
            expect(exited).to.be(true);

            timeout = setTimeout(next, 1000);
        });
    });

    it('should NOT emit "error" if the command actual exists but exited with 1', function (next) {
        var spawned;
        var exited;
        var timeout;

        this.timeout(5000);

        spawned = spawn(__dirname + '/fixtures/exit1')
        .on('error', function (err) {
            spawned.removeAllListeners();
            clearTimeout(timeout);
            next(new Error('Should not emit error'));
        })
        .on('exit', function () {
            exited = true;
        })
        .on('close', function (code, signal) {
            expect(code).to.not.be(0);
            expect(signal).to.be(null);
            expect(exited).to.be(true);

            timeout = setTimeout(next, 1000);
        });
    });
});
<|endoftext|>


<commit_before>module.exports = function() {
  var dataBuffer = Array.prototype.slice.call(arguments),
      data,
      self = this;

  data = dataBuffer.map(function(d) {
    return d.toString();
  });

  // update timer for last message recieved
  this.lastMsg = new Date();

  // check protocol of message
  switch(data[0]) {
    case this.constants.PROTOCOL_CLIENT:
    case this.constants.PROTOCOL_BROKER:
      break;
    default:
      console.log('E: Unsupported protocol', data[0]);
      return;
  }

  switch(data[1]) {
    case this.constants.HEARTBEAT:
      console.log('I: HEARTBEAT');
      var heartbeat = [
        this.constants.PROTOCOL_WORKER, this.constants.HEARTBEAT
      ];
      self.socket.send(heartbeat);
      break;
    case this.constants.REQUEST:
      var req = {}, serviceName;

      data.forEach(function(d, i) {
        var attr = self.constants.MSG_ATTRS[i];

        req[attr] = d.toString();
      });

      try {
        self.constants.MSG_ATTRS.slice(0,-1).forEach(function(c) {
          if(!req.hasOwnProperty(c) || req[c] === '') {
            throw new Error('Missing '+c);
          }
        });

        if(req.params) {
          req.params = JSON.parse(req.params);
        }
      } catch(err) {
        console.log('Connot parse message', req.correlationId,  err);
        return;
      }

      console.log('I: REQUEST', req);

      serviceName = req.serviceType+'.'+req.serviceInstance;

      console.log('emit', serviceName);
      this.events.emit(serviceName, req);
      this.events.emit('request', req);
      break;
    case this.constants.DISCONNECT:
      console.log('E: DISCONNECTED', data[2]);

      this.liveness = 0;
      this.events.emit('disconnect', data[3]);
      break;
    default:
      console.log('?: Unknown request type', data[1]);
  }
}
<commit_msg>Use `self` to refer to local attributes & methods<commit_after>module.exports = function() {
  var dataBuffer = Array.prototype.slice.call(arguments),
      data,
      self = this;

  data = dataBuffer.map(function(d) {
    return d.toString();
  });

  // update timer for last message recieved
  self.lastMsg = new Date();

  // check protocol of message
  switch(data[0]) {
    case self.constants.PROTOCOL_CLIENT:
    case self.constants.PROTOCOL_BROKER:
      break;
    default:
      console.log('E: Unsupported protocol', data[0]);
      return;
  }

  switch(data[1]) {
    case self.constants.HEARTBEAT:
      console.log('I: HEARTBEAT');
      var heartbeat = [
        self.constants.PROTOCOL_WORKER, self.constants.HEARTBEAT
      ];
      self.socket.send(heartbeat);
      break;
    case self.constants.REQUEST:
      var req = {}, serviceName;

      data.forEach(function(d, i) {
        var attr = self.constants.MSG_ATTRS[i];

        req[attr] = d.toString();
      });

      try {
        self.constants.MSG_ATTRS.slice(0,-1).forEach(function(c) {
          if(!req.hasOwnProperty(c) || req[c] === '') {
            throw new Error('Missing '+c);
          }
        });

        if(req.params) {
          req.params = JSON.parse(req.params);
        }
      } catch(err) {
        console.log('Connot parse message', req.correlationId,  err);
        return;
      }

      console.log('I: REQUEST', req);

      serviceName = req.serviceType+'.'+req.serviceInstance;

      self.events.emit(serviceName, req);
      self.events.emit('request', req);
      break;
    case self.constants.DISCONNECT:
      console.log('E: DISCONNECTED', data[2]);

      self.liveness = 0;
      self.events.emit('disconnect', data[3]);
      break;
    default:
      console.log('?: Unknown request type', data[1]);
  }
}
<|endoftext|>


<commit_before>'use strict'

const assert = require('assert')
const fs = require('fs')
const jsdom = require('mocha-jsdom')
const parse5 = require('parse5-utils')
const path = require('path')
const vdomToHTML = require('vdom-to-html')
const snabbdomToHTML = require('snabbdom-to-html')

const render = require('..')

function fixtureFilename(name) {
  return path.resolve(__dirname, 'fixtures/' + name + '.jade')
}

function fixture(name) {
  return fs.readFileSync(fixtureFilename(name), 'utf8')
}

function fixtureToHTML(fixtureName, locals, options) {
  options = Object.assign({filename: fixtureFilename(fixtureName)}, options)

  const compiled = render(fixture(fixtureName), options)
  const fn = eval(`(${compiled})`)
  const root = fn.call({class: 'asdf'}, locals)
  const toHTML = options.vdom === 'snabbdom' ? snabbdomToHTML : vdomToHTML;
  const html = toHTML(root)
  parse5.parse(html, true)
  return html
}

// run rendering tests against each supported Virtual DOM library

const VDOM_LIBS = [
  'virtual-dom',
  'snabbdom',
]

for (let vdom of VDOM_LIBS) {
  const renderFixture = function(fixtureName, locals) {
    return fixtureToHTML(fixtureName, locals, {vdom})
  }

  describe(`rendering with ${vdom}`, function () {
    it('should throw a parser error with filename and line number when rendering a broken template', function () {
      const file = 'break-parser'
      const filename = fixtureFilename(file)
      const compile = function () {
        render(fixture(file), {filename})
      }
      let threw = false

      try {
        compile()
      } catch (err) {
        threw = true
        const filenameAndLineNo = new RegExp(filename.replace('/','\/') + ":2")
        assert(err.path == filename, 'err.path should be the full path to the jade file')
        assert(err.message.match(filenameAndLineNo), 'the error message should contain the full path and line number')
        assert(err.message.match(/Unexpected identifier/), 'the error message should contain the error type')
      } finally {
        assert(threw, 'an error should be thrown')
      }
    })

    it('should throw a compiler error with filename and line number when rendering a broken template', function () {
      const file = 'break-compiler'
      const filename = fixtureFilename(file)
      const compile = function () {
        render(fixture(file), {filename})
      }
      let threw = false

      try {
        compile()
      } catch (err) {
        threw = true
        const filenameAndLineNo = new RegExp(filename.replace('/','\/') + ":2")
        assert(err.path == filename, 'err.path (' + err.path + ') should be the full path to the jade file')
        assert(err.message.match(filenameAndLineNo), 'the error message should contain the full path and line number')
        assert(err.message.match(/You can only have one top-level tag!/), 'the error message should contain the error type')
      } finally {
        assert(threw, 'an error should be thrown')
      }
    })

    it('should render a template without options', function () {
      const compiled = render(fixture('attributes'))
      assert(compiled.includes('class1'))
      assert(compiled.includes('foo'))
      assert(compiled.includes('doge'))
    })

    it('should render a template', function () {
      const html = renderFixture('item', {
        item: {
          id: '1234',
          title: 'some title',
          description: 'some description',
          active: true,
        }
      })

      assert(~html.indexOf('item active'))
      assert(~html.indexOf('class="title"'))
      assert(~html.indexOf(' 15)
      assert(lines[lines.length - 1].trim() === '}')
    })

    it('should run while loops correctly', function () {
      const html = renderFixture('while')
      assert(html.match(/
/g).length === 5)
    })

    it('should insert dynamic tag names', function () {
      let html = renderFixture('dynamic-tag', {myTag: 'input'})
      assert(html.includes('<input class="llamas">'))
      html = renderFixture('dynamic-tag', {myTag: 'textarea'})
      assert(html.includes('<textarea class="llamas">'))
    })

    it('renders a simple template', function () {
      const html = renderFixture('simple')
      assert(html === '
This is text
')
    })

    it('translates basic class notation', function () {
      const html = renderFixture('class')
      assert(html.includes('div class="foo"'))
      assert(html.includes('div class="baz llamas"'))
    })
  })
}

describe('Render', function () {
  jsdom();

  describe('multiple files', function () {
    it('should insert included files', function () {
      const html = fixtureToHTML('include')
      assert(html.includes('
Hello
'))
      assert(html.includes('
llamas!!!
'))
      assert(html.includes('
world
'))
    })

    it('should make included mixins available', function () {
      const html = fixtureToHTML('include-with-mixin')
      assert(html.includes('
'))
      assert(html.includes('
insert me
'))
    })

    it('should insert included literal (non-jade) files', function () {
      const html = fixtureToHTML('literal-import')
      const singleRootImport = '
test
'
      const multiRootImport = '
child 1

child 2
'
      const htmlEntities = function(str) {
        return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"')
      }
      const expectedContents =
        '
' +
          '
' +
            '<text>' + htmlEntities(singleRootImport) + '</text>' +
          '
' +
          '
' +
            '<text>' + htmlEntities('
' + multiRootImport + '
') + '</text>' +
          '
' +
        '
'
      assert(html === expectedContents)
    })

    it('should insert extended files', function () {
      const html = fixtureToHTML('extends')
      assert(html.includes('
'))
      assert(html.includes('capybara'))
      assert(html.includes('default content'))
    })
  })

  describe('attributes', function () {
    it('should add arbitrary attributes', function () {
      const html = fixtureToHTML('attributes')
      assert(html.includes('required'))
      assert(!html.includes('something'))
    })

    it('should add class attributes in array notation', function () {
      let html = fixtureToHTML('attributes')
      assert(html.includes('1 2'))
      html = fixtureToHTML('attributes', {variable: 'meow'})
      assert(html.includes('1 2 meow'))
    })

    it('should add class attributes in object notation', function () {
      let html = fixtureToHTML('attributes')
      assert(html.includes('obj1'))
      assert(!html.includes('obj2'))

      html = fixtureToHTML('attributes', {variable: 'doge'})
      assert(html.includes('obj1'))
      assert(html.includes('obj2'))
    })

    it('should combine class attributes in different notations gracefully', function () {
      let html = fixtureToHTML('attributes')
      assert(html.includes('mixed'))
      assert(html.includes('mixedArray1'))
      assert(!html.includes('mixedObj1'))

      html = fixtureToHTML('attributes', {var2: 'doge'})
      assert(html.includes('mixed'))
      assert(html.includes('mixedArray1'))
      assert(html.includes('mixedObj1'))
      assert(html.includes('doge'))
    })

    it('should render data attributes', function () {
      const html = fixtureToHTML('attributes', {variable: 'capybara'})
      assert(html.includes('data-foo-id="42"'))
      assert(html.includes('data-var="capybara"'))
    })

    it('should convert attributes to correct property names', function () {
      const html = fixtureToHTML('attributes')
      assert(html.includes('autocomplete="on"'))
      assert(html.includes('tabindex="5"'))
      assert(html.includes('for="special-attr"'))
    })
  })

  describe('case statements', function () {
    it('should not execute any cases when none match', function () {
      const html = fixtureToHTML('case')
      assert(!html.includes('foo'))
      assert(!html.includes('bar'))
    })

    it('should execute default when no others match', function () {
      const html = fixtureToHTML('case')
      assert(html.includes('llama'))
    })

    it('should execute only one match', function () {
      const html = fixtureToHTML('case', {variable: 1})
      assert(html.includes('span'))
      assert(!html.includes('input'))
      assert(!html.includes('textarea'))
    })

    it('should fall through from the first case in a chain', function () {
      const html = fixtureToHTML('case', {variable2: 'd'})
      assert(html.includes('bar'))
      assert(!html.includes('foo'))
    })

    it('should fall through from the middle case in a chain', function () {
      const html = fixtureToHTML('case', {variable2: 'e'})
      assert(html.includes('bar'))
      assert(!html.includes('foo'))
    })

    it('should fall through from the last case in a chain', function () {
      const html = fixtureToHTML('case', {variable2: 'f'})
      assert(html.includes('bar'))
      assert(!html.includes('foo'))
    })
  })

  describe('code blocks', function() {
    let html;

    beforeEach(function () {
      html = fixtureToHTML('code')
    })

    it('should run unbuffered code correctly', function () {
      assert(~html.indexOf('
'))
    })

    it('should use locals when evaluating', function () {
      html = fixtureToHTML('code', {x: 0})
      assert(~html.indexOf('
'))

      html = fixtureToHTML('code', {x: -1})
      assert(!~html.indexOf('
'))
    })

    it('should output inline buffered code', function () {
      assert(html.includes('

within another div'))
    })

    it('should output standalone buffered code', function () {
      assert(html.includes('
raw so raw'))
    })

    it('should not output unbuffered code', function () {
      assert(!html.includes('should not be output'))
    })
  })
})
<commit_msg>move most multiple-files tests to multi-lib block<commit_after>'use strict'

const assert = require('assert')
const fs = require('fs')
const jsdom = require('mocha-jsdom')
const parse5 = require('parse5-utils')
const path = require('path')
const vdomToHTML = require('vdom-to-html')
const snabbdomToHTML = require('snabbdom-to-html')

const render = require('..')

function fixtureFilename(name) {
  return path.resolve(__dirname, 'fixtures/' + name + '.jade')
}

function fixture(name) {
  return fs.readFileSync(fixtureFilename(name), 'utf8')
}

function fixtureToHTML(fixtureName, locals, options) {
  options = Object.assign({filename: fixtureFilename(fixtureName)}, options)

  const compiled = render(fixture(fixtureName), options)
  const fn = eval(`(${compiled})`)
  const root = fn.call({class: 'asdf'}, locals)
  const toHTML = options.vdom === 'snabbdom' ? snabbdomToHTML : vdomToHTML;
  const html = toHTML(root)
  parse5.parse(html, true)
  return html
}

// run rendering tests against each supported Virtual DOM library

const VDOM_LIBS = [
  'virtual-dom',
  'snabbdom',
]

for (let vdom of VDOM_LIBS) {
  const renderFixture = function(fixtureName, locals) {
    return fixtureToHTML(fixtureName, locals, {vdom})
  }

  describe(`rendering with ${vdom}`, function () {
    it('should throw a parser error with filename and line number when rendering a broken template', function () {
      const file = 'break-parser'
      const filename = fixtureFilename(file)
      const compile = function () {
        render(fixture(file), {filename})
      }
      let threw = false

      try {
        compile()
      } catch (err) {
        threw = true
        const filenameAndLineNo = new RegExp(filename.replace('/','\/') + ":2")
        assert(err.path == filename, 'err.path should be the full path to the jade file')
        assert(err.message.match(filenameAndLineNo), 'the error message should contain the full path and line number')
        assert(err.message.match(/Unexpected identifier/), 'the error message should contain the error type')
      } finally {
        assert(threw, 'an error should be thrown')
      }
    })

    it('should throw a compiler error with filename and line number when rendering a broken template', function () {
      const file = 'break-compiler'
      const filename = fixtureFilename(file)
      const compile = function () {
        render(fixture(file), {filename})
      }
      let threw = false

      try {
        compile()
      } catch (err) {
        threw = true
        const filenameAndLineNo = new RegExp(filename.replace('/','\/') + ":2")
        assert(err.path == filename, 'err.path (' + err.path + ') should be the full path to the jade file')
        assert(err.message.match(filenameAndLineNo), 'the error message should contain the full path and line number')
        assert(err.message.match(/You can only have one top-level tag!/), 'the error message should contain the error type')
      } finally {
        assert(threw, 'an error should be thrown')
      }
    })

    it('should render a template without options', function () {
      const compiled = render(fixture('attributes'))
      assert(compiled.includes('class1'))
      assert(compiled.includes('foo'))
      assert(compiled.includes('doge'))
    })

    it('should render a template', function () {
      const html = renderFixture('item', {
        item: {
          id: '1234',
          title: 'some title',
          description: 'some description',
          active: true,
        }
      })

      assert(~html.indexOf('item active'))
      assert(~html.indexOf('class="title"'))
      assert(~html.indexOf(' 15)
      assert(lines[lines.length - 1].trim() === '}')
    })

    it('should run while loops correctly', function () {
      const html = renderFixture('while')
      assert(html.match(/
/g).length === 5)
    })

    it('should insert dynamic tag names', function () {
      let html = renderFixture('dynamic-tag', {myTag: 'input'})
      assert(html.includes('<input class="llamas">'))
      html = renderFixture('dynamic-tag', {myTag: 'textarea'})
      assert(html.includes('<textarea class="llamas">'))
    })

    it('renders a simple template', function () {
      const html = renderFixture('simple')
      assert(html === '
This is text
')
    })

    it('translates basic class notation', function () {
      const html = renderFixture('class')
      assert(html.includes('div class="foo"'))
      assert(html.includes('div class="baz llamas"'))
    })

    describe('multiple files', function () {
      it('should insert included files', function () {
        const html = renderFixture('include')
        assert(html.includes('
Hello
'))
        assert(html.includes('
llamas!!!
'))
        assert(html.includes('
world
'))
      })

      it('should make included mixins available', function () {
        const html = renderFixture('include-with-mixin')
        assert(html.includes('
'))
        assert(html.includes('
insert me
'))
      })

      it('should insert extended files', function () {
        const html = renderFixture('extends')
        assert(html.includes('
'))
        assert(html.includes('capybara'))
        assert(html.includes('default content'))
      })
    })
  })
}

describe('Render', function () {
  jsdom();

  describe('multiple files', function () {
    it('should insert included literal (non-jade) files', function () {
      const html = fixtureToHTML('literal-import')
      const singleRootImport = '
test
'
      const multiRootImport = '
child 1

child 2
'
      const htmlEntities = function(str) {
        return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"')
      }
      const expectedContents =
        '
' +
          '
' +
            '<text>' + htmlEntities(singleRootImport) + '</text>' +
          '
' +
          '
' +
            '<text>' + htmlEntities('
' + multiRootImport + '
') + '</text>' +
          '
' +
        '
'
      assert(html === expectedContents)
    })
  })

  describe('attributes', function () {
    it('should add arbitrary attributes', function () {
      const html = fixtureToHTML('attributes')
      assert(html.includes('required'))
      assert(!html.includes('something'))
    })

    it('should add class attributes in array notation', function () {
      let html = fixtureToHTML('attributes')
      assert(html.includes('1 2'))
      html = fixtureToHTML('attributes', {variable: 'meow'})
      assert(html.includes('1 2 meow'))
    })

    it('should add class attributes in object notation', function () {
      let html = fixtureToHTML('attributes')
      assert(html.includes('obj1'))
      assert(!html.includes('obj2'))

      html = fixtureToHTML('attributes', {variable: 'doge'})
      assert(html.includes('obj1'))
      assert(html.includes('obj2'))
    })

    it('should combine class attributes in different notations gracefully', function () {
      let html = fixtureToHTML('attributes')
      assert(html.includes('mixed'))
      assert(html.includes('mixedArray1'))
      assert(!html.includes('mixedObj1'))

      html = fixtureToHTML('attributes', {var2: 'doge'})
      assert(html.includes('mixed'))
      assert(html.includes('mixedArray1'))
      assert(html.includes('mixedObj1'))
      assert(html.includes('doge'))
    })

    it('should render data attributes', function () {
      const html = fixtureToHTML('attributes', {variable: 'capybara'})
      assert(html.includes('data-foo-id="42"'))
      assert(html.includes('data-var="capybara"'))
    })

    it('should convert attributes to correct property names', function () {
      const html = fixtureToHTML('attributes')
      assert(html.includes('autocomplete="on"'))
      assert(html.includes('tabindex="5"'))
      assert(html.includes('for="special-attr"'))
    })
  })

  describe('case statements', function () {
    it('should not execute any cases when none match', function () {
      const html = fixtureToHTML('case')
      assert(!html.includes('foo'))
      assert(!html.includes('bar'))
    })

    it('should execute default when no others match', function () {
      const html = fixtureToHTML('case')
      assert(html.includes('llama'))
    })

    it('should execute only one match', function () {
      const html = fixtureToHTML('case', {variable: 1})
      assert(html.includes('span'))
      assert(!html.includes('input'))
      assert(!html.includes('textarea'))
    })

    it('should fall through from the first case in a chain', function () {
      const html = fixtureToHTML('case', {variable2: 'd'})
      assert(html.includes('bar'))
      assert(!html.includes('foo'))
    })

    it('should fall through from the middle case in a chain', function () {
      const html = fixtureToHTML('case', {variable2: 'e'})
      assert(html.includes('bar'))
      assert(!html.includes('foo'))
    })

    it('should fall through from the last case in a chain', function () {
      const html = fixtureToHTML('case', {variable2: 'f'})
      assert(html.includes('bar'))
      assert(!html.includes('foo'))
    })
  })

  describe('code blocks', function() {
    let html;

    beforeEach(function () {
      html = fixtureToHTML('code')
    })

    it('should run unbuffered code correctly', function () {
      assert(~html.indexOf('
'))
    })

    it('should use locals when evaluating', function () {
      html = fixtureToHTML('code', {x: 0})
      assert(~html.indexOf('
'))

      html = fixtureToHTML('code', {x: -1})
      assert(!~html.indexOf('
'))
    })

    it('should output inline buffered code', function () {
      assert(html.includes('

within another div'))
    })

    it('should output standalone buffered code', function () {
      assert(html.includes('
raw so raw'))
    })

    it('should not output unbuffered code', function () {
      assert(!html.includes('should not be output'))
    })
  })
})
<|endoftext|>


<commit_before>/*jslint node:true*/
var http = require('http');
module.exports = function(grunt) {
  "use strict";
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-qunit');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-browserify');
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    browserify: {
      dis: {
        files: {
          'dist/unmin/js/objectDiff.js': ['src/js/objectDiff.js']
        },
        options: {
          standalone: 'objectDiff'
        }
      }
    },
    qunit: {
      all: ['tests/*.html']
    },

    watch: {
      scripts: {
        files: ['src/js/*.js'],
        tasks: ['dev-js']
      },
      tests: {
        files: ['tests/unit/*.js'],
        tasks: ['qunit']
      }
    },
    jshint: {
      options: {

      },
      grunt: {
        src:['Gruntfile.js']
      },
      src: {
        src: ['src/**/*.js']
      }
    },
    concat: {
      options: {
        separator: ';'
      },
      dist: {
        src: ['src/**/*.js'],
        dest: 'dist/<%= pkg.name %>.js'
      }
    },
    clean: {
      dist: 'dist'
    },
    uglify: {
      options: {
        sourceMap: true
      },
      dynamic_mappings: {
        files: [{
          expand: true,
          cwd: 'dist/unmin',
          src: ['js/**/*.js'],
          dest: 'dist/min/',
          ext: '.js'
        }]
      }
    }
  });
  grunt.registerTask('dev-js', ['jshint','browserify', 'qunit']);
  //grunt.registerTask('dist-js', ['uglify']);
  grunt.registerTask('dist-js', ['jshint','clean','browserify','uglify','qunit']);
  grunt.registerTask('default', ['dist-js']);
};<commit_msg>remove http, not needed in this project<commit_after>/*jslint node:true*/
module.exports = function(grunt) {
  "use strict";
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-qunit');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-browserify');
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    browserify: {
      dis: {
        files: {
          'dist/unmin/js/objectDiff.js': ['src/js/objectDiff.js']
        },
        options: {
          standalone: 'objectDiff'
        }
      }
    },
    qunit: {
      all: ['tests/*.html']
    },

    watch: {
      scripts: {
        files: ['src/js/*.js'],
        tasks: ['dev-js']
      },
      tests: {
        files: ['tests/unit/*.js'],
        tasks: ['qunit']
      }
    },
    jshint: {
      options: {

      },
      grunt: {
        src:['Gruntfile.js']
      },
      src: {
        src: ['src/**/*.js']
      }
    },
    concat: {
      options: {
        separator: ';'
      },
      dist: {
        src: ['src/**/*.js'],
        dest: 'dist/<%= pkg.name %>.js'
      }
    },
    clean: {
      dist: 'dist'
    },
    uglify: {
      options: {
        sourceMap: true
      },
      dynamic_mappings: {
        files: [{
          expand: true,
          cwd: 'dist/unmin',
          src: ['js/**/*.js'],
          dest: 'dist/min/',
          ext: '.js'
        }]
      }
    }
  });
  grunt.registerTask('dev-js', ['jshint','browserify', 'qunit']);
  //grunt.registerTask('dist-js', ['uglify']);
  grunt.registerTask('dist-js', ['jshint','clean','browserify','uglify','qunit']);
  grunt.registerTask('default', ['dist-js']);
};<|endoftext|>


<commit_before>// Generated on 2014-04-17 using generator-webapp 0.4.9
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

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);

    // Configurable paths
    var config = {
        app: 'app',
        dist: 'dist'
    };

    // Define the configuration for all the tasks
    grunt.initConfig({

        // Project settings
        config: config,

        // Watches files for changes and runs tasks based on the changed files
        watch: {
            bower: {
                files: ['bower.json'],
                tasks: ['bowerInstall']
            },
            js: {
                files: ['<%= config.app %>/scripts/{,*/}*.js'],
                //tasks: ['jshint'],
                options: {
                    livereload: true
                }
            },
            jstest: {
                files: ['test/spec/{,*/}*.js'],
                tasks: ['test:watch']
            },
            gruntfile: {
                files: ['Gruntfile.js']
            },
            styles: {
                files: ['<%= config.app %>/styles/{,*/}*.css'],
                tasks: ['newer:copy:styles', 'autoprefixer']
            },
            livereload: {
                options: {
                    livereload: '<%= connect.options.livereload %>'
                },
                files: [
                    '<%= config.app %>/{,*/}*.html',
                    '.tmp/styles/{,*/}*.css',
                    '<%= config.app %>/images/{,*/}*'
                ]
            }
        },

        // The actual grunt server settings
        connect: {
            options: {
                port: 9000,
                open: true,
                livereload: 35729,
                // Change this to '0.0.0.0' to access the server from outside
                hostname: 'localhost'
            },
            livereload: {
                options: {
                    middleware: function(connect) {
                        return [
                            connect.static('.tmp'),
                            connect().use('/bower_components', connect.static('./bower_components')),
                            connect.static(config.app)
                        ];
                    }
                }
            },
            test: {
                options: {
                    open: false,
                    port: 9001,
                    middleware: function(connect) {
                        return [
                            connect.static('.tmp'),
                            connect.static('test'),
                            connect().use('/bower_components', connect.static('./bower_components')),
                            connect.static(config.app)
                        ];
                    }
                }
            },
            dist: {
                options: {
                    base: '<%= config.dist %>',
                    livereload: false
                }
            }
        },

        // Empties folders to start fresh
        clean: {
            dist: {
                files: [{
                    dot: true,
                    src: [
                        '.tmp',
                        '<%= config.dist %>/*',
                        '!<%= config.dist %>/.git*'
                    ]
                }]
            },
            server: '.tmp'
        },

        // Make sure code styles are up to par and there are no obvious mistakes
        jshint: {
            options: {
                jshintrc: '.jshintrc',
                reporter: require('jshint-stylish')
            },
            all: [
                'Gruntfile.js',
                '<%= config.app %>/scripts/{,*/}*.js',
                '!<%= config.app %>/scripts/vendor/*',
                'test/spec/{,*/}*.js'
            ]
        },

        // Mocha testing framework configuration options
        mocha: {
            all: {
                options: {
                    run: true,
                    urls: ['http://<%= connect.test.options.hostname %>:<%= connect.test.options.port %>/index.html']
                }
            }
        },

        // Add vendor prefixed styles
        autoprefixer: {
            options: {
                browsers: ['last 1 version']
            },
            dist: {
                files: [{
                    expand: true,
                    cwd: '.tmp/styles/',
                    src: '{,*/}*.css',
                    dest: '.tmp/styles/'
                }]
            }
        },

        // Automatically inject Bower components into the HTML file
        bowerInstall: {
            app: {
                src: ['<%= config.app %>/index.html'],
                exclude: ['bower_components/bootstrap/dist/js/bootstrap.js']
            }
        },

        // Renames files for browser caching purposes
        rev: {
            dist: {
                files: {
                    src: [
                        '<%= config.dist %>/scripts/{,*/}*.js',
                        '<%= config.dist %>/styles/{,*/}*.css',
                        '<%= config.dist %>/images/{,*/}*.*',
                        '<%= config.dist %>/styles/fonts/{,*/}*.*',
                        '<%= config.dist %>/*.{ico,png}'
                    ]
                }
            }
        },

        // Reads HTML for usemin blocks to enable smart builds that automatically
        // concat, minify and revision files. Creates configurations in memory so
        // additional tasks can operate on them
        useminPrepare: {
            options: {
                dest: '<%= config.dist %>'
            },
            html: '<%= config.app %>/index.html'
        },

        // Performs rewrites based on rev and the useminPrepare configuration
        usemin: {
            options: {
                assetsDirs: ['<%= config.dist %>', '<%= config.dist %>/images']
            },
            html: ['<%= config.dist %>/{,*/}*.html'],
            css: ['<%= config.dist %>/styles/{,*/}*.css']
        },

        // The following *-min tasks produce minified files in the dist folder
        imagemin: {
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= config.app %>/images',
                    src: '{,*/}*.{gif,jpeg,jpg,png}',
                    dest: '<%= config.dist %>/images'
                }]
            }
        },

        svgmin: {
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= config.app %>/images',
                    src: '{,*/}*.svg',
                    dest: '<%= config.dist %>/images'
                }]
            }
        },

        htmlmin: {
            dist: {
                options: {
                    collapseBooleanAttributes: true,
                    collapseWhitespace: true,
                    removeAttributeQuotes: true,
                    removeCommentsFromCDATA: true,
                    removeEmptyAttributes: true,
                    removeOptionalTags: true,
                    removeRedundantAttributes: true,
                    useShortDoctype: true
                },
                files: [{
                    expand: true,
                    cwd: '<%= config.dist %>',
                    src: '{,*/}*.html',
                    dest: '<%= config.dist %>'
                }]
            }
        },

        // By default, your `index.html`'s <!-- Usemin block --> will take care of
        // minification. These next options are pre-configured if you do not wish
        // to use the Usemin blocks.
        // cssmin: {
        //     dist: {
        //         files: {
        //             '<%= config.dist %>/styles/main.css': [
        //                 '.tmp/styles/{,*/}*.css',
        //                 '<%= config.app %>/styles/{,*/}*.css'
        //             ]
        //         }
        //     }
        // },
        // uglify: {
        //     dist: {
        //         files: {
        //             '<%= config.dist %>/scripts/scripts.js': [
        //                 '<%= config.dist %>/scripts/scripts.js'
        //             ]
        //         }
        //     }
        // },
        // concat: {
        //     dist: {}
        // },

        // Copies remaining files to places other tasks can use
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= config.app %>',
                    dest: '<%= config.dist %>',
                    src: [
                        '*.{ico,png,txt}',
                        '.htaccess',
                        'images/{,*/}*.webp',
                        '{,*/}*.html',
                        'styles/fonts/{,*/}*.*'
                    ]
                }, {
                    expand: true,
                    dot: true,
                    cwd: 'bower_components/bootstrap/dist',
                    src: ['fonts/*.*'],
                    dest: '<%= config.dist %>'
                }]
            },
            styles: {
                expand: true,
                dot: true,
                cwd: '<%= config.app %>/styles',
                dest: '.tmp/styles/',
                src: '{,*/}*.css'
            }
        },

        // Run some tasks in parallel to speed up build process
        concurrent: {
            server: [
                'copy:styles'
            ],
            test: [
                'copy:styles'
            ],
            dist: [
                'copy:styles',
                'imagemin',
                'svgmin'
            ]
        }
    });

    grunt.registerTask('serve', function (target) {
        if (target === 'dist') {
            return grunt.task.run(['build', 'connect:dist:keepalive']);
        }

        grunt.task.run([
            'clean:server',
            'concurrent:server',
            'autoprefixer',
            'connect:livereload',
            'watch'
        ]);
    });

    grunt.registerTask('server', function (target) {
        grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
        grunt.task.run([target ? ('serve:' + target) : 'serve']);
    });

    grunt.registerTask('test', function (target) {
        if (target !== 'watch') {
            grunt.task.run([
                'clean:server',
                'concurrent:test',
                'autoprefixer'
            ]);
        }

        grunt.task.run([
            'connect:test',
            'mocha'
        ]);
    });

    grunt.registerTask('build', [
        'clean:dist',
        'useminPrepare',
        'concurrent:dist',
        'autoprefixer',
        'concat',
        'cssmin',
        'uglify',
        'copy:dist',
        'rev',
        'usemin',
        'htmlmin'
    ]);

    grunt.registerTask('default', [
        'newer:jshint',
        'test',
        'build'
    ]);
};
<commit_msg>process all html files with grunt<commit_after>// Generated on 2014-04-17 using generator-webapp 0.4.9
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

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);

    // Configurable paths
    var config = {
        app: 'app',
        dist: 'dist'
    };

    // Define the configuration for all the tasks
    grunt.initConfig({

        // Project settings
        config: config,

        // Watches files for changes and runs tasks based on the changed files
        watch: {
            bower: {
                files: ['bower.json'],
                tasks: ['bowerInstall']
            },
            js: {
                files: ['<%= config.app %>/scripts/{,*/}*.js'],
                //tasks: ['jshint'],
                options: {
                    livereload: true
                }
            },
            jstest: {
                files: ['test/spec/{,*/}*.js'],
                tasks: ['test:watch']
            },
            gruntfile: {
                files: ['Gruntfile.js']
            },
            styles: {
                files: ['<%= config.app %>/styles/{,*/}*.css'],
                tasks: ['newer:copy:styles', 'autoprefixer']
            },
            livereload: {
                options: {
                    livereload: '<%= connect.options.livereload %>'
                },
                files: [
                    '<%= config.app %>/{,*/}*.html',
                    '.tmp/styles/{,*/}*.css',
                    '<%= config.app %>/images/{,*/}*'
                ]
            }
        },

        // The actual grunt server settings
        connect: {
            options: {
                port: 9000,
                open: true,
                livereload: 35729,
                // Change this to '0.0.0.0' to access the server from outside
                hostname: 'localhost'
            },
            livereload: {
                options: {
                    middleware: function(connect) {
                        return [
                            connect.static('.tmp'),
                            connect().use('/bower_components', connect.static('./bower_components')),
                            connect.static(config.app)
                        ];
                    }
                }
            },
            test: {
                options: {
                    open: false,
                    port: 9001,
                    middleware: function(connect) {
                        return [
                            connect.static('.tmp'),
                            connect.static('test'),
                            connect().use('/bower_components', connect.static('./bower_components')),
                            connect.static(config.app)
                        ];
                    }
                }
            },
            dist: {
                options: {
                    base: '<%= config.dist %>',
                    livereload: false
                }
            }
        },

        // Empties folders to start fresh
        clean: {
            dist: {
                files: [{
                    dot: true,
                    src: [
                        '.tmp',
                        '<%= config.dist %>/*',
                        '!<%= config.dist %>/.git*'
                    ]
                }]
            },
            server: '.tmp'
        },

        // Make sure code styles are up to par and there are no obvious mistakes
        jshint: {
            options: {
                jshintrc: '.jshintrc',
                reporter: require('jshint-stylish')
            },
            all: [
                'Gruntfile.js',
                '<%= config.app %>/scripts/{,*/}*.js',
                '!<%= config.app %>/scripts/vendor/*',
                'test/spec/{,*/}*.js'
            ]
        },

        // Mocha testing framework configuration options
        mocha: {
            all: {
                options: {
                    run: true,
                    urls: ['http://<%= connect.test.options.hostname %>:<%= connect.test.options.port %>/index.html']
                }
            }
        },

        // Add vendor prefixed styles
        autoprefixer: {
            options: {
                browsers: ['last 1 version']
            },
            dist: {
                files: [{
                    expand: true,
                    cwd: '.tmp/styles/',
                    src: '{,*/}*.css',
                    dest: '.tmp/styles/'
                }]
            }
        },

        // Automatically inject Bower components into the HTML file
        bowerInstall: {
            app: {
                src: ['<%= config.app %>/index.html'],
                exclude: ['bower_components/bootstrap/dist/js/bootstrap.js']
            }
        },

        // Renames files for browser caching purposes
        rev: {
            dist: {
                files: {
                    src: [
                        '<%= config.dist %>/scripts/{,*/}*.js',
                        '<%= config.dist %>/styles/{,*/}*.css',
                        '<%= config.dist %>/images/{,*/}*.*',
                        '<%= config.dist %>/styles/fonts/{,*/}*.*',
                        '<%= config.dist %>/*.{ico,png}'
                    ]
                }
            }
        },

        // Reads HTML for usemin blocks to enable smart builds that automatically
        // concat, minify and revision files. Creates configurations in memory so
        // additional tasks can operate on them
        useminPrepare: {
            options: {
                dest: '<%= config.dist %>'
            },
            html: '<%= config.app %>/*.html'
        },

        // Performs rewrites based on rev and the useminPrepare configuration
        usemin: {
            options: {
                assetsDirs: ['<%= config.dist %>', '<%= config.dist %>/images']
            },
            html: ['<%= config.dist %>/{,*/}*.html'],
            css: ['<%= config.dist %>/styles/{,*/}*.css']
        },

        // The following *-min tasks produce minified files in the dist folder
        imagemin: {
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= config.app %>/images',
                    src: '{,*/}*.{gif,jpeg,jpg,png}',
                    dest: '<%= config.dist %>/images'
                }]
            }
        },

        svgmin: {
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= config.app %>/images',
                    src: '{,*/}*.svg',
                    dest: '<%= config.dist %>/images'
                }]
            }
        },

        htmlmin: {
            dist: {
                options: {
                    collapseBooleanAttributes: true,
                    collapseWhitespace: true,
                    removeAttributeQuotes: true,
                    removeCommentsFromCDATA: true,
                    removeEmptyAttributes: true,
                    removeOptionalTags: true,
                    removeRedundantAttributes: true,
                    useShortDoctype: true
                },
                files: [{
                    expand: true,
                    cwd: '<%= config.dist %>',
                    src: '{,*/}*.html',
                    dest: '<%= config.dist %>'
                }]
            }
        },

        // By default, your `index.html`'s <!-- Usemin block --> will take care of
        // minification. These next options are pre-configured if you do not wish
        // to use the Usemin blocks.
        // cssmin: {
        //     dist: {
        //         files: {
        //             '<%= config.dist %>/styles/main.css': [
        //                 '.tmp/styles/{,*/}*.css',
        //                 '<%= config.app %>/styles/{,*/}*.css'
        //             ]
        //         }
        //     }
        // },
        // uglify: {
        //     dist: {
        //         files: {
        //             '<%= config.dist %>/scripts/scripts.js': [
        //                 '<%= config.dist %>/scripts/scripts.js'
        //             ]
        //         }
        //     }
        // },
        // concat: {
        //     dist: {}
        // },

        // Copies remaining files to places other tasks can use
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= config.app %>',
                    dest: '<%= config.dist %>',
                    src: [
                        '*.{ico,png,txt}',
                        '.htaccess',
                        'images/{,*/}*.webp',
                        '{,*/}*.html',
                        'styles/fonts/{,*/}*.*'
                    ]
                }, {
                    expand: true,
                    dot: true,
                    cwd: 'bower_components/bootstrap/dist',
                    src: ['fonts/*.*'],
                    dest: '<%= config.dist %>'
                }]
            },
            styles: {
                expand: true,
                dot: true,
                cwd: '<%= config.app %>/styles',
                dest: '.tmp/styles/',
                src: '{,*/}*.css'
            }
        },

        // Run some tasks in parallel to speed up build process
        concurrent: {
            server: [
                'copy:styles'
            ],
            test: [
                'copy:styles'
            ],
            dist: [
                'copy:styles',
                'imagemin',
                'svgmin'
            ]
        }
    });

    grunt.registerTask('serve', function (target) {
        if (target === 'dist') {
            return grunt.task.run(['build', 'connect:dist:keepalive']);
        }

        grunt.task.run([
            'clean:server',
            'concurrent:server',
            'autoprefixer',
            'connect:livereload',
            'watch'
        ]);
    });

    grunt.registerTask('server', function (target) {
        grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
        grunt.task.run([target ? ('serve:' + target) : 'serve']);
    });

    grunt.registerTask('test', function (target) {
        if (target !== 'watch') {
            grunt.task.run([
                'clean:server',
                'concurrent:test',
                'autoprefixer'
            ]);
        }

        grunt.task.run([
            'connect:test',
            'mocha'
        ]);
    });

    grunt.registerTask('build', [
        'clean:dist',
        'useminPrepare',
        'concurrent:dist',
        'autoprefixer',
        'concat',
        'cssmin',
        'uglify',
        'copy:dist',
        'rev',
        'usemin',
        'htmlmin'
    ]);

    grunt.registerTask('default', [
        'newer:jshint',
        'test',
        'build'
    ]);
};
<|endoftext|>


<commit_before>import { interface, implements } from 'sweet-interfaces';
import { Functor } from './functor';
import { Contravariant } from './contravariant';
import { Category } from './category';

const identity = Function[Category.id]();

interface Profunctor extends Functor, Contravariant {
  // promap :: Profunctor p => p b c ~> (a -> b, c -> d) -> p a d
  promap(f, g) {
    return this[Profunctor.lmap](f)[Profunctor.rmap](g);
  }

  // lmap :: Profunctor p => p b c ~> (a -> b) -> p a c
  lmap(f) {
    return this[Profunctor.promap](f, identity);
  }

  // rmap :: Profunctor p => p a b ~> (b -> c) -> p a c
  rmap(f) {
    return this[Profunctor.promap](identity, f);
  }

  // arr :: (Category p, Profunctor p) => (a -> b) -> p a b
  static arr(f) {
    return f[Profunctor.rmap](identity);
  }

  [Functor.map](f) {
    return this[Profunctor.promap](identity, f);
  }
  [Contravariant.contramap](f) {
    return this[Profunctor.promap](f, identity);
  }
}
// TODO: change to default export once sweet-js/sweet-core/issues/620 ships
export { Profunctor };

Function.prototype[Profunctor.promap] = function promap(f, g) {
  return x => g(this(f(x)));
};
Function.prototype[Profunctor.lmap] = Function.prototype[Contravariant.contramap];
Function.prototype[Profunctor.rmap] = Function.prototype[Functor.map];

Function implements Profunctor;
<commit_msg>Remove erroneous Profunctor-Contravariant relation<commit_after>import { interface, implements } from 'sweet-interfaces';
import { Functor } from './functor';
import { Category } from './category';

const identity = Function[Category.id]();

interface Profunctor extends Functor {
  // promap :: Profunctor p => p b c ~> (a -> b, c -> d) -> p a d
  promap(f, g) {
    return this[Profunctor.lmap](f)[Profunctor.rmap](g);
  }

  // lmap :: Profunctor p => p b c ~> (a -> b) -> p a c
  lmap(f) {
    return this[Profunctor.promap](f, identity);
  }

  // rmap :: Profunctor p => p a b ~> (b -> c) -> p a c
  rmap(f) {
    return this[Profunctor.promap](identity, f);
  }

  // arr :: (Category p, Profunctor p) => (a -> b) -> p a b
  static arr(f) {
    return f[Profunctor.rmap](identity);
  }

  [Functor.map](f) {
    return this[Profunctor.promap](identity, f);
  }
}
// TODO: change to default export once sweet-js/sweet-core/issues/620 ships
export { Profunctor };

Function.prototype[Profunctor.promap] = function promap(f, g) {
  return x => g(this(f(x)));
};
Function.prototype[Profunctor.lmap] = Function.prototype[Contravariant.contramap];
Function.prototype[Profunctor.rmap] = Function.prototype[Functor.map];

Function implements Profunctor;
<|endoftext|>