<commit_before>var assert = require('assert'),
    fs = require('fs'),
    path = require('path'),
    read = fs.readFileSync,
    sass = require('../sass'),
    fixture = path.join.bind(null, __dirname, 'fixtures'),
    resolveFixture = path.resolve.bind(null, __dirname, 'fixtures');

describe('api (deprecated)', function() {
  describe('.render(src, fn)', function() {
    it('should compile sass to css', function(done) {
      var src = read(fixture('simple/index.scss'), 'utf8');
      var expected = read(fixture('simple/expected.css'), 'utf8').trim();

      sass.render(src, function(err, css) {
        assert(!err);
        assert.equal(css.trim(), expected.replace(/\r\n/g, '\n'));
        done();
      });
    });

    it('should throw error for bad input', function(done) {
      sass.render('#navbar width 80%;', function(err) {
        assert(err);
        done();
      });
    });
  });

  describe('.renderSync(src)', function() {
    it('should compile sass to css', function(done) {
      var src = read(fixture('simple/index.scss'), 'utf8');
      var expected = read(fixture('simple/expected.css'), 'utf8').trim();

      assert.equal(sass.renderSync(src).trim(), expected.replace(/\r\n/g, '\n'));
      done();
    });

    it('should throw error for bad input', function(done) {
      assert.throws(function() {
        sass.renderSync('#navbar width 80%;');
      });

      done();
    });
  });
});

describe('api', function() {
  describe('.render(options)', function() {
    it('should compile sass to css', function(done) {
      var src = read(fixture('simple/index.scss'), 'utf8');
      var expected = read(fixture('simple/expected.css'), 'utf8').trim();

      sass.render({
        data: src,
        success: function(css) {
          assert.equal(css.trim(), expected.replace(/\r\n/g, '\n'));
          done();
        }
      });
    });

    it('should throw error status 1 for bad input', function(done) {
      sass.render({
        data: '#navbar width 80%;',
        error: function(err, status) {
          assert(err);
          assert.equal(status, 1);
          done();
        }
      });
    });

    it('should compile with include paths', function(done) {
      var src = read(fixture('include-path/index.scss'), 'utf8');
      var expected = read(fixture('include-path/expected.css'), 'utf8').trim();

      sass.render({
        data: src,
        includePaths: [
          fixture('include-path/functions'),
          fixture('include-path/lib')
        ],
        success: function(css) {
          assert.equal(css.trim(), expected.replace(/\r\n/g, '\n'));
          done();
        }
      });
    });

    it('should compile with image path', function(done) {
      var src = read(fixture('image-path/index.scss'), 'utf8');
      var expected = read(fixture('image-path/expected.css'), 'utf8').trim();

      sass.render({
        data: src,
        imagePath: '/path/to/images',
        success: function(css) {
          assert.equal(css.trim(), expected.replace(/\r\n/g, '\n'));
          done();
        }
      });
    });

    it('should throw error with non-string image path', function(done) {
      var src = read(fixture('image-path/index.scss'), 'utf8');

      assert.throws(function() {
        sass.render({
          data: src,
          imagePath: ['/path/to/images']
        });
      });

      done();
    });

    it('should render with --precision option', function(done) {
      var src = read(fixture('precision/index.scss'), 'utf8');
      var expected = read(fixture('precision/expected.css'), 'utf8').trim();

      sass.render({
        data: src,
        precision: 10,
        success: function(css) {
          assert.equal(css.trim(), expected.replace(/\r\n/g, '\n'));
          done();
        }
      });
    });

    it('should compile with stats', function(done) {
      var src = fixture('precision/index.scss');
      var stats = {};

      sass.render({
        file: src,
        stats: stats,
        sourceMap: true,
        success: function() {
          assert.equal(stats.entry, src);
          done();
        }
      });
    });
  });

  describe('.renderSync(options)', function() {
    it('should compile with renderSync', function(done) {
      var src = read(fixture('simple/index.scss'), 'utf8');
      var expected = read(fixture('simple/expected.css'), 'utf8').trim();

      assert.equal(sass.renderSync({ data: src }).trim(), expected.replace(/\r\n/g, '\n'));
      done();
    });

    it('should throw error for bad input', function(done) {
      assert.throws(function() {
        sass.renderSync({ data: '#navbar width 80%;' });
      });

      done();
    });
  });

  describe('.renderFile(options)', function() {
    it('should compile with renderFile', function(done) {
      var src = read(fixture('simple/index.scss'), 'utf8');
      var dest = fixture('simple/build.css');
      var expected = read(fixture('simple/expected.css'), 'utf8').trim();

      sass.renderFile({
        data: src,
        outFile: dest,
        success: function() {
          assert.equal(read(dest, 'utf8').trim(), expected.replace(/\r\n/g, '\n'));
          fs.unlinkSync(dest);
          done();
        }
      });
    });

    it('should save source map to default name', function(done) {
      var src = fixture('source-map/index.scss');
      var dest = fixture('source-map/build.css');
      var name = 'build.css.map';

      sass.renderFile({
        file: src,
        outFile: dest,
        sourceMap: true,
        success: function(file, map) {
          assert.equal(path.basename(map), name);
          assert(read(dest, 'utf8').indexOf('sourceMappingURL=' + name) !== -1);
          fs.unlinkSync(map);
          fs.unlinkSync(dest);
          done();
        }
      });
    });

    it('should save source map to specified name', function(done) {
      var src = fixture('source-map/index.scss');
      var dest = fixture('source-map/build.css');
      var name = 'foo.css.map';

      sass.renderFile({
        file: src,
        outFile: dest,
        sourceMap: name,
        success: function(file, map) {
          assert.equal(path.basename(map), name);
          assert(read(dest, 'utf8').indexOf('sourceMappingURL=' + name) !== -1);
          fs.unlinkSync(map);
          fs.unlinkSync(dest);
          done();
        }
      });
    });

    it('should save source paths relative to the source map file', function(done) {
      var src = fixture('include-files/index.scss');
      var dest = fixture('include-files/build.css');
      var obj;

      sass.renderFile({
        file: src,
        outFile: dest,
        sourceMap: true,
        success: function(file, map) {
          obj = JSON.parse(read(map, 'utf8'));
          assert.equal(obj.sources[0], 'index.scss');
          assert.equal(obj.sources[1], 'foo.scss');
          assert.equal(obj.sources[2], 'bar.scss');
          fs.unlinkSync(map);
          fs.unlinkSync(dest);
          done();
        }
      });
    });
  });

  describe('.render({ stats: {} })', function() {
    var start = Date.now();
    var stats = {};

    before(function (done) {
      sass.render({
        file: fixture('include-files/index.scss'),
        stats: stats,
        success: function () {
          done();
        },
        error: function (err) {
          assert(!err);
          done();
        }
      });
    });

    it('should provide a start timestamp', function(done) {
      assert(typeof stats.start === 'number');
      assert(stats.start >= start);
      done();
    });

    it('should provide an end timestamp', function(done) {
      assert(typeof stats.end === 'number');
      assert(stats.end >= stats.start);
      done();
    });

    it('should provide a duration', function(done) {
      assert(typeof stats.duration === 'number');
      assert.equal(stats.end - stats.start, stats.duration);
      done();
    });

    it('should contain the given entry file', function(done) {
      assert.equal(stats.entry, fixture('include-files/index.scss'));
      done();
    });

    it('should contain an array of all included files', function(done) {
      var expected = [
        fixture('include-files/bar.scss').replace(/\\/g, '/'),
        fixture('include-files/foo.scss').replace(/\\/g, '/'),
        fixture('include-files/index.scss').replace(/\\/g, '/')
      ];

      assert.equal(stats.includedFiles[0], expected[0]);
      assert.equal(stats.includedFiles[1], expected[1]);
      assert.equal(stats.includedFiles[2], expected[2]);
      done();
    });

    it('should contain array with the entry if there are no import statements', function(done) {
      var expected = fixture('simple/index.scss').replace(/\\/g, '/');

      sass.render({
        file: fixture('simple/index.scss'),
        stats: stats,
        success: function () {
          assert.deepEqual(stats.includedFiles, [expected]);
          done();
        }
      });
    });

    it('should state `data` as entry file', function(done) {
      sass.render({
        data: read(fixture('simple/index.scss'), 'utf8'),
        stats: stats,
        success: function () {
          assert.equal(stats.entry, 'data');
          done();
        }
      });
    });

    it('should contain an empty array as includedFiles', function(done) {
      sass.render({
        data: read(fixture('simple/index.scss'), 'utf8'),
        stats: stats,
        success: function () {
          assert.deepEqual(stats.includedFiles, []);
          done();
        }
      });
    });
  });

  describe('.renderSync({ stats: {} })', function() {
    var start = Date.now();
    var stats = {};

    before(function () {
      sass.renderSync({
        file: fixture('include-files/index.scss'),
        stats: stats
      });
    });

    it('should provide a start timestamp', function(done) {
      assert(typeof stats.start === 'number');
      assert(stats.start >= start);
      done();
    });

    it('should provide an end timestamp', function(done) {
      assert(typeof stats.end === 'number');
      assert(stats.end >= stats.start);
      done();
    });

    it('should provide a duration', function(done) {
      assert(typeof stats.duration === 'number');
      assert.equal(stats.end - stats.start, stats.duration);
      done();
    });

    it('should contain the given entry file', function(done) {
      assert.equal(stats.entry, resolveFixture('include-files/index.scss'));
      done();
    });

    it('should contain an array of all included files', function(done) {
      var expected = [
        fixture('include-files/bar.scss').replace(/\\/g, '/'),
        fixture('include-files/foo.scss').replace(/\\/g, '/'),
        fixture('include-files/index.scss').replace(/\\/g, '/')
      ];

      assert.equal(stats.includedFiles[0], expected[0]);
      assert.equal(stats.includedFiles[1], expected[1]);
      assert.equal(stats.includedFiles[2], expected[2]);
      done();
    });

    it('should contain array with the entry if there are no import statements', function(done) {
      var expected = fixture('simple/index.scss').replace(/\\/g, '/');
      sass.renderSync({
        file: fixture('simple/index.scss'),
        stats: stats
      });

      assert.deepEqual(stats.includedFiles, [expected]);
      done();
    });

    it('should state `data` as entry file', function(done) {
      sass.renderSync({
        data: read(fixture('simple/index.scss'), 'utf8'),
        stats: stats
      });

      assert.equal(stats.entry, 'data');
      done();
    });

    it('should contain an empty array as includedFiles', function(done) {
      sass.renderSync({
        data: read(fixture('simple/index.scss'), 'utf8'),
        stats: stats
      });

      assert.deepEqual(stats.includedFiles, []);
      done();
    });
  });
});
<commit_msg>Test: Adds back stats test.<commit_after>var assert = require('assert'),
    fs = require('fs'),
    path = require('path'),
    read = fs.readFileSync,
    sass = require('../sass'),
    fixture = path.join.bind(null, __dirname, 'fixtures'),
    resolveFixture = path.resolve.bind(null, __dirname, 'fixtures');

describe('api (deprecated)', function() {
  describe('.render(src, fn)', function() {
    it('should compile sass to css', function(done) {
      var src = read(fixture('simple/index.scss'), 'utf8');
      var expected = read(fixture('simple/expected.css'), 'utf8').trim();

      sass.render(src, function(err, css) {
        assert(!err);
        assert.equal(css.trim(), expected.replace(/\r\n/g, '\n'));
        done();
      });
    });

    it('should throw error for bad input', function(done) {
      sass.render('#navbar width 80%;', function(err) {
        assert(err);
        done();
      });
    });
  });

  describe('.renderSync(src)', function() {
    it('should compile sass to css', function(done) {
      var src = read(fixture('simple/index.scss'), 'utf8');
      var expected = read(fixture('simple/expected.css'), 'utf8').trim();

      assert.equal(sass.renderSync(src).trim(), expected.replace(/\r\n/g, '\n'));
      done();
    });

    it('should throw error for bad input', function(done) {
      assert.throws(function() {
        sass.renderSync('#navbar width 80%;');
      });

      done();
    });
  });
});

describe('api', function() {
  describe('.render(options)', function() {
    it('should compile sass to css', function(done) {
      var src = read(fixture('simple/index.scss'), 'utf8');
      var expected = read(fixture('simple/expected.css'), 'utf8').trim();

      sass.render({
        data: src,
        success: function(css) {
          assert.equal(css.trim(), expected.replace(/\r\n/g, '\n'));
          done();
        }
      });
    });

    it('should throw error status 1 for bad input', function(done) {
      sass.render({
        data: '#navbar width 80%;',
        error: function(err, status) {
          assert(err);
          assert.equal(status, 1);
          done();
        }
      });
    });

    it('should compile with include paths', function(done) {
      var src = read(fixture('include-path/index.scss'), 'utf8');
      var expected = read(fixture('include-path/expected.css'), 'utf8').trim();

      sass.render({
        data: src,
        includePaths: [
          fixture('include-path/functions'),
          fixture('include-path/lib')
        ],
        success: function(css) {
          assert.equal(css.trim(), expected.replace(/\r\n/g, '\n'));
          done();
        }
      });
    });

    it('should compile with image path', function(done) {
      var src = read(fixture('image-path/index.scss'), 'utf8');
      var expected = read(fixture('image-path/expected.css'), 'utf8').trim();

      sass.render({
        data: src,
        imagePath: '/path/to/images',
        success: function(css) {
          assert.equal(css.trim(), expected.replace(/\r\n/g, '\n'));
          done();
        }
      });
    });

    it('should throw error with non-string image path', function(done) {
      var src = read(fixture('image-path/index.scss'), 'utf8');

      assert.throws(function() {
        sass.render({
          data: src,
          imagePath: ['/path/to/images']
        });
      });

      done();
    });

    it('should render with --precision option', function(done) {
      var src = read(fixture('precision/index.scss'), 'utf8');
      var expected = read(fixture('precision/expected.css'), 'utf8').trim();

      sass.render({
        data: src,
        precision: 10,
        success: function(css) {
          assert.equal(css.trim(), expected.replace(/\r\n/g, '\n'));
          done();
        }
      });
    });

    it('should compile with stats', function(done) {
      var src = fixture('precision/index.scss');
      var stats = {};

      sass.render({
        file: src,
        stats: stats,
        sourceMap: true,
        success: function() {
          assert.equal(stats.entry, src);
          done();
        }
      });
    });
  });

  describe('.renderSync(options)', function() {
    it('should compile with renderSync', function(done) {
      var src = read(fixture('simple/index.scss'), 'utf8');
      var expected = read(fixture('simple/expected.css'), 'utf8').trim();

      assert.equal(sass.renderSync({ data: src }).trim(), expected.replace(/\r\n/g, '\n'));
      done();
    });

    it('should throw error for bad input', function(done) {
      assert.throws(function() {
        sass.renderSync({ data: '#navbar width 80%;' });
      });

      done();
    });
  });

  describe('.renderFile(options)', function() {
    it('should compile with renderFile', function(done) {
      var src = read(fixture('simple/index.scss'), 'utf8');
      var dest = fixture('simple/build.css');
      var expected = read(fixture('simple/expected.css'), 'utf8').trim();

      sass.renderFile({
        data: src,
        outFile: dest,
        success: function() {
          assert.equal(read(dest, 'utf8').trim(), expected.replace(/\r\n/g, '\n'));
          fs.unlinkSync(dest);
          done();
        }
      });
    });

    it('should save source map to default name', function(done) {
      var src = fixture('source-map/index.scss');
      var dest = fixture('source-map/build.css');
      var name = 'build.css.map';

      sass.renderFile({
        file: src,
        outFile: dest,
        sourceMap: true,
        success: function(file, map) {
          assert.equal(path.basename(map), name);
          assert(read(dest, 'utf8').indexOf('sourceMappingURL=' + name) !== -1);
          fs.unlinkSync(map);
          fs.unlinkSync(dest);
          done();
        }
      });
    });

    it('should save source map to specified name', function(done) {
      var src = fixture('source-map/index.scss');
      var dest = fixture('source-map/build.css');
      var name = 'foo.css.map';

      sass.renderFile({
        file: src,
        outFile: dest,
        sourceMap: name,
        success: function(file, map) {
          assert.equal(path.basename(map), name);
          assert(read(dest, 'utf8').indexOf('sourceMappingURL=' + name) !== -1);
          fs.unlinkSync(map);
          fs.unlinkSync(dest);
          done();
        }
      });
    });

    it('should save source paths relative to the source map file', function(done) {
      var src = fixture('include-files/index.scss');
      var dest = fixture('include-files/build.css');
      var obj;

      sass.renderFile({
        file: src,
        outFile: dest,
        sourceMap: true,
        success: function(file, map) {
          obj = JSON.parse(read(map, 'utf8'));
          assert.equal(obj.sources[0], 'index.scss');
          assert.equal(obj.sources[1], 'foo.scss');
          assert.equal(obj.sources[2], 'bar.scss');
          fs.unlinkSync(map);
          fs.unlinkSync(dest);
          done();
        }
      });
    });
  });

  describe('.render({ stats: {} })', function() {
    var start = Date.now();
    var stats = {};

    before(function(done) {
      sass.render({
        file: fixture('include-files/index.scss'),
        stats: stats,
        success: function() {
          done();
        },
        error: function(err) {
          assert(!err);
          done();
        }
      });
    });

    it('should provide a start timestamp', function(done) {
      assert(typeof stats.start === 'number');
      assert(stats.start >= start);
      done();
    });

    it('should provide an end timestamp', function(done) {
      assert(typeof stats.end === 'number');
      assert(stats.end >= stats.start);
      done();
    });

    it('should provide a duration', function(done) {
      assert(typeof stats.duration === 'number');
      assert.equal(stats.end - stats.start, stats.duration);
      done();
    });

    it('should contain the given entry file', function(done) {
      assert.equal(stats.entry, fixture('include-files/index.scss'));
      done();
    });

    it('should contain an array of all included files', function(done) {
      var expected = [
        fixture('include-files/bar.scss').replace(/\\/g, '/'),
        fixture('include-files/foo.scss').replace(/\\/g, '/'),
        fixture('include-files/index.scss').replace(/\\/g, '/')
      ];

      assert.equal(stats.includedFiles[0], expected[0]);
      assert.equal(stats.includedFiles[1], expected[1]);
      assert.equal(stats.includedFiles[2], expected[2]);
      done();
    });

    it('should contain array with the entry if there are no import statements', function(done) {
      var expected = fixture('simple/index.scss').replace(/\\/g, '/');

      sass.render({
        file: fixture('simple/index.scss'),
        stats: stats,
        success: function() {
          assert.deepEqual(stats.includedFiles, [expected]);
          done();
        }
      });
    });

    it('should state `data` as entry file', function(done) {
      sass.render({
        data: read(fixture('simple/index.scss'), 'utf8'),
        stats: stats,
        success: function() {
          assert.equal(stats.entry, 'data');
          done();
        }
      });
    });

    it('should contain an empty array as includedFiles', function(done) {
      sass.render({
        data: read(fixture('simple/index.scss'), 'utf8'),
        stats: stats,
        success: function() {
          assert.deepEqual(stats.includedFiles, []);
          done();
        }
      });
    });
  });

  describe('.renderSync({ stats: {} })', function() {
    var start = Date.now();
    var stats = {};

    before(function() {
      sass.renderSync({
        file: fixture('include-files/index.scss'),
        stats: stats
      });
    });

    it('should provide a start timestamp', function(done) {
      assert(typeof stats.start === 'number');
      assert(stats.start >= start);
      done();
    });

    it('should provide an end timestamp', function(done) {
      assert(typeof stats.end === 'number');
      assert(stats.end >= stats.start);
      done();
    });

    it('should provide a duration', function(done) {
      assert(typeof stats.duration === 'number');
      assert.equal(stats.end - stats.start, stats.duration);
      done();
    });

    it('should contain the given entry file', function(done) {
      assert.equal(stats.entry, resolveFixture('include-files/index.scss'));
      done();
    });

    it('should contain an array of all included files', function(done) {
      var expected = [
        fixture('include-files/bar.scss').replace(/\\/g, '/'),
        fixture('include-files/foo.scss').replace(/\\/g, '/'),
        fixture('include-files/index.scss').replace(/\\/g, '/')
      ];

      assert.equal(stats.includedFiles[0], expected[0]);
      assert.equal(stats.includedFiles[1], expected[1]);
      assert.equal(stats.includedFiles[2], expected[2]);
      done();
    });

    it('should contain array with the entry if there are no import statements', function(done) {
      var expected = fixture('simple/index.scss').replace(/\\/g, '/');
      sass.renderSync({
        file: fixture('simple/index.scss'),
        stats: stats
      });

      assert.deepEqual(stats.includedFiles, [expected]);
      done();
    });

    it('should state `data` as entry file', function(done) {
      sass.renderSync({
        data: read(fixture('simple/index.scss'), 'utf8'),
        stats: stats
      });

      assert.equal(stats.entry, 'data');
      done();
    });

    it('should contain an empty array as includedFiles', function(done) {
      sass.renderSync({
        data: read(fixture('simple/index.scss'), 'utf8'),
        stats: stats
      });

      assert.deepEqual(stats.includedFiles, []);
      done();
    });

    it('should report correct sourceMap in stats with renderSync', function(done) {
      var stats = {};

      sass.renderSync({
        file: fixture('simple/index.scss'),
        outFile: fixture('simple/index.css'),
        stats: stats,
        sourceMap: true
      });

      done(assert.ok(stats.sourceMap.indexOf('index.scss') !== -1));
    });
  });
});
<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- *\
   Gruntfile - project build instructions
   --------------------------------------------------------------------------

   This file is part of XML-to-bootstrap.
   https://github.com/acch/XML-to-bootstrap

   Copyright 2016 Achim Christ
   Released under the MIT license
   (https://github.com/acch/XML-to-bootstrap/blob/master/LICENSE)

\* -------------------------------------------------------------------------- */

// TODO: uncss task?
// TODO: jshint task? (inkl. .jshintrc)
// TODO: scsslint task?

module.exports = function(grunt) {
  "use strict";

  // dependencies
  var path = require('path');
  var parser = require('xml2json');

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

    // path definitions
    path: {
      anchor:          'lib/anchor-js',
      bootstrap:       'modules/bootstrap',
      fontawesome:     'lib/font-awesome',
      headroom:        'lib/headroom.js',
      jquery:          'lib/jquery',
      photoswipe:      'lib/photoswipe',
      scrollposstyler: 'lib/scrollpos-styler',
      tether:          'lib/tether'
    },

    exec: {
      submodules: {
        cmd: 'git submodule update --init \
        && if ! grep -q customvars <%= path.bootstrap %>/scss/_custom.scss; then echo \'@import "customvars";\' >> <%= path.bootstrap %>/scss/_custom.scss; fi \
        && ln -sf ../../../sass/customvars.scss <%= path.bootstrap %>/scss/'
      }
    },

    subgrunt: {
      bootstrap: {
        'modules/bootstrap': 'dist'
      }
    },

    clean: {
      publish: [
        'css/*',
        'js/*',
        '!js/headings.js',
        '!js/navbar.js',
        'publish/*',
        '!publish/assets/.gitkeep'
      ]
    },

    bower: {
      publish: {
        options: {
          cleanBowerDir: false,
          cleanTargetDir: true,
          copy: true,
          layout: 'byComponent'
        }
      }
    },

    copy: {
      publish: {
        files: [
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.anchor %>',
            src: '**/anchor.js',
            dest: 'js/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.bootstrap %>/dist',
            src: '**/bootstrap.min.css',
            dest: 'publish/css/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.bootstrap %>/dist',
            src: '**/bootstrap.min.js',
            dest: 'publish/js/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.fontawesome %>',
            src: '**/font-awesome.min.css',
            dest: 'publish/css/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.headroom %>',
            src: '**/headroom.js',
            dest: 'js/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.jquery %>',
            src: '**/jquery.min.js',
            dest: 'publish/js/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.photoswipe %>',
            src: ['**/photoswipe.css', '**/default-skin.css'],
            dest: 'css/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.photoswipe %>',
            src: '**/photoswipe*.js',
            dest: 'js/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.scrollposstyler %>',
            src: '**/scrollPosStyler.js',
            dest: 'js/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.tether %>',
            src: '**/tether.min.js',
            dest: 'publish/js/'
          }
        ]
      },

      assets_pre: {
        expand: true,
        cwd: 'src/img/',
        src: '*.{png,jpg,gif}',
        dest: 'img/'
      },

      assets_post: {
        expand: true,
        cwd: 'img/min/',
        src: '**/*.{png,jpg,gif}',
        dest: 'publish/assets/'
      }
    },

    xsltproc: {
      options: {
        stylesheet: 'style/main.xsl',
        xinclude: true
      },
      dev: {
        options: {
          params: {
            'devmode': 'true()'
          }
        },
        src: 'src/main.xml',
        dest: 'publish/index.html'
      },
      prod: {
        options: {
          params: {
            'devmode': 'false()'
          }
        },
        src: '<%= xsltproc.dev.src %>',
        dest: '<%= xsltproc.dev.dest %>'
      }
    },

    concat: {
      publish: {
        files: [
          {
            src: [
              'js/options.json',
              'js/anchor.js',
              'js/headroom.js',
              'js/scrollPosStyler.js',
              'js/headings.js',
              'js/navbar.js'
            ],
            dest: 'publish/js/script.js'
          },
          {
            src: 'css/*.css',
            dest: 'publish/css/gallery.css'
          },
          {
            src: 'js/photoswipe*.js',
            dest: 'publish/js/gallery.js'
          }
        ]
      }
    },

    uglify: {
      publish: {
        files: {
          'publish/js/script.js': 'publish/js/script.js',
          'publish/js/gallery.js': 'publish/js/gallery.js'
        }
      }
    },

    sass: {
      options: {
        style: 'nested'
      },
      publish: {
        src: 'sass/style.scss',
        dest: 'publish/css/style.css'
      }
    },

    autoprefixer: {
//      options: {
//        browsers: '> 1%, last 2 versions'
//      },
      publish: {
        src: ['publish/css/style.css', 'publish/css/gallery.css']
      }
    },

    csslint: {
      options: {
        'adjoining-classes': false,
        'compatible-vendor-prefixes': false,
        'fallback-colors': false,
        'important': false
      },
      publish: {
        src: 'publish/css/style.css'
      }
    },

    cssmin: {
      publish: {
        files: {
          'publish/css/style.css': 'publish/css/style.css',
          'publish/css/gallery.css': 'publish/css/gallery.css'
        }
      }
    },

    htmllint: {
      options: {
        ignore: [
          'The "contentinfo" role is unnecessary for element "footer".',
          'The "banner" role is unnecessary for element "header".'
        ]
      },
      publish: {
        expand: true,
        nonull: true,
        src: 'publish/**/*.html'
      }
    },

    htmlmin: {
      options: {
        removeComments: true,
        collapseWhitespace: true
      },
      publish: {
        expand: true,
        nonull: true,
        src: 'publish/**/*.html'
      }
    },

    prettify: {
      publish: {
        expand: true,
        nonull: true,
        src: 'publish/**/*.html'
      }
    },

    responsive_images: {
      options: {
        concurrency: 2
        // sizes are defined by 'xmlopts' task
      },
      assets: {
        expand: true,
        cwd: 'src/img/',
        src: '*/**/*.{png,jpg,gif}',
        dest: 'img/'
      }
    },

    imagemin: {
      assets: {
        expand: true,
        cwd: 'img/',
        src: [ '**/*.{png,jpg,gif}', '!min/**' ],
        dest: 'img/min/'
      }
    },

    connect: {
      publish: {
        options: {
          port: 8000,
          base: 'publish',
          keepalive: true,
          //open: 'http://localhost:8000/',
        }
      }
    }
  });

  // load the plugin(s)
  require('load-grunt-tasks')(grunt);

  // read options from XML
  grunt.registerTask('xmlopts', function() {

    // parse options.xml as object
    var xmlopts = parser.toJson(grunt.file.read('src/options.xml'), {
      coerce: true,
      object: true
    }).options;

    // extract Grunt options
    var gruntopts = xmlopts.export.filter(function(e) {
      return e.type == 'grunt';
    })[0].option;

    // temp configuration object
    var config = {
      responsive_images: {
        options: {
          sizes: []
        }
      }
    };

    // iterate over Grunt options
    for (var i = 0; gruntopts[i]; ++i) {
      // add options to temp configuration object
      switch (gruntopts[i].name) {

        case 'responive_image.size':
          config.responsive_images.options.sizes.push({
            name: gruntopts[i]['$t'],
            width: gruntopts[i]['$t']
          });
          break;

        // ...process further options...

      }
    }

    // apply temp Grunt configuration
    grunt.config.merge(config);
  });

  // copy sample files
  grunt.registerTask('copy_samples', function() {

    // copy sample files if they don't exist
    function copySampleIfNotExist(relpath) {

      // recurse sample subdirectory
      grunt.file.recurse(path.join(relpath, 'sample'), function(abspath, rootdir, subdir, filename) {

        // check if destination file exists
        var destfile = path.join(relpath, filename);
        if (! grunt.file.exists(destfile)) {

          // copy sample to destination
          grunt.log.writeln('Copying sample: ' + filename);
          grunt.file.copy(abspath, destfile);
        }
      });
    }

    // copy XML samples
    copySampleIfNotExist('src');

    // copy Sass samples
    copySampleIfNotExist('sass');

    // copy sample images only if directory doesn't exist, yet
    if (! grunt.file.isDir('src/img/')) {

      // copy sample images
      grunt.log.writeln('Copying sample images');
      grunt.file.copy('src/sampleimg/', 'src/img/');
    }
  });

  // initialize submodules
  grunt.registerTask('init', [
    'copy_samples',
    'exec:submodules',
    'subgrunt'
  ]);

  // no minification but linting (use this for development)
  grunt.registerTask('debug', [
    'copy_samples',
    'xmlopts',
    'clean',
    'bower',
    'copy:publish',
    'xsltproc:dev',
    'concat',
    'sass',
    'autoprefixer',
    'csslint',
    'prettify',
    'htmllint',
    'copy:assets_pre',
    'responsive_images',
    'newer:imagemin',
    'copy:assets_post'
  ]);

  // no linting but minification (use this for development)
  grunt.registerTask('default', [
    'copy_samples',
    'xmlopts',
    'clean',
    'bower',
    'copy:publish',
    'xsltproc:dev',
    'concat',
    'uglify',
    'sass',
    'autoprefixer',
    'cssmin',
    'htmlmin',
    'copy:assets_pre',
    'responsive_images',
    'newer:imagemin',
    'copy:assets_post'
  ]);

  // no linting but minification (use this for production)
  grunt.registerTask('prod', [
    'copy_samples',
    'xmlopts',
    'clean',
    'bower',
    'copy:publish',
    'xsltproc:prod',
    'concat',
    'uglify',
    'sass',
    'autoprefixer',
    'cssmin',
    'htmlmin',
    'copy:assets_pre',
    'responsive_images',
    'newer:imagemin',
    'copy:assets_post'
  ]);

};
<commit_msg>Properly clean publish/ while keeping publish/assets/<commit_after>/* -------------------------------------------------------------------------- *\
   Gruntfile - project build instructions
   --------------------------------------------------------------------------

   This file is part of XML-to-bootstrap.
   https://github.com/acch/XML-to-bootstrap

   Copyright 2016 Achim Christ
   Released under the MIT license
   (https://github.com/acch/XML-to-bootstrap/blob/master/LICENSE)

\* -------------------------------------------------------------------------- */

// TODO: uncss task?
// TODO: jshint task? (inkl. .jshintrc)
// TODO: scsslint task?

module.exports = function(grunt) {
  "use strict";

  // dependencies
  var path = require('path');
  var parser = require('xml2json');

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

    // path definitions
    path: {
      anchor:          'lib/anchor-js',
      bootstrap:       'modules/bootstrap',
      fontawesome:     'lib/font-awesome',
      headroom:        'lib/headroom.js',
      jquery:          'lib/jquery',
      photoswipe:      'lib/photoswipe',
      scrollposstyler: 'lib/scrollpos-styler',
      tether:          'lib/tether'
    },

    exec: {
      submodules: {
        cmd: 'git submodule update --init \
        && if ! grep -q customvars <%= path.bootstrap %>/scss/_custom.scss; then echo \'@import "customvars";\' >> <%= path.bootstrap %>/scss/_custom.scss; fi \
        && ln -sf ../../../sass/customvars.scss <%= path.bootstrap %>/scss/'
      }
    },

    subgrunt: {
      bootstrap: {
        'modules/bootstrap': 'dist'
      }
    },

    clean: {
      publish: [
        'css/*',
        'js/*',
        '!js/headings.js',
        '!js/navbar.js',
        'publish/assets/*',
        '!publish/assets/.gitkeep',
        'publish/*',
        '!publish/assets'
      ]
    },

    bower: {
      publish: {
        options: {
          cleanBowerDir: false,
          cleanTargetDir: true,
          copy: true,
          layout: 'byComponent'
        }
      }
    },

    copy: {
      publish: {
        files: [
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.anchor %>',
            src: '**/anchor.js',
            dest: 'js/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.bootstrap %>/dist',
            src: '**/bootstrap.min.css',
            dest: 'publish/css/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.bootstrap %>/dist',
            src: '**/bootstrap.min.js',
            dest: 'publish/js/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.fontawesome %>',
            src: '**/font-awesome.min.css',
            dest: 'publish/css/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.headroom %>',
            src: '**/headroom.js',
            dest: 'js/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.jquery %>',
            src: '**/jquery.min.js',
            dest: 'publish/js/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.photoswipe %>',
            src: ['**/photoswipe.css', '**/default-skin.css'],
            dest: 'css/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.photoswipe %>',
            src: '**/photoswipe*.js',
            dest: 'js/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.scrollposstyler %>',
            src: '**/scrollPosStyler.js',
            dest: 'js/'
          },
          {
            expand: true,
            flatten: true,
            nonull: true,
            cwd: '<%= path.tether %>',
            src: '**/tether.min.js',
            dest: 'publish/js/'
          }
        ]
      },

      assets_pre: {
        expand: true,
        cwd: 'src/img/',
        src: '*.{png,jpg,gif}',
        dest: 'img/'
      },

      assets_post: {
        expand: true,
        cwd: 'img/min/',
        src: '**/*.{png,jpg,gif}',
        dest: 'publish/assets/'
      }
    },

    xsltproc: {
      options: {
        stylesheet: 'style/main.xsl',
        xinclude: true
      },
      dev: {
        options: {
          params: {
            'devmode': 'true()'
          }
        },
        src: 'src/main.xml',
        dest: 'publish/index.html'
      },
      prod: {
        options: {
          params: {
            'devmode': 'false()'
          }
        },
        src: '<%= xsltproc.dev.src %>',
        dest: '<%= xsltproc.dev.dest %>'
      }
    },

    concat: {
      publish: {
        files: [
          {
            src: [
              'js/options.json',
              'js/anchor.js',
              'js/headroom.js',
              'js/scrollPosStyler.js',
              'js/headings.js',
              'js/navbar.js'
            ],
            dest: 'publish/js/script.js'
          },
          {
            src: 'css/*.css',
            dest: 'publish/css/gallery.css'
          },
          {
            src: 'js/photoswipe*.js',
            dest: 'publish/js/gallery.js'
          }
        ]
      }
    },

    uglify: {
      publish: {
        files: {
          'publish/js/script.js': 'publish/js/script.js',
          'publish/js/gallery.js': 'publish/js/gallery.js'
        }
      }
    },

    sass: {
      options: {
        style: 'nested'
      },
      publish: {
        src: 'sass/style.scss',
        dest: 'publish/css/style.css'
      }
    },

    autoprefixer: {
//      options: {
//        browsers: '> 1%, last 2 versions'
//      },
      publish: {
        src: ['publish/css/style.css', 'publish/css/gallery.css']
      }
    },

    csslint: {
      options: {
        'adjoining-classes': false,
        'compatible-vendor-prefixes': false,
        'fallback-colors': false,
        'important': false
      },
      publish: {
        src: 'publish/css/style.css'
      }
    },

    cssmin: {
      publish: {
        files: {
          'publish/css/style.css': 'publish/css/style.css',
          'publish/css/gallery.css': 'publish/css/gallery.css'
        }
      }
    },

    htmllint: {
      options: {
        ignore: [
          'The "contentinfo" role is unnecessary for element "footer".',
          'The "banner" role is unnecessary for element "header".'
        ]
      },
      publish: {
        expand: true,
        nonull: true,
        src: 'publish/**/*.html'
      }
    },

    htmlmin: {
      options: {
        removeComments: true,
        collapseWhitespace: true
      },
      publish: {
        expand: true,
        nonull: true,
        src: 'publish/**/*.html'
      }
    },

    prettify: {
      publish: {
        expand: true,
        nonull: true,
        src: 'publish/**/*.html'
      }
    },

    responsive_images: {
      options: {
        concurrency: 2
        // sizes are defined by 'xmlopts' task
      },
      assets: {
        expand: true,
        cwd: 'src/img/',
        src: '*/**/*.{png,jpg,gif}',
        dest: 'img/'
      }
    },

    imagemin: {
      assets: {
        expand: true,
        cwd: 'img/',
        src: [ '**/*.{png,jpg,gif}', '!min/**' ],
        dest: 'img/min/'
      }
    },

    connect: {
      publish: {
        options: {
          port: 8000,
          base: 'publish',
          keepalive: true,
          //open: 'http://localhost:8000/',
        }
      }
    }
  });

  // load the plugin(s)
  require('load-grunt-tasks')(grunt);

  // read options from XML
  grunt.registerTask('xmlopts', function() {

    // parse options.xml as object
    var xmlopts = parser.toJson(grunt.file.read('src/options.xml'), {
      coerce: true,
      object: true
    }).options;

    // extract Grunt options
    var gruntopts = xmlopts.export.filter(function(e) {
      return e.type == 'grunt';
    })[0].option;

    // temp configuration object
    var config = {
      responsive_images: {
        options: {
          sizes: []
        }
      }
    };

    // iterate over Grunt options
    for (var i = 0; gruntopts[i]; ++i) {
      // add options to temp configuration object
      switch (gruntopts[i].name) {

        case 'responive_image.size':
          config.responsive_images.options.sizes.push({
            name: gruntopts[i]['$t'],
            width: gruntopts[i]['$t']
          });
          break;

        // ...process further options...

      }
    }

    // apply temp Grunt configuration
    grunt.config.merge(config);
  });

  // copy sample files
  grunt.registerTask('copy_samples', function() {

    // copy sample files if they don't exist
    function copySampleIfNotExist(relpath) {

      // recurse sample subdirectory
      grunt.file.recurse(path.join(relpath, 'sample'), function(abspath, rootdir, subdir, filename) {

        // check if destination file exists
        var destfile = path.join(relpath, filename);
        if (! grunt.file.exists(destfile)) {

          // copy sample to destination
          grunt.log.writeln('Copying sample: ' + filename);
          grunt.file.copy(abspath, destfile);
        }
      });
    }

    // copy XML samples
    copySampleIfNotExist('src');

    // copy Sass samples
    copySampleIfNotExist('sass');

    // copy sample images only if directory doesn't exist, yet
    if (! grunt.file.isDir('src/img/')) {

      // copy sample images
      grunt.log.writeln('Copying sample images');
      grunt.file.copy('src/sampleimg/', 'src/img/');
    }
  });

  // initialize submodules
  grunt.registerTask('init', [
    'copy_samples',
    'exec:submodules',
    'subgrunt'
  ]);

  // no minification but linting (use this for development)
  grunt.registerTask('debug', [
    'copy_samples',
    'xmlopts',
    'clean',
    'bower',
    'copy:publish',
    'xsltproc:dev',
    'concat',
    'sass',
    'autoprefixer',
    'csslint',
    'prettify',
    'htmllint',
    'copy:assets_pre',
    'responsive_images',
    'newer:imagemin',
    'copy:assets_post'
  ]);

  // no linting but minification (use this for development)
  grunt.registerTask('default', [
    'copy_samples',
    'xmlopts',
    'clean',
    'bower',
    'copy:publish',
    'xsltproc:dev',
    'concat',
    'uglify',
    'sass',
    'autoprefixer',
    'cssmin',
    'htmlmin',
    'copy:assets_pre',
    'responsive_images',
    'newer:imagemin',
    'copy:assets_post'
  ]);

  // no linting but minification (use this for production)
  grunt.registerTask('prod', [
    'copy_samples',
    'xmlopts',
    'clean',
    'bower',
    'copy:publish',
    'xsltproc:prod',
    'concat',
    'uglify',
    'sass',
    'autoprefixer',
    'cssmin',
    'htmlmin',
    'copy:assets_pre',
    'responsive_images',
    'newer:imagemin',
    'copy:assets_post'
  ]);

};
<|endoftext|>


<commit_before>/*
 * client.js: Client base for the Nodejitsu API clients.
 *
 * (C) 2010, Nodejitsu Inc.
 *
 */

var eyes = require('eyes'),
    fs = require('fs'),
    request = require('request'),
    jitsu = require('jitsu');

//
// ### function Client (options)
// #### @options {Object} Options for this instance
// Constructor function for the Client base responsible
// for communicating with Nodejitsu's API
//
var Client = exports.Client = function (options) {
  this.options = options;
  this._request = request;
};

//
// ### @private function request (method, uri, [body], success, callback)
// #### @method {string} HTTP method to use
// #### @uri {Array} Locator for the Remote Resource
// #### @body {Object} **optional** JSON Request Body
// #### @callback {function} Continuation to call if errors occur.
// #### @success {function} Continuation to call upon successful transactions
// Makes a request to `this.remoteUri + uri` using `method` and any
// `body` (JSON-only) if supplied. Short circuits to `callback` if the response
// code from Nodejitsu matches `jitsu.failCodes`.
//
Client.prototype.request = function (method, uri /* variable arguments */) {
  var options, args = Array.prototype.slice.call(arguments),
      success = args.pop(),
      callback = args.pop(),
      body = typeof args[args.length - 1] === 'object' && !Array.isArray(args[args.length - 1]) && args.pop(),
      encoded = jitsu.utils.base64.encode(this.options.get('username') + ':' + this.options.get('password'));

  options = {
    method: method || 'GET',
    uri: this.options.get('remoteUri') + '/' + uri.join('/'),
    headers: {
      'Authorization': 'Basic ' + encoded,
      'Content-Type': 'application/json'
    }
  };

  if (body) {
    options.body = JSON.stringify(body);
  }

  this._request(options, function (err, response, body) {
    if (err) {
      return callback(err);
    }

    var statusCode, result, error;

    try {
      statusCode = response.statusCode.toString();
      result = JSON.parse(body);
    }
    catch (ex) {
      // Ignore Errors
    }

    var poweredBy = response.headers['x-powered-by'];
    if (poweredBy.indexOf('Nodejitsu') === -1) {
      error = new Error('Jitsu requires you to connect to Nodejitsu\'s stack (api.nodejitsu.com)');
      error.statusCode = "403";
      error.result = "";
      return callback(error);
    }

    if (Object.keys(jitsu.failCodes).indexOf(statusCode) !== -1) {
      error = new Error('Nodejitsu Error (' + statusCode + '): ' + jitsu.failCodes[statusCode]);
      error.statusCode = statusCode;
      error.result = result;
      return callback(error);
    }

    success(response, result);
  });
};

//
// ### function upload (uri, contentType, file, callback, success)
// #### @uri {Array} Locator for the Remote Resource
// #### @contentType {string} Content-Type header to use for the upload.
// #### @file {string} Path of the local file to upload.
// #### @success {function} Continuation to call upon successful transactions
// #### @callback {function} Continuation to call if errors occur.
// Makes a `POST` request to `this.remoteUri + uri` with the data in `file`
// as the request body. Short circuits to `callback` if the response
// code from Nodejitsu matches `jitsu.failCodes`.
//
Client.prototype.upload = function (uri, contentType, file, callback, success) {
  var self = this,
      options,
      out,
      encoded;

  encoded = jitsu.utils.base64.encode(this.options.get('username') + ':' + this.options.get('password'));

  fs.readFile(file, function (err, data) {
    options = {
      method: 'POST',
      uri: self.options.get('remoteUri') + '/' + uri.join('/'),
      headers: {
        'Authorization': 'Basic ' + encoded,
        'Content-Type': contentType,
        'Content-Length': data.length
      }
    };

    out = self._request(options, function (err, response, body) {
      if (err) {
        return callback(err);
      }

      var statusCode, result, error;

      try {
        statusCode = response.statusCode.toString();
        result = JSON.parse(body);
      }
      catch (ex) {
        // Ignore Errors
      }
      if (Object.keys(jitsu.failCodes).indexOf(statusCode) !== -1) {
        error = new Error('Nodejitsu Error (' + statusCode + '): ' + jitsu.failCodes[statusCode]);
        error.result = result;
        return callback(error);
      }

      success(response, result);
    });

    fs.createReadStream(file).pipe(out);
  });
};
<commit_msg>[fix] exit out gracefully if no x-powered-by header exists<commit_after>/*
 * client.js: Client base for the Nodejitsu API clients.
 *
 * (C) 2010, Nodejitsu Inc.
 *
 */

var eyes = require('eyes'),
    fs = require('fs'),
    request = require('request'),
    jitsu = require('jitsu');

//
// ### function Client (options)
// #### @options {Object} Options for this instance
// Constructor function for the Client base responsible
// for communicating with Nodejitsu's API
//
var Client = exports.Client = function (options) {
  this.options = options;
  this._request = request;
};

//
// ### @private function request (method, uri, [body], success, callback)
// #### @method {string} HTTP method to use
// #### @uri {Array} Locator for the Remote Resource
// #### @body {Object} **optional** JSON Request Body
// #### @callback {function} Continuation to call if errors occur.
// #### @success {function} Continuation to call upon successful transactions
// Makes a request to `this.remoteUri + uri` using `method` and any
// `body` (JSON-only) if supplied. Short circuits to `callback` if the response
// code from Nodejitsu matches `jitsu.failCodes`.
//
Client.prototype.request = function (method, uri /* variable arguments */) {
  var options, args = Array.prototype.slice.call(arguments),
      success = args.pop(),
      callback = args.pop(),
      body = typeof args[args.length - 1] === 'object' && !Array.isArray(args[args.length - 1]) && args.pop(),
      encoded = jitsu.utils.base64.encode(this.options.get('username') + ':' + this.options.get('password'));

  options = {
    method: method || 'GET',
    uri: this.options.get('remoteUri') + '/' + uri.join('/'),
    headers: {
      'Authorization': 'Basic ' + encoded,
      'Content-Type': 'application/json'
    }
  };

  if (body) {
    options.body = JSON.stringify(body);
  }

  this._request(options, function (err, response, body) {
    if (err) {
      return callback(err);
    }

    var statusCode, result, error;

    try {
      statusCode = response.statusCode.toString();
      result = JSON.parse(body);
    }
    catch (ex) {
      // Ignore Errors
    }

    var poweredBy = response.headers['x-powered-by'];
    if (!poweredBy || poweredBy.indexOf('Nodejitsu') === -1) {
      error = new Error('Jitsu requires you to connect to Nodejitsu\'s stack (api.nodejitsu.com)');
      error.statusCode = "403";
      error.result = "";
      return callback(error);
    }

    if (Object.keys(jitsu.failCodes).indexOf(statusCode) !== -1) {
      error = new Error('Nodejitsu Error (' + statusCode + '): ' + jitsu.failCodes[statusCode]);
      error.statusCode = statusCode;
      error.result = result;
      return callback(error);
    }

    success(response, result);
  });
};

//
// ### function upload (uri, contentType, file, callback, success)
// #### @uri {Array} Locator for the Remote Resource
// #### @contentType {string} Content-Type header to use for the upload.
// #### @file {string} Path of the local file to upload.
// #### @success {function} Continuation to call upon successful transactions
// #### @callback {function} Continuation to call if errors occur.
// Makes a `POST` request to `this.remoteUri + uri` with the data in `file`
// as the request body. Short circuits to `callback` if the response
// code from Nodejitsu matches `jitsu.failCodes`.
//
Client.prototype.upload = function (uri, contentType, file, callback, success) {
  var self = this,
      options,
      out,
      encoded;

  encoded = jitsu.utils.base64.encode(this.options.get('username') + ':' + this.options.get('password'));

  fs.readFile(file, function (err, data) {
    options = {
      method: 'POST',
      uri: self.options.get('remoteUri') + '/' + uri.join('/'),
      headers: {
        'Authorization': 'Basic ' + encoded,
        'Content-Type': contentType,
        'Content-Length': data.length
      }
    };

    out = self._request(options, function (err, response, body) {
      if (err) {
        return callback(err);
      }

      var statusCode, result, error;

      try {
        statusCode = response.statusCode.toString();
        result = JSON.parse(body);
      }
      catch (ex) {
        // Ignore Errors
      }
      if (Object.keys(jitsu.failCodes).indexOf(statusCode) !== -1) {
        error = new Error('Nodejitsu Error (' + statusCode + '): ' + jitsu.failCodes[statusCode]);
        error.result = result;
        return callback(error);
      }

      success(response, result);
    });

    fs.createReadStream(file).pipe(out);
  });
};
<|endoftext|>


<commit_before>
var expect = require("expect.js")
,   w3c = require("..")
;

if (!process.env.W3CAPIKEY) {
    console.error("No API key has been set, make sure you defined the W3CAPIKEY environment variable.");
    process.exit(1);
}
w3c.apiKey = process.env.W3CAPIKEY;

function listChecker (done, title) {
    return function (err, data) {
        expect(err).to.not.be.ok();
        expect(data).to.be.an("array");
        if (title) expect(data.some(function (it) { return it.title === title; })).to.be.ok();
        done();
    };
}

function embedChecker (done, field, value) {
    return function (err, data) {
        expect(err).to.not.be.ok();
        expect(data).to.be.an("array");
        expect(data.some(function (it) { return it[field] === value; })).to.be.ok();
        done();
    };
}

function itemChecker (done, field, value) {
    return function (err, data) {
        expect(err).to.not.be.ok();
        expect(data[field]).to.equal(value);
        done();
    };
}

describe("Domains", function () {
    it("can be listed", function (done) {
        w3c.domains().fetch(listChecker(done, "Interaction"));
    });
    it("can be fetched", function (done) {
        w3c.domain(41481).fetch(itemChecker(done, "name", "Interaction"));
    });
    it("have groups", function (done) {
        w3c.domain(41481).groups().fetch(listChecker(done, "Internationalization Working Group"));
    });
    it("have services", function (done) {
        w3c.domain(41481).services().fetch(listChecker(done, "Issues Tracking"));
    });
    it("have users", function (done) {
        w3c.domain(41481).users().fetch(listChecker(done, "Philippe Le Hégaret"));
    });
});

describe("Groups", function () {
    it("can be listed", function (done) {
        w3c.groups().fetch(listChecker(done, "Cascading Style Sheets (CSS) Working Group"));
    });
    it("can be fetched", function (done) {
        w3c.group(32061).fetch(itemChecker(done, "name", "Cascading Style Sheets (CSS) Working Group"));
    });
    it("have chairs", function (done) {
        // XXX this will change soon
        w3c.group(32061).chairs().fetch(listChecker(done, "Daniel Glazman"));
    });
    it("have services", function (done) {
        w3c.group(32061).services().fetch(listChecker(done, "Wiki"));
    });
    it("have specifications", function (done) {
        w3c.group(32061).specifications().fetch(listChecker(done, "Selectors Level 3"));
    });
    it("have teamcontacts", function (done) {
        w3c.group(32061).teamcontacts().fetch(listChecker(done, "Bert Bos"));
    });
    it("have users", function (done) {
        w3c.group(32061).users().fetch(listChecker(done, "Tab Atkins Jr."));
    });
    it("have charters", function (done) {
        w3c.group(32061).charters().fetch(listChecker(done));
    });
    it("have charters that can be fetched", function (done) {
        w3c.group(32061).charter(102).fetch(itemChecker(done, "end", "1999-02-28"));
    });
    it("have participations", function (done) {
        w3c.group(32061).participations().fetch(listChecker(done));
    });
});

describe("Services", function () {
    it("can be fetched", function (done) {
        w3c.service(2).fetch(itemChecker(done, "type", "tracker"));
    });
    it("have groups", function (done) {
        w3c.service(2).groups().fetch(listChecker(done, "Systems"));
    });
});

describe("Specifications", function () {
    it("can be listed", function (done) {
        w3c.specifications().fetch(listChecker(done, "SVG Paths"));
    });
    it("can be fetched", function (done) {
        w3c.specification("rex").fetch(itemChecker(done, "shortname", "rex"));
    });
    it("have superseded", function (done) {
        w3c.specification("SVG").superseded().fetch(listChecker(done, "Scalable Vector Graphics (SVG) 1.1 (Second Edition)"));
    });
    it("have supersedes", function (done) {
        w3c.specification("SVG11").supersedes().fetch(listChecker(done, "Scalable Vector Graphics (SVG) 1.0 Specification"));
    });
    it("have latest", function (done) {
        w3c.specification("SVG11").latest().fetch(itemChecker(done, "date", "2011-08-16"));
    });
});

describe("Specifications Version", function () {
    it("can be listed", function (done) {
        w3c.specification("SVG11").versions().fetch(listChecker(done, "Scalable Vector Graphics (SVG) 1.1 Specification"));
    });
    it("can be fetched", function (done) {
        w3c.specification("SVG11").version("20030114").fetch(itemChecker(done, "date", "2003-01-14"));
    });
    it("have deliverers", function (done) {
        w3c.specification("SVG11").version("20030114").deliverers().fetch(listChecker(done, "SVG Working Group"));
    });
    it("have editors", function (done) {
        w3c.specification("SVG11").version("20030114").editors().fetch(listChecker(done, "Dean Jackson"));
    });
    it("have successors", function (done) {
        w3c.specification("CSS2").version("20070719").successors().fetch(listChecker(done, "Candidate Recommendation"));
    });
    it("have predecessors", function (done) {
        w3c.specification("CSS2").version("20090423").predecessors().fetch(listChecker(done, "Candidate Recommendation"));
    });
});

describe("Users", function () {
    var ian = "ggdj8tciu9kwwc4o4ww888ggkwok0c8";
    it("can be fetched", function (done) {
        w3c.user(ian).fetch(itemChecker(done, "given", "Ian"));
    });
    it("have affiliations", function (done) {
        w3c.user(ian).affiliations().fetch(listChecker(done));
    });
    it("have groups", function (done) {
        w3c.user(ian).groups().fetch(listChecker(done, "Community Council"));
    });
    it("have participations", function (done) {
        w3c.user(ian).participations().fetch(listChecker(done, "Web Payments Working Group"));
    });
    it("have specifications", function (done) {
        w3c.user(ian).specifications().fetch(listChecker(done, "Accessibility Features of CSS"));
    });
});

describe('Affiliations', function () {
    const STAFF = 52794;
    it('can be listed', function (done) {
        w3c.affiliations().fetch(listChecker(done, 'Framkom (Forskningsaktiebolaget Medie-och Kommunikationsteknik)'));
    });
    it('can be fetched', function (done) {
        w3c.affiliation(STAFF).fetch(itemChecker(done, 'name', 'W3C Staff'));
    });
    it('have participants', function (done) {
        w3c.affiliation(STAFF).participants().fetch(listChecker(done, 'Kazuyuki Ashimura'));
    });
    it('have participations', function (done) {
        w3c.affiliation(STAFF).participations().fetch(listChecker(done, 'Evaluation and Repair Tools Working Group'));
    });
});

describe('Participations', function () {
     const WIKI = 1503;
    it('can be fetched', function (done) {
        w3c.participation(WIKI).fetch(itemChecker(done, 'created', '2011-03-07 08:59:38'));
    });
    it('have participants', function (done) {
        w3c.participation(WIKI).participants().fetch(listChecker(done, 'Oliver Friedrich'));
    });
});

describe("Embeds", function () {
    it("apply to domains", function (done) {
        w3c.domains().fetch({ embed: true }, embedChecker(done, "name", "Management"));
    });
    it("apply to groups", function (done) {
        w3c.groups().fetch({ embed: true }, embedChecker(done, "type", "community group"));
    });
    it("apply to specifications", function (done) {
        w3c.specifications().fetch({ embed: true }, embedChecker(done, "shortname", "wbxml"));
    });
});
<commit_msg>Update test cases<commit_after>
var expect = require("expect.js")
,   w3c = require("..")
;

if (!process.env.W3CAPIKEY) {
    console.error("No API key has been set, make sure you defined the W3CAPIKEY environment variable.");
    process.exit(1);
}
w3c.apiKey = process.env.W3CAPIKEY;

function listChecker (done, title) {
    return function (err, data) {
        expect(err).to.not.be.ok();
        expect(data).to.be.an("array");
        if (title) expect(data.some(function (it) { return it.title === title; })).to.be.ok();
        done();
    };
}

function embedChecker (done, field, value) {
    return function (err, data) {
        expect(err).to.not.be.ok();
        expect(data).to.be.an("array");
        expect(data.some(function (it) { return it[field] === value; })).to.be.ok();
        done();
    };
}

function itemChecker (done, field, value) {
    return function (err, data) {
        expect(err).to.not.be.ok();
        expect(data[field]).to.equal(value);
        done();
    };
}

describe("Domains", function () {
    it("can be listed", function (done) {
        w3c.domains().fetch(listChecker(done, "Interaction"));
    });
    it("can be fetched", function (done) {
        w3c.domain(41481).fetch(itemChecker(done, "name", "Interaction"));
    });
    it("have groups", function (done) {
        w3c.domain(41481).groups().fetch(listChecker(done, "Internationalization Working Group"));
    });
    it("have services", function (done) {
        w3c.domain(41481).services().fetch(listChecker(done, "Issues Tracking"));
    });
    it("have users", function (done) {
        w3c.domain(41481).users().fetch(listChecker(done, "Philippe Le Hégaret"));
    });
});

describe("Groups", function () {
    it("can be listed", function (done) {
        w3c.groups().fetch(listChecker(done, "Cascading Style Sheets (CSS) Working Group"));
    });
    it("can be fetched", function (done) {
        w3c.group(32061).fetch(itemChecker(done, "name", "Cascading Style Sheets (CSS) Working Group"));
    });
    it("have chairs", function (done) {
        w3c.group(32061).chairs().fetch(listChecker(done, "Rossen Atanassov"));
    });
    it("have services", function (done) {
        w3c.group(32061).services().fetch(listChecker(done, "Wiki"));
    });
    it("have specifications", function (done) {
        w3c.group(32061).specifications().fetch(listChecker(done, "Selectors Level 3"));
    });
    it("have teamcontacts", function (done) {
        w3c.group(32061).teamcontacts().fetch(listChecker(done, "Bert Bos"));
    });
    it("have users", function (done) {
        w3c.group(32061).users().fetch(listChecker(done, "Tab Atkins Jr."));
    });
    it("have charters", function (done) {
        w3c.group(32061).charters().fetch(listChecker(done));
    });
    it("have charters that can be fetched", function (done) {
        w3c.group(32061).charter(102).fetch(itemChecker(done, "end", "1999-02-28"));
    });
    it("have participations", function (done) {
        w3c.group(32061).participations().fetch(listChecker(done));
    });
});

describe("Services", function () {
    it("can be fetched", function (done) {
        w3c.service(2).fetch(itemChecker(done, "type", "tracker"));
    });
    it("have groups", function (done) {
        w3c.service(2).groups().fetch(listChecker(done, "Systems"));
    });
});

describe("Specifications", function () {
    it("can be listed", function (done) {
        w3c.specifications().fetch(listChecker(done, "SVG Paths"));
    });
    it("can be fetched", function (done) {
        w3c.specification("rex").fetch(itemChecker(done, "shortname", "rex"));
    });
    it("have superseded", function (done) {
        w3c.specification("SVG").superseded().fetch(listChecker(done, "Scalable Vector Graphics (SVG) 1.1 (Second Edition)"));
    });
    it("have supersedes", function (done) {
        w3c.specification("SVG11").supersedes().fetch(listChecker(done, "Scalable Vector Graphics (SVG) 1.0 Specification"));
    });
    it("have latest", function (done) {
        w3c.specification("SVG11").latest().fetch(itemChecker(done, "date", "2011-08-16"));
    });
});

describe("Specifications Version", function () {
    it("can be listed", function (done) {
        w3c.specification("SVG11").versions().fetch(listChecker(done, "Scalable Vector Graphics (SVG) 1.1 Specification"));
    });
    it("can be fetched", function (done) {
        w3c.specification("SVG11").version("20030114").fetch(itemChecker(done, "date", "2003-01-14"));
    });
    it("have deliverers", function (done) {
        w3c.specification("SVG11").version("20030114").deliverers().fetch(listChecker(done, "SVG Working Group"));
    });
    it("have editors", function (done) {
        w3c.specification("SVG11").version("20030114").editors().fetch(listChecker(done, "Dean Jackson"));
    });
    it("have successors", function (done) {
        w3c.specification("CSS2").version("20070719").successors().fetch(listChecker(done, "Candidate Recommendation"));
    });
    it("have predecessors", function (done) {
        w3c.specification("CSS2").version("20090423").predecessors().fetch(listChecker(done, "Candidate Recommendation"));
    });
});

describe("Users", function () {
    var ian = "ggdj8tciu9kwwc4o4ww888ggkwok0c8";
    it("can be fetched", function (done) {
        w3c.user(ian).fetch(itemChecker(done, "given", "Ian"));
    });
    it("have affiliations", function (done) {
        w3c.user(ian).affiliations().fetch(listChecker(done));
    });
    it("have groups", function (done) {
        w3c.user(ian).groups().fetch(listChecker(done, "Community Council"));
    });
    it("have participations", function (done) {
        w3c.user(ian).participations().fetch(listChecker(done, "Web Payments Working Group"));
    });
    it("have specifications", function (done) {
        w3c.user(ian).specifications().fetch(listChecker(done, "Accessibility Features of CSS"));
    });
});

describe('Affiliations', function () {
    const STAFF = 52794;
    it('can be listed', function (done) {
        w3c.affiliations().fetch(listChecker(done, 'Framkom (Forskningsaktiebolaget Medie-och Kommunikationsteknik)'));
    });
    it('can be fetched', function (done) {
        w3c.affiliation(STAFF).fetch(itemChecker(done, 'name', 'W3C Staff'));
    });
    it('have participants', function (done) {
        w3c.affiliation(STAFF).participants().fetch(listChecker(done, 'Kazuyuki Ashimura'));
    });
    it('have participations', function (done) {
        w3c.affiliation(STAFF).participations().fetch(listChecker(done, 'Evaluation and Repair Tools Working Group'));
    });
});

describe('Participations', function () {
     const WIKI = 1503;
    it('can be fetched', function (done) {
        w3c.participation(WIKI).fetch(itemChecker(done, 'created', '2011-03-07 08:59:38'));
    });
    it('have participants', function (done) {
        w3c.participation(WIKI).participants().fetch(listChecker(done, 'Oliver Friedrich'));
    });
});

describe("Embeds", function () {
    it("apply to domains", function (done) {
        w3c.domains().fetch({ embed: true }, embedChecker(done, "name", "Management"));
    });
    it("apply to groups", function (done) {
        w3c.groups().fetch({ embed: true }, embedChecker(done, "type", "community group"));
    });
    it("apply to specifications", function (done) {
        w3c.specifications().fetch({ embed: true }, embedChecker(done, "shortname", "wbxml"));
    });
});
<|endoftext|>


<commit_before>module.exports = function(grunt) {

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

    connect: {
      server: {
        options: {
          hostname: '127.0.0.1',
          base: '.',
          port: 8080
        }
      }
    },

    jshint: {
      files: ['src/*.js'],
      options: {
        jshintrc: '.jshintrc'
      }
    },

    uglify: {
      grouped: {
        options: {
          mangle: false,
          compress: false,
          beautify: true
        },
        files: {
          'build/date-enhancer.js': ['src/*.js']
        }
      },
      minified: {
        options: {
          mangle: true,
          compress: {
            sequences: true,
            properties: true,
            dead_code: true,
            booleans: true,
            loops: true,
            if_return: true,
            join_vars: true,
            drop_console: true,
          }
        },
        files: {
          'build/date-enhancer.min.js': ['src/*.js']
        }
      }
    },

    jasmine : {
      src : 'src/*.js',
      options : {
        specs : 'spec/*.js'
      }
    },

    watch: {
      scripts: {
        files: ['src/*', 'spec/*', 'Gruntfile.js'],
        tasks: ['default'],
        options: {
          interrupt: true,
        },
      },
    },

    karma: {
      options: {
        frameworks: ['jasmine'],
        files: ['spec/*.js', 'src/*.js'],
      },
      unit: {
        browsers: ['PhantomJS', 'Safari', 'Firefox'],
      },
      travis: {
        browsers: ['PhantomJS'],
        singleRun: true,
        reporters: ['coverage'],
        coverageReporter: {
          type: "lcov",
          dir: "coverage/"
        },
      }
    },

    coveralls: {
      options: {
        debug: true,
        coverageDir: 'coverage/',
        dryRun: true,
        force: true,
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-jasmine');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-karma-coveralls');

  grunt.registerTask('test', ['jshint', 'karma:travis']);
  grunt.registerTask('default', ['test', 'uglify', 'coveralls']);
};
<commit_msg>Removing dryRun on coveralls conf<commit_after>module.exports = function(grunt) {

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

    connect: {
      server: {
        options: {
          hostname: '127.0.0.1',
          base: '.',
          port: 8080
        }
      }
    },

    jshint: {
      files: ['src/*.js'],
      options: {
        jshintrc: '.jshintrc'
      }
    },

    uglify: {
      grouped: {
        options: {
          mangle: false,
          compress: false,
          beautify: true
        },
        files: {
          'build/date-enhancer.js': ['src/*.js']
        }
      },
      minified: {
        options: {
          mangle: true,
          compress: {
            sequences: true,
            properties: true,
            dead_code: true,
            booleans: true,
            loops: true,
            if_return: true,
            join_vars: true,
            drop_console: true,
          }
        },
        files: {
          'build/date-enhancer.min.js': ['src/*.js']
        }
      }
    },

    jasmine : {
      src : 'src/*.js',
      options : {
        specs : 'spec/*.js'
      }
    },

    watch: {
      scripts: {
        files: ['src/*', 'spec/*', 'Gruntfile.js'],
        tasks: ['default'],
        options: {
          interrupt: true,
        },
      },
    },

    karma: {
      options: {
        frameworks: ['jasmine'],
        files: ['spec/*.js', 'src/*.js'],
      },
      unit: {
        browsers: ['PhantomJS', 'Safari', 'Firefox'],
      },
      travis: {
        browsers: ['PhantomJS'],
        singleRun: true,
        reporters: ['coverage'],
        coverageReporter: {
          type: "lcov",
          dir: "coverage/"
        },
      }
    },

    coveralls: {
      options: {
        coverageDir: 'coverage/',
        force: true,
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-jasmine');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-karma-coveralls');

  grunt.registerTask('test', ['jshint', 'karma:travis']);
  grunt.registerTask('default', ['test', 'uglify', 'coveralls']);
};
<|endoftext|>


<commit_before>module.exports = function (grunt) {
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-copy');

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        watch: {
            less: {
                files: ['src/styles/**/*.less'],
                tasks: ['less']
            },
            js: {
                files: ['src/scripts/**/*.js'],
                tasks: ['concat', 'uglify']
            }
        },
        less: {
            dev: {
                files: {
                    'examples/css/narwhal.css': 'src/styles/narwhal.less'
                }
            },
            // to generate distribution uncompressed versions
            uncompressed: {
                options: {
                    compress: false,
                    ieCompat: true,
                    yuicompress: false // Off until calc() bug is addressed.  https://github.com/yui/yuicompressor/issues/59
                },
                files: {
                    'dist/narwhal.css': 'src/styles/narwhal.less',
                    'examples/css/narwhal.css': 'src/styles/narwhal.less'
                }
            },
            production: {
                options: {
                    compress: true,
                    ieCompat: true,
                    yuicompress: false // Off until calc() bug is addressed.  https://github.com/yui/yuicompressor/issues/59
                },
                files: {
                    'dist/narwhal.min.css': 'src/styles/narwhal.less',
                    'examples/css/narwhal.min.css': 'src/styles/narwhal.less'
                }
            }
        },
        scripts: {
            libs: [
            ],
            core: [
                'src/scripts/core/narwhal.js',
                'src/scripts/core/cartesian.js',
                'src/scripts/core/**/*.js'
            ],
            vis: [
                'src/scripts/visualizations/**/*.js'
            ]
        },
        include: {
            core: {
                src: ['<%= scripts.core %>'],
                dest: 'web/include/login/scripts.html'
            }
        },
        concat: {
            all: {
                src: ['<%= scripts.core %>', '<%= scripts.vis %>'],
                dest: 'dist/narwhal.js'
            }
        },
        uglify: {
            options: {
                sourceMap: function (fileName) {
                    return fileName.replace(/\.js$/, '.map');
                },
                banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
                        '<%= grunt.template.today("yyyy-mm-dd") %> */\n'
            },
            production: {
                files: {
                    'dist/narwhal.min.js': ['dist/narwhal.js']
                }
            }
        }
    });

    // Default task.
    grunt.registerTask('default', ['less:dev', 'watch']);
    grunt.registerTask('production', ['concat', 'uglify', 'less:production']);
    grunt.registerTask('linked', ['concat', 'uglify', 'less:uncompressed', 'less:production', 'watch']);

    grunt.registerMultiTask('templates', 'Compiles underscore templates', function () {
        var _ = require('lodash');
        var options = this.options({
            separator: grunt.util.linefeed,
            templateSettings: {},
            templateNamespace: 'tmpl'
        });

        function getNamespace(ns) {
            var output = [];
            var curPath = 'App';
            if (ns !== 'App') {
                var nsParts = ns.split('.');
                nsParts.forEach(function(curPart, index) {
                    if (curPart !== 'App') {
                        curPath += '[' + JSON.stringify(curPart) + ']';
                        output.push(curPath + ' = ' + curPath + ' || {};');
                    }
                });
            }

            return {
                namespace: curPath,
                declaration: output.join('\n')
            };
        }

        this.files.forEach(function (f) {
            var namespaces = [];
            var output = f.src.filter(function (path) {
                if (!grunt.file.exists(path)) {
                    grunt.log.warn('Source file "' + filepath + '" not found.');
                    return false;
                } else {
                    return true;
                }
            }).map(function (path) {
                var src = grunt.file.read(path);
                var parts = path.match(/.+\/(?:template|tmpl)(?:s)?\/(.+).html/i)[1].split('/');
                var ns = _.initial(parts).join('.').replace(/(-.)/g, function () {
                    return arguments[0].substring(1).toUpperCase();
                });
                var name = _.last(parts).replace(/(-.)/g, function () {
                    return arguments[0].substring(1).toUpperCase();
                });
                var nsInfo = getNamespace([options.templateNamespace, ns].join('.'));
                var compiled;

                try {
                    compiled = _.template(src, false, options.templateSettings).source;
                } catch (e) {
                    grunt.log.error(e);
                    grunt.fail.warn('_.template failed to compile in file "' + filepath + '"');
                }

                if (options.prettify) {
                    compiled = compiled.replace(new RegExp('\n', 'g'), '');
                }

                namespaces = [].concat(namespaces, nsInfo.declaration.split('\n'));

                return nsInfo.namespace + '["' + name + '"] = ' + compiled + ';';
            });

            if (output.length < 1) {
                grunt.log.warn('Destination not written because compiled files were empty.');
            } else {
                if (options.templateNamespace !== false) {
                    output.unshift(_.uniq(namespaces).join('\n'));
                }

                output.unshift('(function (App, undefined) {');
                output.push('})( this["' + options.namespace + '"]);');

                grunt.file.write(f.dest, output.join(grunt.util.normalizelf(options.separator)));
                grunt.log.writeln('File "' + f.dest + '" created.');
            }
        });

    });

    grunt.registerMultiTask('include', 'Inserts all required script tags into the html at a special marked insertion point', function () {
        var _ = require('lodash');
        var options = this.options({
            separator: grunt.util.linefeed,
            attributes: '',
            webRoot: 'web/'
        });
        var reRoot = new RegExp('^' + options.webRoot);

        this.files.forEach(function (f) {
            var output = f.src.filter(function (path) {
                if (!grunt.file.exists(path)) {
                    grunt.log.warn('Source file "' + filepath + '" not found.');
                    return false;
                } else {
                    return true;
                }
            }).map(function (path) {
                return _.compact(['<script', options.attributes, 'src="' + path.replace(reRoot, '') + '"></script>']).join(' ');
            });

            if (output.length < 1) {
                grunt.log.warn('Destination not written because compiled files were empty.');
            } else {
                grunt.file.write(f.dest, output.join(grunt.util.normalizelf(options.separator)));
                grunt.log.writeln('File "' + f.dest + '" created.');
            }
        });

    });

};
<commit_msg>Compile only example less for dev in grunt file<commit_after>module.exports = function (grunt) {
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-copy');

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        watch: {
            less: {
                files: ['src/styles/**/*.less'],
                tasks: ['less:dev']
            },
            js: {
                files: ['src/scripts/**/*.js'],
                tasks: ['concat', 'uglify']
            }
        },
        less: {
            dev: {
                files: {
                    'examples/css/narwhal.css': 'src/styles/narwhal.less'
                }
            },
            // to generate distribution uncompressed versions
            uncompressed: {
                options: {
                    compress: false,
                    ieCompat: true,
                    yuicompress: false // Off until calc() bug is addressed.  https://github.com/yui/yuicompressor/issues/59
                },
                files: {
                    'dist/narwhal.css': 'src/styles/narwhal.less',
                    'examples/css/narwhal.css': 'src/styles/narwhal.less'
                }
            },
            production: {
                options: {
                    compress: true,
                    ieCompat: true,
                    yuicompress: false // Off until calc() bug is addressed.  https://github.com/yui/yuicompressor/issues/59
                },
                files: {
                    'dist/narwhal.min.css': 'src/styles/narwhal.less',
                    'examples/css/narwhal.min.css': 'src/styles/narwhal.less'
                }
            }
        },
        scripts: {
            libs: [
            ],
            core: [
                'src/scripts/core/narwhal.js',
                'src/scripts/core/cartesian.js',
                'src/scripts/core/**/*.js'
            ],
            vis: [
                'src/scripts/visualizations/**/*.js'
            ]
        },
        include: {
            core: {
                src: ['<%= scripts.core %>'],
                dest: 'web/include/login/scripts.html'
            }
        },
        concat: {
            all: {
                src: ['<%= scripts.core %>', '<%= scripts.vis %>'],
                dest: 'dist/narwhal.js'
            }
        },
        uglify: {
            options: {
                sourceMap: function (fileName) {
                    return fileName.replace(/\.js$/, '.map');
                },
                banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
                        '<%= grunt.template.today("yyyy-mm-dd") %> */\n'
            },
            production: {
                files: {
                    'dist/narwhal.min.js': ['dist/narwhal.js']
                }
            }
        }
    });

    // Default task.
    grunt.registerTask('default', ['less:dev', 'watch:less']);
    grunt.registerTask('production', ['concat', 'uglify', 'less:production']);
    grunt.registerTask('linked', ['concat', 'uglify', 'less:uncompressed', 'less:production', 'watch']);

    grunt.registerMultiTask('templates', 'Compiles underscore templates', function () {
        var _ = require('lodash');
        var options = this.options({
            separator: grunt.util.linefeed,
            templateSettings: {},
            templateNamespace: 'tmpl'
        });

        function getNamespace(ns) {
            var output = [];
            var curPath = 'App';
            if (ns !== 'App') {
                var nsParts = ns.split('.');
                nsParts.forEach(function(curPart, index) {
                    if (curPart !== 'App') {
                        curPath += '[' + JSON.stringify(curPart) + ']';
                        output.push(curPath + ' = ' + curPath + ' || {};');
                    }
                });
            }

            return {
                namespace: curPath,
                declaration: output.join('\n')
            };
        }

        this.files.forEach(function (f) {
            var namespaces = [];
            var output = f.src.filter(function (path) {
                if (!grunt.file.exists(path)) {
                    grunt.log.warn('Source file "' + filepath + '" not found.');
                    return false;
                } else {
                    return true;
                }
            }).map(function (path) {
                var src = grunt.file.read(path);
                var parts = path.match(/.+\/(?:template|tmpl)(?:s)?\/(.+).html/i)[1].split('/');
                var ns = _.initial(parts).join('.').replace(/(-.)/g, function () {
                    return arguments[0].substring(1).toUpperCase();
                });
                var name = _.last(parts).replace(/(-.)/g, function () {
                    return arguments[0].substring(1).toUpperCase();
                });
                var nsInfo = getNamespace([options.templateNamespace, ns].join('.'));
                var compiled;

                try {
                    compiled = _.template(src, false, options.templateSettings).source;
                } catch (e) {
                    grunt.log.error(e);
                    grunt.fail.warn('_.template failed to compile in file "' + filepath + '"');
                }

                if (options.prettify) {
                    compiled = compiled.replace(new RegExp('\n', 'g'), '');
                }

                namespaces = [].concat(namespaces, nsInfo.declaration.split('\n'));

                return nsInfo.namespace + '["' + name + '"] = ' + compiled + ';';
            });

            if (output.length < 1) {
                grunt.log.warn('Destination not written because compiled files were empty.');
            } else {
                if (options.templateNamespace !== false) {
                    output.unshift(_.uniq(namespaces).join('\n'));
                }

                output.unshift('(function (App, undefined) {');
                output.push('})( this["' + options.namespace + '"]);');

                grunt.file.write(f.dest, output.join(grunt.util.normalizelf(options.separator)));
                grunt.log.writeln('File "' + f.dest + '" created.');
            }
        });

    });

    grunt.registerMultiTask('include', 'Inserts all required script tags into the html at a special marked insertion point', function () {
        var _ = require('lodash');
        var options = this.options({
            separator: grunt.util.linefeed,
            attributes: '',
            webRoot: 'web/'
        });
        var reRoot = new RegExp('^' + options.webRoot);

        this.files.forEach(function (f) {
            var output = f.src.filter(function (path) {
                if (!grunt.file.exists(path)) {
                    grunt.log.warn('Source file "' + filepath + '" not found.');
                    return false;
                } else {
                    return true;
                }
            }).map(function (path) {
                return _.compact(['<script', options.attributes, 'src="' + path.replace(reRoot, '') + '"></script>']).join(' ');
            });

            if (output.length < 1) {
                grunt.log.warn('Destination not written because compiled files were empty.');
            } else {
                grunt.file.write(f.dest, output.join(grunt.util.normalizelf(options.separator)));
                grunt.log.writeln('File "' + f.dest + '" created.');
            }
        });

    });

};
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var path = require('path');
var assert = require('yeoman-generator').assert;
var helpers = require('yeoman-generator').test;

var Xml2Js = require('xml2js');
var validator = require('validator');
var chai = require('chai'),
  expect = chai.expect;

// generator prompt responses
var promptResponses = {};

/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */

describe('office:app', function(){

  // set timeouts to 5s
  this.timeout(10000);

  var projectEscapedName = 'my-first-addin';
  var manifestFileName = 'manifest-' + projectEscapedName + '.xml';

  describe('runs mail subgenerator', function(){

    beforeEach(function(done){
      // setup generator prompts
      var options = {
        name: 'My First Addin',
        rootPath: '',
        type: 'mail',
        tech: 'html',
        outlookForm: ['mail-read', 'mail-compose', 'appointment-read', 'appointment-compose'],
        'skip-install': true
      };

      // run the generator
      helpers.run(path.join(__dirname, '../generators/app'))
        .withPrompts(options)
        .on('end', done);
    });

    it('manifest-*.xml is for mail addin', function(done){

      // verify manifest-*.xml exists
      assert.file(manifestFileName);

      // load manifest-*.xml as JSON
      var parser = new Xml2Js.Parser();
      fs.readFile(manifestFileName, 'utf8', function(err, manifestContent){
        parser.parseString(manifestContent, function(err, manifestJson){

          // check addin type
          expect(manifestJson.OfficeApp.$['xsi:type']).to.equal('MailApp');

          done();
        });
      });

    });

  }); // describe('runs mail subgenerator')

  describe('runs taskpane subgenerator', function(){

    beforeEach(function(done){
      // setup generator prompts
      var options = {
        name: 'My First Addin',
        rootPath: '',
        type: 'taskpane',
        tech: 'ng-adal',
        clients: ['Document', 'Workbook'],
        'skip-install': true
      };

      // run the generator
      helpers.run(path.join(__dirname, '../generators/app'))
        .withPrompts(options)
        .on('end', done);
    });

    it('manifest-*.xml is for taskpane addin', function(done){

      // verify manifest-*.xml exists
      assert.file(manifestFileName);

      // load manifest-*.xml as JSON
      var parser = new Xml2Js.Parser();
      fs.readFile(manifestFileName, 'utf8', function(err, manifestContent){
        parser.parseString(manifestContent, function(err, manifestJson){

          // check addin type
          expect(manifestJson.OfficeApp.$['xsi:type']).to.equal('TaskPaneApp');

          done();
        });
      });

    });

  }); // describe('runs content subgenerator')

  describe('runs content subgenerator', function(){

    beforeEach(function(done){
      // setup generator prompts
      var options = {
        name: 'My First Addin',
        rootPath: '',
        type: 'content',
        tech: 'html',
        clients: ['Document', 'Workbook'],
        'skip-install': true
      };

      // run the generator
      helpers.run(path.join(__dirname, '../generators/app'))
        .withPrompts(options)
        .on('end', done);
    });

    it('manifest-*.xml is for content addin', function(done){

      // verify manifest-*.xml exists
      assert.file(manifestFileName);

      // load manifest-*.xml as JSON
      var parser = new Xml2Js.Parser();
      fs.readFile(manifestFileName, 'utf8', function(err, manifestContent){
        parser.parseString(manifestContent, function(err, manifestJson){

          // check addin type
          expect(manifestJson.OfficeApp.$['xsi:type']).to.equal('ContentApp');

          done();
        });
      });

    });

  }); // describe('runs content subgenerator')

}); // describe('office:app')
<commit_msg>Fixing mail generator test in app.js<commit_after>'use strict';

var fs = require('fs');
var path = require('path');
var assert = require('yeoman-generator').assert;
var helpers = require('yeoman-generator').test;

var Xml2Js = require('xml2js');
var validator = require('validator');
var chai = require('chai'),
  expect = chai.expect;

// generator prompt responses
var promptResponses = {};

/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */

describe('office:app', function(){

  // set timeouts to 5s
  this.timeout(10000);

  var projectEscapedName = 'my-first-addin';
  var manifestFileName = 'manifest-' + projectEscapedName + '.xml';

  describe('runs mail subgenerator', function(){

    beforeEach(function(done){
      // setup generator prompts
      var options = {
        name: 'My First Addin',
        rootPath: '',
        type: 'mail',
        tech: 'html',
        extensionPoint: [
          'MessageReadCommandSurface',
          'MessageComposeCommandSurface',
          'AppointmentAttendeeCommandSurface',
          'AppointmentOrganizerCommandSurface'
        ],
        'skip-install': true
      };

      // run the generator
      helpers.run(path.join(__dirname, '../generators/app'))
        .withPrompts(options)
        .on('end', done);
    });

    it('manifest-*.xml is for mail addin', function(done){

      // verify manifest-*.xml exists
      assert.file(manifestFileName);

      // load manifest-*.xml as JSON
      var parser = new Xml2Js.Parser();
      fs.readFile(manifestFileName, 'utf8', function(err, manifestContent){
        parser.parseString(manifestContent, function(err, manifestJson){

          // check addin type
          expect(manifestJson.OfficeApp.$['xsi:type']).to.equal('MailApp');

          done();
        });
      });

    });

  }); // describe('runs mail subgenerator')

  describe('runs taskpane subgenerator', function(){

    beforeEach(function(done){
      // setup generator prompts
      var options = {
        name: 'My First Addin',
        rootPath: '',
        type: 'taskpane',
        tech: 'ng-adal',
        clients: ['Document', 'Workbook'],
        'skip-install': true
      };

      // run the generator
      helpers.run(path.join(__dirname, '../generators/app'))
        .withPrompts(options)
        .on('end', done);
    });

    it('manifest-*.xml is for taskpane addin', function(done){

      // verify manifest-*.xml exists
      assert.file(manifestFileName);

      // load manifest-*.xml as JSON
      var parser = new Xml2Js.Parser();
      fs.readFile(manifestFileName, 'utf8', function(err, manifestContent){
        parser.parseString(manifestContent, function(err, manifestJson){

          // check addin type
          expect(manifestJson.OfficeApp.$['xsi:type']).to.equal('TaskPaneApp');

          done();
        });
      });

    });

  }); // describe('runs content subgenerator')

  describe('runs content subgenerator', function(){

    beforeEach(function(done){
      // setup generator prompts
      var options = {
        name: 'My First Addin',
        rootPath: '',
        type: 'content',
        tech: 'html',
        clients: ['Document', 'Workbook'],
        'skip-install': true
      };

      // run the generator
      helpers.run(path.join(__dirname, '../generators/app'))
        .withPrompts(options)
        .on('end', done);
    });

    it('manifest-*.xml is for content addin', function(done){

      // verify manifest-*.xml exists
      assert.file(manifestFileName);

      // load manifest-*.xml as JSON
      var parser = new Xml2Js.Parser();
      fs.readFile(manifestFileName, 'utf8', function(err, manifestContent){
        parser.parseString(manifestContent, function(err, manifestJson){

          // check addin type
          expect(manifestJson.OfficeApp.$['xsi:type']).to.equal('ContentApp');

          done();
        });
      });

    });

  }); // describe('runs content subgenerator')

}); // describe('office:app')
<|endoftext|>