<commit_before>describe('[module]smart-complete', function() {
  var $scUtil, $timeout, $q;
  beforeEach(module('smart-complete'));
  beforeEach(inject(function(_$scUtil_, _$timeout_, _$q_) {
    $scUtil = _$scUtil_;
    $timeout = _$timeout_;
    $q = _$q_;
  }));

  describe('[service]$scUtil', function() {

    describe('[method]$debounce', function() {
      it('debouncedFunc should be called once in 300ms', function() {
        var spyFunc = jasmine.createSpy('spyFunc'),
          debouncedFunc = $scUtil.debounce(spyFunc);
        debouncedFunc();
        debouncedFunc();
        $timeout.flush(200);
        debouncedFunc();
        $timeout.flush(300);
        $timeout.verifyNoPendingTasks();
        expect(spyFunc).toHaveBeenCalledTimes(1);
      });

      it('debouncedFuncWith100ms should be called once in 100ms', function() {
        var spyFunc = jasmine.createSpy('spyFunc'),
          debouncedFuncWith100ms = $scUtil.debounce(spyFunc, 100);
        debouncedFuncWith100ms();
        expect(spyFunc).not.toHaveBeenCalled();
        debouncedFuncWith100ms();
        $timeout.flush(50);
        expect(spyFunc).not.toHaveBeenCalled();
        debouncedFuncWith100ms();
        $timeout.flush(100);
        $timeout.verifyNoPendingTasks();
        expect(spyFunc).toHaveBeenCalledTimes(1);
      });

      it('debouncedFuncWithPromise should return a promise', function() {
        var deferred = $q.defer(),
          spyPromiseFunc = jasmine.createSpy('spyPromiseFunc').and.returnValue(deferred.promise),
          debouncedFuncWithPromise = $scUtil.debounce(spyPromiseFunc),
          res;
        debouncedFuncWithPromise().then(function(data) {
          res = data;
        });
        expect(res).toBeUndefined();
        deferred.resolve('ok');
        $timeout.flush(300);
        expect(res).toBe('ok');
      });
    });

    describe('[method]noopSearchFunc', function() {
      it('noopSearchFunc should return a promise with value []', function() {
        $scUtil.noopSearchFunc().then(function(data) {
          expect(data).toEqual([]);
        });
        $timeout.flush(10);
      });
    });

  });

  describe('[directive]smartComplete', function() {
    var $compile, scope;
    beforeEach(inject(function(_$compile_, _$rootScope_) {
      $compile = _$compile_;
      scope = _$rootScope_.$new();
    }));

    it('should throw error if tagName is not input or textarea', function() {
      expect(function() {
        $compile('

')(scope);
      }).toThrow('tagName must be input or textarea');
    });

    it('after init, should create an empty hidden dom with ul.smart-complete', function() {
      var $$input = $compile('<input smart-complete>')(scope);
      scope.$digest();
      var $$completor = $$input.next();
      expect($$completor[0].tagName).toBe('UL');
      expect($$completor.hasClass('smart-complete')).toBe(true);
      expect($$completor.is(':hidden')).toBe(true);
      expect($$completor.html()).toBe('');
    });

    describe('event', function() {
      var $$input, $$completor,
        selectedClass = 'current-selected';

      beforeEach(function() {
        scope.searchFunc = function(s) {
          return $q.when(['hate', 'love', 'like'].filter(function(item) {
            return item.indexOf(s) !== -1;
          }));
        };
        scope.sep = false;

        $$input = $('<input smart-complete="searchFunc" sc-sep="sep">');
        $('body').html($$input);
        $compile($$input)(scope);
        $$completor = $$input.next();
      });

      function triggerInputKeyup(which) {
        which = which || 0;
        var keyUpEvt = $.Event('keyup');
        keyUpEvt.which = which;
        $$input.trigger(keyUpEvt);
      }

      function triggerInputKeyDown(which) {
        which = which || 0;
        var keyDownEvt = $.Event('keydown');
        keyDownEvt.which = which;
        $$input.trigger(keyDownEvt);
      }

      it('should show 3 items when click input', function() {
        $$input.trigger('click');
        scope.$digest();
        expect($$completor.children().length).toBe(3);
      });

      it('should show 2 items when type key "l"', function() {
        $$input.val('l');
        triggerInputKeyup(0);
        $timeout.flush(300);
        expect($$completor.children().length).toBe(2);
      });

      it('should show 1 item when input word "ha"', function() {
        $$input.val('ha');
        triggerInputKeyup(0);
        $timeout.flush(300);
        expect($$completor.children().length).toBe(1);
      });

      it('item should be selected when type key up', function() {
        $$input.trigger('click');
        scope.$digest();
        triggerInputKeyDown(38);
        expect($$completor.children().last().hasClass(selectedClass)).toBe(true);
        expect($$input.val()).toBe('like');
      });

      it('when sep is ",", should show 2 items when iput word "hate,l"', function() {
        scope.sep = ',';
        scope.$digest();
        $$input.val('hate,l');
        triggerInputKeyup(0);
        $timeout.flush(300);
        expect($$completor.children().length).toBe(2);
        triggerInputKeyDown(40);
        expect($$completor.children().first().hasClass(selectedClass)).toBe(true);
        expect($$input.val()).toBe('hate,love');
        triggerInputKeyDown(40);
        expect($$completor.children().last().hasClass(selectedClass)).toBe(true);
        expect($$input.val()).toBe('hate,like');
      });

      it('completor should be hidden after type key enter', function() {
        $$input.trigger('click');
        scope.$digest();
        expect($$completor.is(':visible')).toBe(true);
        triggerInputKeyDown(13);
        expect($$completor.is(':visible')).toBe(false);
      });

      it('mouseenter, mouseleave and click on item', function() {
        $$input.trigger('click');
        scope.$digest();
        var firstItem = $$completor.children().first();
        firstItem.trigger('mouseenter');
        expect(firstItem.hasClass(selectedClass)).toBe(true);
        firstItem.trigger('mouseleave');
        expect(firstItem.hasClass(selectedClass)).toBe(false);
        firstItem.trigger('click');
        expect($$completor.is(':visible')).toBe(false);
        expect($$input.val()).toBe('hate');
      });
    });

    describe('textarea', function() {
      var $$textarea, $$completor,
        selectedClass = 'current-selected';

      beforeEach(function() {
        scope.searchFunc = function(s) {
          return $q.when(['hate', 'love', 'like'].filter(function(item) {
            return item.indexOf(s) !== -1;
          }));
        };
        scope.sep = false;

        $$textarea = $('<textarea smart-complete="searchFunc" sc-sep="sep"></textarea>');
        $('body').html($$textarea);
        $compile($$textarea)(scope);
        $$completor = $$textarea.next();
      });
      it('textarea is ok', function() {
        $$textarea.trigger('click');
        scope.$digest();
        expect($$completor.is(':visible')).toBe(true);
        expect($$completor.children().length).toBe(3);
        var firstItem = $$completor.children().first();
        firstItem.trigger('mouseenter');
        expect(firstItem.hasClass(selectedClass)).toBe(true);
      });
    });

  });

});
<commit_msg>update smart-complete.js unit test<commit_after>describe('[module]smart-complete', function() {
  var $scUtil, $timeout, $q;
  beforeEach(module('smart-complete'));
  beforeEach(inject(function(_$scUtil_, _$timeout_, _$q_) {
    $scUtil = _$scUtil_;
    $timeout = _$timeout_;
    $q = _$q_;
  }));

  describe('[service]$scUtil', function() {

    describe('[method]$debounce', function() {
      it('debouncedFunc should be called once in 300ms', function() {
        var spyFunc = jasmine.createSpy('spyFunc'),
          debouncedFunc = $scUtil.debounce(spyFunc);
        debouncedFunc();
        debouncedFunc();
        $timeout.flush(200);
        debouncedFunc();
        $timeout.flush(300);
        $timeout.verifyNoPendingTasks();
        expect(spyFunc).toHaveBeenCalledTimes(1);
      });

      it('debouncedFuncWith100ms should be called once in 100ms', function() {
        var spyFunc = jasmine.createSpy('spyFunc'),
          debouncedFuncWith100ms = $scUtil.debounce(spyFunc, 100);
        debouncedFuncWith100ms();
        expect(spyFunc).not.toHaveBeenCalled();
        debouncedFuncWith100ms();
        $timeout.flush(50);
        expect(spyFunc).not.toHaveBeenCalled();
        debouncedFuncWith100ms();
        $timeout.flush(100);
        $timeout.verifyNoPendingTasks();
        expect(spyFunc).toHaveBeenCalledTimes(1);
      });

      it('debouncedFuncWithPromise should return a promise', function() {
        var deferred = $q.defer(),
          spyPromiseFunc = jasmine.createSpy('spyPromiseFunc').and.returnValue(deferred.promise),
          debouncedFuncWithPromise = $scUtil.debounce(spyPromiseFunc),
          res;
        debouncedFuncWithPromise().then(function(data) {
          res = data;
        });
        expect(res).toBeUndefined();
        deferred.resolve('ok');
        $timeout.flush(300);
        expect(res).toBe('ok');
      });
    });

    describe('[method]noopSearchFunc', function() {
      it('noopSearchFunc should return a promise with value []', function() {
        $scUtil.noopSearchFunc().then(function(data) {
          expect(data).toEqual([]);
        });
        $timeout.flush(10);
      });
    });

  });

  describe('[directive]smartComplete', function() {
    var $compile, scope;
    beforeEach(inject(function(_$compile_, _$rootScope_) {
      $compile = _$compile_;
      scope = _$rootScope_.$new();
    }));

    it('should throw error if tagName is not input or textarea', function() {
      expect(function() {
        $compile('

')(scope);
      }).toThrow('tagName must be input or textarea');
    });

    it('after init, should create an empty hidden dom with ul.smart-complete', function() {
      var $$input = $compile('<input smart-complete>')(scope);
      scope.$digest();
      var $$completor = $$input.next();
      expect($$completor[0].tagName).toBe('UL');
      expect($$completor.hasClass('smart-complete')).toBe(true);
      expect($$completor.is(':hidden')).toBe(true);
      expect($$completor.html()).toBe('');
    });

    describe('event', function() {
      var $$input, $$completor,
        selectedClass = 'current-selected';

      beforeEach(function() {
        scope.searchFunc = function(s) {
          return $q.when(['hate', 'love', 'like'].filter(function(item) {
            console.log(item.indexOf(s));
            return item.indexOf(s) !== -1;
          }));
        };
        scope.sep = false;
        scope.width = '100%';
        scope.height = '200';
        scope.itemClickCb = function() {};
        scope.enterCb = function() {};

        $$input = $([
          '<input style="width: 200px" smart-complete="searchFunc"',
          'sc-sep="sep"',
          'sc-width="width"',
          'sc-height="height"',
          'sc-item-click-cb="itemClickCb"',
          'sc-enter-cb="enterCb"',
          '>'
        ].join(' '));
        $('body').html($$input);
        $compile($$input)(scope);
        $$completor = $$input.next();
      });

      function triggerInputKeyup(which) {
        which = which || 0;
        var keyUpEvt = $.Event('keyup');
        keyUpEvt.which = which;
        $$input.trigger(keyUpEvt);
      }

      function triggerInputKeyDown(which) {
        which = which || 0;
        var keyDownEvt = $.Event('keydown');
        keyDownEvt.which = which;
        $$input.trigger(keyDownEvt);
      }

      it('should show 3 items when click input', function() {
        $$input.trigger('click');
        scope.$digest();
        expect($$completor.children().length).toBe(3);
      });

      it('should show 2 items when type key "l"', function() {
        $$input.val('l');
        triggerInputKeyDown('l'.charCodeAt());
        triggerInputKeyup('l'.charCodeAt());
        $timeout.flush(300);
        expect($$completor.children().length).toBe(2);
      });

      it('should show 1 item when input word "ha"', function() {
        $$input.val('ha');
        triggerInputKeyup(0);
        $timeout.flush(300);
        expect($$completor.children().length).toBe(1);
      });

      it('item should be selected when type key up', function() {
        $$input.trigger('click');
        scope.$digest();
        triggerInputKeyDown(38);
        expect($$completor.children().last().hasClass(selectedClass)).toBe(true);
        expect($$input.val()).toBe('like');
      });

      it('when sep is ",", should show 2 items when iput word "hate,l"', function() {
        scope.sep = ',';
        scope.$digest();
        $$input.val('hate,l');
        triggerInputKeyup(0);
        $timeout.flush(300);
        expect($$completor.children().length).toBe(2);
        triggerInputKeyDown(40);
        expect($$completor.children().first().hasClass(selectedClass)).toBe(true);
        expect($$input.val()).toBe('hate,love');
        triggerInputKeyDown(40);
        expect($$completor.children().last().hasClass(selectedClass)).toBe(true);
        expect($$input.val()).toBe('hate,like');
      });

      it('completor should be hidden after type key enter', function() {
        $$input.trigger('click');
        scope.$digest();
        expect($$completor.is(':visible')).toBe(true);
        triggerInputKeyDown(13);
        $timeout.flush(10);
        expect($$completor.is(':visible')).toBe(false);
      });

      it('completor should be hidden after type key tab', function() {
        $$input.trigger('click');
        scope.$digest();
        expect($$completor.is(':visible')).toBe(true);
        triggerInputKeyDown(9);
        triggerInputKeyup(9);
        $timeout.flush(300);
        expect($$completor.is(':visible')).toBe(false);
      });

      it('mouseenter, mouseleave and click on item', function() {
        $$input.trigger('click');
        scope.$digest();
        var firstItem = $$completor.children().first();
        firstItem.trigger('mouseenter');
        expect(firstItem.hasClass(selectedClass)).toBe(true);
        firstItem.trigger('mouseleave');
        expect(firstItem.hasClass(selectedClass)).toBe(false);
        firstItem.trigger('click');
        $timeout.flush(10);
        expect($$completor.is(':visible')).toBe(false);
        expect($$input.val()).toBe('hate');
      });

      it('items shuould be empty when smart-complete return $q.reject', function() {
        scope.searchFunc = function() {
          return $q.reject();
        };
        $$input.trigger('click');
        scope.$digest();
        expect($$completor.children().length).toBe(0);
      });

      it('left of completor should be 112', function() {
        scope.width = '100';
        scope.sep = ',';
        $$completor.css({
          position: 'absolute'
        });
        $$input.val('loooooooooooooooooooooooooooooooooooooooooooogword,hate,like');
        $$input.trigger('click');
        $$input.caret('pos', 56);
        scope.$digest();
        expect($$completor.position().left).toBe(112);
        triggerInputKeyDown(38);
        triggerInputKeyup(38);
        $timeout.flush(300);
        expect($$input.val()).toBe('loooooooooooooooooooooooooooooooooooooooooooogword,hate,like');
      });
    });

    describe('textarea', function() {
      var $$textarea, $$completor,
        selectedClass = 'current-selected';

      beforeEach(function() {
        scope.searchFunc = function(s) {
          return $q.when(['hate', 'love', 'like'].filter(function(item) {
            return item.indexOf(s) !== -1;
          }));
        };
        scope.sep = false;

        $$textarea = $('<textarea smart-complete="searchFunc" sc-sep="sep"></textarea>');
        $('body').html($$textarea);
        $compile($$textarea)(scope);
        $$completor = $$textarea.next();
      });
      it('textarea is ok', function() {
        $$textarea.trigger('click');
        scope.$digest();
        expect($$completor.is(':visible')).toBe(true);
        expect($$completor.children().length).toBe(3);
        var firstItem = $$completor.children().first();
        firstItem.trigger('mouseenter');
        expect(firstItem.hasClass(selectedClass)).toBe(true);
      });
    });

  });

});
<|endoftext|>


<commit_before>/*global module:false*/
module.exports = function(grunt) {

  var banner = ['/*!',
                 ' * Sir Trevor JS v<%= pkg.version %>',
                 ' *',
                 ' * Released under the MIT license',
                 ' * www.opensource.org/licenses/MIT',
                 ' *',
                 ' * <%= grunt.template.today("yyyy-mm-dd") %>',
                 ' */\n\n'
                ].join("\n");

  grunt.loadNpmTasks('grunt-rigger');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-sass');

  grunt.initConfig({

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

    'jasmine' : {
      'sir-trevor': {
        src : 'sir-trevor.js',
        options: {
          vendor: ['bower_components/jquery/jquery.js',
                   'bower_components/underscore/underscore.js',
                   'bower_components/Eventable/eventable.js'],
          specs : 'spec/javascripts/**/*.spec.js',
          helpers : ['spec/javascripts/helpers/*.js',
                     'bower_components/sinonjs/sinon.js',
                     'bower_components/jasmine-sinon/lib/jasmine-sinon.js']
        }
      }
    },

    rig: {
      build: {
        options: {
          banner: banner
        },
        files: {
          'sir-trevor.js': ['src/sir-trevor.js']
        }
      }
    },

    uglify: {
      options: {
        mangle: false,
        banner: banner
      },
      standard: {
        files: {
          'sir-trevor.min.js': ['sir-trevor.js']
        }
      }
    },

    watch: {
      scripts: {
        files: ['src/*.js', 'src/**/*.js', 'src/sass/*.scss'],
        tasks: ['sass', 'rig']
      }
    },

    jshint: {
      all: ['sir-trevor.js'],

      options: {
        curly: true,
        eqeqeq: true,
        immed: false,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        browser: true
      },
      globals: {
        jQuery: true,
        _: true,
        console: true
      }
    },

    sass: {
      dist: {
        files: {
          'sir-trevor.css': 'src/sass/main.scss'
        }
      }
    }

  });

  // Default task.
  grunt.loadNpmTasks('grunt-contrib-jasmine');

  grunt.registerTask('travis', ['rig', 'jasmine']);

  grunt.registerTask('default', ['sass', 'rig', 'uglify', 'jasmine']);

  grunt.registerTask('jasmine-browser', ['server','watch']);

};
<commit_msg>SH-1575 Update the jasmine tests to output the test results in junit format so we can setup a bamboo plan for this code to run tests on each push.<commit_after>/*global module:false*/
module.exports = function(grunt) {

  var banner = ['/*!',
                 ' * Sir Trevor JS v<%= pkg.version %>',
                 ' *',
                 ' * Released under the MIT license',
                 ' * www.opensource.org/licenses/MIT',
                 ' *',
                 ' * <%= grunt.template.today("yyyy-mm-dd") %>',
                 ' */\n\n'
                ].join("\n");

  grunt.loadNpmTasks('grunt-rigger');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-sass');

  grunt.initConfig({

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

    'jasmine' : {
      'sir-trevor': {
        src : 'sir-trevor.js',
        options: {
          vendor: ['bower_components/jquery/jquery.js',
                   'bower_components/underscore/underscore.js',
                   'bower_components/Eventable/eventable.js'],
          specs : 'spec/javascripts/**/*.spec.js',
          helpers : ['spec/javascripts/helpers/*.js',
                     'bower_components/sinonjs/sinon.js',
                     'bower_components/jasmine-sinon/lib/jasmine-sinon.js'],
          junit : {
            path : './jasmine-test-reports',
            consolidate : true
          }
        }
      }
    },

    rig: {
      build: {
        options: {
          banner: banner
        },
        files: {
          'sir-trevor.js': ['src/sir-trevor.js']
        }
      }
    },

    uglify: {
      options: {
        mangle: false,
        banner: banner
      },
      standard: {
        files: {
          'sir-trevor.min.js': ['sir-trevor.js']
        }
      }
    },

    watch: {
      scripts: {
        files: ['src/*.js', 'src/**/*.js', 'src/sass/*.scss'],
        tasks: ['sass', 'rig']
      }
    },

    jshint: {
      all: ['sir-trevor.js'],

      options: {
        curly: true,
        eqeqeq: true,
        immed: false,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        browser: true
      },
      globals: {
        jQuery: true,
        _: true,
        console: true
      }
    },

    sass: {
      dist: {
        files: {
          'sir-trevor.css': 'src/sass/main.scss'
        }
      }
    }

  });

  // Default task.
  grunt.loadNpmTasks('grunt-contrib-jasmine');

  grunt.registerTask('travis', ['rig', 'jasmine']);

  grunt.registerTask('default', ['sass', 'rig', 'uglify', 'jasmine']);

  grunt.registerTask('jasmine-browser', ['server','watch']);

};
<|endoftext|>


<commit_before>module.exports = function (grunt) {
    'use strict';

    var globalConfig = {
        src: 'src',
        dest: 'dist',
        timestamp: Date.now(),
        jsVendorHeaderFiles: [
            '<%= globalConfig.src %>/js/vendor/header/*.js'
        ],
        jsVendorFooterFiles: [
            '<%= globalConfig.src %>/js/vendor/footer/jquery.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/transition.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/alert.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/button.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/carousel.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/collapse.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/dropdown.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/modal.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/tooltip.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/popover.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/scrollspy.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/tab.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/affix.js',
            '<%= globalConfig.src %>/js/vendor/footer/*.js' // include all other files from vendor directory
        ]
    };

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

        jshint: {
            options: {
                jshintrc: '.jshintrc'
            },
            files: [
                '<%= globalConfig.src %>/js/*.js',
                'Gruntfile.js'
            ]
        },
        clean: {
            pages: ['<%= globalConfig.dest %>/pages/**/*.html'],
            js: ['<%= globalConfig.dest %>/js/**/*.js', '<%= globalConfig.dest %>/js/**/*.map'],
            css: ['<%= globalConfig.dest %>/css/**/*.css', '<%= globalConfig.dest %>/css/**/*.map'],
            images: ['<%= globalConfig.dest %>/images/**/*.{png,jpg,gif,svg}', '<%= globalConfig.dest %>/images-content/**/*.{png,jpg,gif,svg}']
        },
        assemble: {
            options: {
                layoutdir: '<%= globalConfig.src %>/templates/layouts',
                flatten: true,
                layout: 'default.hbs',
                partials: '<%= globalConfig.src %>/templates/partials/*.hbs'
            },
            page: {
                files: {
                    '<%= globalConfig.dest %>/pages/': ['<%= globalConfig.src %>/templates/pages/*.hbs']
                }
            }
        },
        concat: {
            options: {
                sourceMap: true
            },
            vendor: {
                files: {
                    '<%= globalConfig.dest %>/js/vendors.header.lib.js': globalConfig.jsVendorHeaderFiles,
                    '<%= globalConfig.dest %>/js/vendors.footer.lib.js': globalConfig.jsVendorFooterFiles
                }
            },
            app: {
                files: {
                    '<%= globalConfig.dest %>/js/app.js': ['<%= globalConfig.src %>/js/*.js']
                }
            }
        },
        uglify: {
            dist: {
                options: {
                    mangle: false,
                    beautify: false,
                    preserveComments: /^!|@preserve|@license|@cc_on/i,
                    sourceMap: true
                },
                files: {
                    '<%= globalConfig.dest %>/js/vendors.header.lib.js': globalConfig.jsVendorHeaderFiles,
                    '<%= globalConfig.dest %>/js/vendors.footer.lib.js': globalConfig.jsVendorFooterFiles,
                    '<%= globalConfig.dest %>/js/app.js': '<%= globalConfig.src %>/js/*.js'
                }
            }
        },
        sass: {
            dev: {
                options: {
                    sourceMap: true,
                    outputStyle: 'expanded'
                },
                files: [
                    {
                        expand: true,
                        cwd: '<%= globalConfig.src %>/sass',
                        src: ['**/*.scss'],
                        dest: '<%= globalConfig.dest %>/css',
                        ext: '.css'
                    }
                ]
            },
            dist: {
                options: {
                    sourceMap: true,
                    outputStyle: 'compressed'
                },
                files: [
                    {
                        expand: true,
                        cwd: '<%= globalConfig.src %>/sass',
                        src: ['**/*.scss'],
                        dest: '<%= globalConfig.dest %>/css',
                        ext: '.css'
                    }
                ]
            }
        },
        imagemin: {
            images: {
                options: {
                    optimizationLevel: 3
                },
                files: [{
                    expand: true,
                    cwd: '<%= globalConfig.src %>/images',
                    src: ['**/*.{png,jpg,gif,svg}'],
                    dest: '<%= globalConfig.dest %>/images/'
                }]
            },
            'images-content': {
                options: {
                    optimizationLevel: 3
                },
                files: [{
                    expand: true,
                    cwd: '<%= globalConfig.src %>/images-content',
                    src: ['**/*.{png,jpg,gif,svg}'],
                    dest: '<%= globalConfig.dest %>/images-content/'
                }]
            }
        },
        sprite: {
            all: {
                src: '<%= globalConfig.dest %>/images/sprites/*.{png,jpg,gif}',
                destCss: '<%= globalConfig.src %>/sass/_base/_sprites.scss',
                dest: '<%= globalConfig.dest %>/images/sprites.png',
                imgPath: '../images/sprites.png?v=<%= globalConfig.timestamp %>',
                'cssVarMap': function (sprite) {
                    var str = sprite.name,
                        res = str.split("_"),
                        spritePrefix = 'sprite-';

                    if (res[res.length - 1] === 'hover') {
                        sprite.name = spritePrefix + res.slice(0, -1).join("_") + '.sprite--active';
                    } else {
                        sprite.name = spritePrefix + sprite.name;
                    }
                }
            }
        },
        postcss: {
            options: {
                map: {
                    inline: false // save all sourcemaps as separate files
                },
                processors: [
                    require('autoprefixer')({browsers: ['> 1%', 'last 2 versions', 'Firefox ESR'], remove: false})
                ]
            },
            dist: {
                src: '<%= globalConfig.dest %>/css/**/*.css'
            }
        },
        watch: {
            options: {
                spawn: false
            },
            assemble: {
                files: ['<%= globalConfig.src %>/templates/**/*.hbs'],
                tasks: ['clean:pages', 'assemble']
            },
            images: {
                files: ['<%= globalConfig.src %>/images/**/*.{png,jpg,gif,svg}', '<%= globalConfig.src %>/images-content/**/*.{png,jpg,gif,svg}'],
                tasks: ['clean:images', 'imagemin', 'sprite', 'sass:dev', 'postcss']
            },
            'concat-app': {
                files: ['<%= globalConfig.src %>/js/*.js'],
                tasks: ['jshint', 'concat:app']
            },
            'concat-vendor': {
                files: ['<%= globalConfig.src %>/js/vendor/**/*.js'],
                tasks: ['concat:vendor']
            },
            sass: {
                files: ['<%= globalConfig.src %>/sass/**/*.scss'],
                tasks: ['clean:css', 'sass:dev', 'postcss']
            }
        },
        browserSync: {
            bsFiles: {
                src : [
                    '<%= globalConfig.dest %>/css/*.css',
                    '<%= globalConfig.dest %>/js/*.js',
                    '<%= globalConfig.dest %>/pages/*.html'
                ]
            },
            options: {
                watchTask: true,
                server: {
                    baseDir: "./"
                }
            }
        }
    });

    /* load every plugin in package.json */
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('assemble');
    grunt.loadNpmTasks('grunt-sass');
    grunt.loadNpmTasks('grunt-spritesmith');
    grunt.loadNpmTasks('grunt-contrib-imagemin');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-postcss');
    grunt.loadNpmTasks('grunt-browser-sync');

    /* grunt tasks */
    grunt.registerTask('default', [
        'jshint',
        'clean',
        'assemble',
        'concat',
        'imagemin',
        'sprite',
        'sass:dev',
        'postcss',
        'browserSync',
        'watch'
    ]);
    grunt.registerTask('build', [
        'jshint',
        'clean',
        'assemble',
        'uglify:dist',
        'imagemin',
        'sprite',
        'sass:dist',
        'postcss'
    ]);

};<commit_msg>Use `true` as a safe (default) value for spawn option.<commit_after>module.exports = function (grunt) {
    'use strict';

    var globalConfig = {
        src: 'src',
        dest: 'dist',
        timestamp: Date.now(),
        jsVendorHeaderFiles: [
            '<%= globalConfig.src %>/js/vendor/header/*.js'
        ],
        jsVendorFooterFiles: [
            '<%= globalConfig.src %>/js/vendor/footer/jquery.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/transition.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/alert.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/button.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/carousel.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/collapse.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/dropdown.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/modal.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/tooltip.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/popover.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/scrollspy.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/tab.js',
            //'<%= globalConfig.src %>/js/vendor/footer/bootstrap/affix.js',
            '<%= globalConfig.src %>/js/vendor/footer/*.js' // include all other files from vendor directory
        ]
    };

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

        jshint: {
            options: {
                jshintrc: '.jshintrc'
            },
            files: [
                '<%= globalConfig.src %>/js/*.js',
                'Gruntfile.js'
            ]
        },
        clean: {
            pages: ['<%= globalConfig.dest %>/pages/**/*.html'],
            js: ['<%= globalConfig.dest %>/js/**/*.js', '<%= globalConfig.dest %>/js/**/*.map'],
            css: ['<%= globalConfig.dest %>/css/**/*.css', '<%= globalConfig.dest %>/css/**/*.map'],
            images: ['<%= globalConfig.dest %>/images/**/*.{png,jpg,gif,svg}', '<%= globalConfig.dest %>/images-content/**/*.{png,jpg,gif,svg}']
        },
        assemble: {
            options: {
                layoutdir: '<%= globalConfig.src %>/templates/layouts',
                flatten: true,
                layout: 'default.hbs',
                partials: '<%= globalConfig.src %>/templates/partials/*.hbs'
            },
            page: {
                files: {
                    '<%= globalConfig.dest %>/pages/': ['<%= globalConfig.src %>/templates/pages/*.hbs']
                }
            }
        },
        concat: {
            options: {
                sourceMap: true
            },
            vendor: {
                files: {
                    '<%= globalConfig.dest %>/js/vendors.header.lib.js': globalConfig.jsVendorHeaderFiles,
                    '<%= globalConfig.dest %>/js/vendors.footer.lib.js': globalConfig.jsVendorFooterFiles
                }
            },
            app: {
                files: {
                    '<%= globalConfig.dest %>/js/app.js': ['<%= globalConfig.src %>/js/*.js']
                }
            }
        },
        uglify: {
            dist: {
                options: {
                    mangle: false,
                    beautify: false,
                    preserveComments: /^!|@preserve|@license|@cc_on/i,
                    sourceMap: true
                },
                files: {
                    '<%= globalConfig.dest %>/js/vendors.header.lib.js': globalConfig.jsVendorHeaderFiles,
                    '<%= globalConfig.dest %>/js/vendors.footer.lib.js': globalConfig.jsVendorFooterFiles,
                    '<%= globalConfig.dest %>/js/app.js': '<%= globalConfig.src %>/js/*.js'
                }
            }
        },
        sass: {
            dev: {
                options: {
                    sourceMap: true,
                    outputStyle: 'expanded'
                },
                files: [
                    {
                        expand: true,
                        cwd: '<%= globalConfig.src %>/sass',
                        src: ['**/*.scss'],
                        dest: '<%= globalConfig.dest %>/css',
                        ext: '.css'
                    }
                ]
            },
            dist: {
                options: {
                    sourceMap: true,
                    outputStyle: 'compressed'
                },
                files: [
                    {
                        expand: true,
                        cwd: '<%= globalConfig.src %>/sass',
                        src: ['**/*.scss'],
                        dest: '<%= globalConfig.dest %>/css',
                        ext: '.css'
                    }
                ]
            }
        },
        imagemin: {
            images: {
                options: {
                    optimizationLevel: 3
                },
                files: [{
                    expand: true,
                    cwd: '<%= globalConfig.src %>/images',
                    src: ['**/*.{png,jpg,gif,svg}'],
                    dest: '<%= globalConfig.dest %>/images/'
                }]
            },
            'images-content': {
                options: {
                    optimizationLevel: 3
                },
                files: [{
                    expand: true,
                    cwd: '<%= globalConfig.src %>/images-content',
                    src: ['**/*.{png,jpg,gif,svg}'],
                    dest: '<%= globalConfig.dest %>/images-content/'
                }]
            }
        },
        sprite: {
            all: {
                src: '<%= globalConfig.dest %>/images/sprites/*.{png,jpg,gif}',
                destCss: '<%= globalConfig.src %>/sass/_base/_sprites.scss',
                dest: '<%= globalConfig.dest %>/images/sprites.png',
                imgPath: '../images/sprites.png?v=<%= globalConfig.timestamp %>',
                'cssVarMap': function (sprite) {
                    var str = sprite.name,
                        res = str.split("_"),
                        spritePrefix = 'sprite-';

                    if (res[res.length - 1] === 'hover') {
                        sprite.name = spritePrefix + res.slice(0, -1).join("_") + '.sprite--active';
                    } else {
                        sprite.name = spritePrefix + sprite.name;
                    }
                }
            }
        },
        postcss: {
            options: {
                map: {
                    inline: false // save all sourcemaps as separate files
                },
                processors: [
                    require('autoprefixer')({browsers: ['> 1%', 'last 2 versions', 'Firefox ESR'], remove: false})
                ]
            },
            dist: {
                src: '<%= globalConfig.dest %>/css/**/*.css'
            }
        },
        watch: {
            options: {
                spawn: true
            },
            assemble: {
                files: ['<%= globalConfig.src %>/templates/**/*.hbs'],
                tasks: ['clean:pages', 'assemble']
            },
            images: {
                files: ['<%= globalConfig.src %>/images/**/*.{png,jpg,gif,svg}', '<%= globalConfig.src %>/images-content/**/*.{png,jpg,gif,svg}'],
                tasks: ['clean:images', 'imagemin', 'sprite', 'sass:dev', 'postcss']
            },
            'concat-app': {
                files: ['<%= globalConfig.src %>/js/*.js'],
                tasks: ['jshint', 'concat:app']
            },
            'concat-vendor': {
                files: ['<%= globalConfig.src %>/js/vendor/**/*.js'],
                tasks: ['concat:vendor']
            },
            sass: {
                files: ['<%= globalConfig.src %>/sass/**/*.scss'],
                tasks: ['clean:css', 'sass:dev', 'postcss']
            }
        },
        browserSync: {
            bsFiles: {
                src : [
                    '<%= globalConfig.dest %>/css/*.css',
                    '<%= globalConfig.dest %>/js/*.js',
                    '<%= globalConfig.dest %>/pages/*.html'
                ]
            },
            options: {
                watchTask: true,
                server: {
                    baseDir: "./"
                }
            }
        }
    });

    /* load every plugin in package.json */
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('assemble');
    grunt.loadNpmTasks('grunt-sass');
    grunt.loadNpmTasks('grunt-spritesmith');
    grunt.loadNpmTasks('grunt-contrib-imagemin');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-postcss');
    grunt.loadNpmTasks('grunt-browser-sync');

    /* grunt tasks */
    grunt.registerTask('default', [
        'jshint',
        'clean',
        'assemble',
        'concat',
        'imagemin',
        'sprite',
        'sass:dev',
        'postcss',
        'browserSync',
        'watch'
    ]);
    grunt.registerTask('build', [
        'jshint',
        'clean',
        'assemble',
        'uglify:dist',
        'imagemin',
        'sprite',
        'sass:dist',
        'postcss'
    ]);

};<|endoftext|>


<commit_before>/**
 * Converts a string that was serialized with jQuery.param back to the object.
 *
 * @param {String} str
 *  The string containing the URL params. If string starts with a `?` mark
 *  (default when using `location.search`) it will be removed prior to
 *  parsing it.
 *
 * @return {Object}
 *
 * @example:
 *
 *  parseParams('foo=bar&foo=bar2&bar=foo');
 *  parseParams('foo[]=bar&foo[]=bar2&bar[]=foo');
 *
 *  // Both invocation return:
 *  //
 *  //  {
 *  //      "foo": [
 *  //          "bar",
 *  //          "bar2"
 *  //      ],
 *  //      "bar": "foo"
 *  //  }
 */
var parseParams = function parseParamsFn(str) {

    if (str.charAt(0) === "?") {
        str = str.substr(1);
    }

    var obj         = {}, pair,
        pairs       = str.split("&"),
        prevkey, prev, arg,
        injectParam = function(key, val) {

            var firstBracket = key.indexOf('[');

            if (firstBracket === -1) {
                if (obj[key] !== undefined) {
                    if (!(obj[key] instanceof Array)) {
                        obj[key] = [ obj[key] ];
                    }

                    obj[key].push(val);

                } else {
                    obj[key] = val;
                }

                return;
            }

            prevkey = key.substring(0, firstBracket);
            key     = key.substr(firstBracket);
            prev    = obj;

            key.replace(/\[([^\]]+)?\]/g, function(chunk, idx/*, pos*/) {
                var newobj, newkey;

                if (chunk.match(/\[\d*\]/)) {
                    newobj = prev[prevkey] || [];
                    newkey = idx || '[]';

                } else {
                    newobj = prev[prevkey] || {};
                    newkey = idx;
                }

                if (prevkey === '[]') {
                    prev.push(newobj);

                } else {
                    prev[prevkey] = newobj;
                }

                prev    = newobj;
                prevkey = newkey;
            });

            if (prevkey === '[]') {
                prev.push(val);

            } else {
                prev[prevkey] = val;
            }
        };

    // If not string was passed in, return an empty object
    if (!str) {
        return obj;
    }

    for( arg = 0; arg < pairs.length; arg++ ) {
        pair = pairs[ arg ].split( "=" );
        injectParam(
            decodeURIComponent(String(pair[0]).replace(/\+/g, " ")),
            decodeURIComponent(String(pair[1]).replace(/\+/g, " "))
        );
    }

    return obj;
};

export default parseParams;
<commit_msg>Fix to parseUrlParams when single string value is used on input<commit_after>/**
 * Converts a string that was serialized with jQuery.param back to the object.
 *
 * @param {String} str
 *  The string containing the URL params. If string starts with a `?` mark
 *  (default when using `location.search`) it will be removed prior to
 *  parsing it.
 *
 * @return {Object}
 *
 * @example:
 *
 *  parseParams('foo=bar&foo=bar2&bar=foo');
 *  parseParams('foo[]=bar&foo[]=bar2&bar[]=foo');
 *
 *  // Both invocation return:
 *  //
 *  //  {
 *  //      "foo": [
 *  //          "bar",
 *  //          "bar2"
 *  //      ],
 *  //      "bar": "foo"
 *  //  }
 */
var parseParams = function parseParamsFn(str) {

    if (str.charAt(0) === "?") {
        str = str.substr(1);
    }

    var obj         = {}, pair,
        pairs       = str.split("&"),
        prevkey, prev, arg,
        injectParam = function(key, val) {

            var firstBracket = key.indexOf('[');

            if (firstBracket === -1) {
                if (obj[key] !== undefined) {
                    if (!(obj[key] instanceof Array)) {
                        obj[key] = [ obj[key] ];
                    }

                    obj[key].push(val);

                } else {
                    obj[key] = val;
                }

                return;
            }

            prevkey = key.substring(0, firstBracket);
            key     = key.substr(firstBracket);
            prev    = obj;

            key.replace(/\[([^\]]+)?\]/g, function(chunk, idx/*, pos*/) {
                var newobj, newkey;

                if (chunk.match(/\[\d*\]/)) {
                    newobj = prev[prevkey] || [];
                    newkey = idx || '[]';

                } else {
                    newobj = prev[prevkey] || {};
                    newkey = idx;
                }

                if (prevkey === '[]') {
                    prev.push(newobj);

                } else {
                    prev[prevkey] = newobj;
                }

                prev    = newobj;
                prevkey = newkey;
            });

            if (prevkey === '[]') {
                prev.push(val);

            } else {
                prev[prevkey] = val;
            }
        };

    // If not string was passed in, return an empty object
    if (!str) {
        return obj;
    }

    for( arg = 0; arg < pairs.length; arg++ ) {
        pair = pairs[ arg ].split( "=" );
        injectParam(
            decodeURIComponent(String(pair[0]).replace(/\+/g, " ")),
            decodeURIComponent(String(pair[1] || "").replace(/\+/g, " "))
        );
    }

    return obj;
};

export default parseParams;
<|endoftext|>


<commit_before>module.exports = function(grunt) {
  grunt.initConfig({
    clean: ["dist"],

    watch: {
      elm: {
        files: ["Dreamwriter/**/*.elm", "*.elm"],
        tasks: ["elm"]
      },
      stylus: {
        files: ["src/stylesheets/**/*.styl"],
        tasks: ["stylesheets"]
      },
      html: {
        files: ["src/index.html"],
        tasks: ["copy:index"]
      },
      images: {
        files: ["src/images/*.*"],
        tasks: ["copy:images"]
      },
      fonts: {
        files: ["src/fonts/*.*"],
        tasks: ["copy:fonts"]
      },
      bower: {
        files: ["bower.json"],
        tasks: ["browserifyBower"]
      },
      dist: {
        files: ["dist/**/*", "!dist/dreamwriter.appcache", "!dist/cache/**/*"],
        tasks: ["copy:cache", "appcache"]
      }
    },

    connect: {
      "static": {
        options: {
          port: 8000,
          base: 'dist'
        }
      }
    },

    copy: {
      index: {
        src: "src/index.html",
        dest: "dist/index.html"
      },
      images: {
        expand: true,
        cwd: "src",
        src: "images/**",
        dest: "dist/"
      },
      fonts: {
        expand: true,
        cwd: "src",
        src: "fonts/**",
        dest: "dist/"
      },
      cache: {
        expand: true,
        cwd: "dist",
        src: ["*.*", "fonts/*.*", "images/*.*"],
        dest: "dist/cache/"
      }
    },

    stylus: {
      compile: {
        options: {
          paths: ["src/stylesheets/*.styl"]
        },
        files: {
          "dist/dreamwriter.css": ["src/stylesheets/*.styl"]
        }
      }
    },

    autoprefixer: {
      dreamwriter: {
        options: {
          map: true
        },
        src: "dist/dreamwriter.css",
        dest: "dist/dreamwriter.css"
      }
    },

    elm: {
      dreamwriter: {
        srcDir: "Dreamwriter",
        files: {
          "dist": "App.elm"
        }
      }
    },

    browserify: {
      options: {
        transform: ['browserify-mustache', 'coffeeify'],
        watch: true,
        browserifyOptions: {
          debug: true
        }
      },
      dreamwriter: {
        extensions: ['.coffee', '.mustache', '.json'],
        src: ["./src/**/*.coffee", "./src/**/*.mustache", "./src/**/*.json"],
        dest: "dist/bootstrap-elm.js"
      }
    },

    browserifyBower: {
      options: {
        file: "dist/vendor.js",
        forceResolve: {
          "FileSaver.js": "FileSaver.min.js",
          "db.js": "src/db.js"
        }
      },
      vendor: {}
    },

    appcache: {
      options: {
        basePath: 'dist'
      },
      all: {
        dest: 'dist/dreamwriter.appcache',
        cache: {
          patterns: ['dist/cache/**/*']
        },
        network: '*',
        fallback: [
          '/                               /cache/index.html',
          '/index.html                     /cache/index.html',
          '/dreamwriter.css                /cache/dreamwriter.css',
          '/dreamwriter.css.map            /cache/dreamwriter.css.map',
          '/dreamwriter.js                 /cache/dreamwriter.js',
          '/vendor.js                      /cache/vendor.js',
          '/fonts/robot-slab-bold.woff     /cache/fonts/roboto-slab-bold.woff',
          '/fonts/roboto-slab-regular.woff /cache/fonts/roboto-slab-regular.woff',
          '/fonts/ubuntu.woff              /cache/fonts/ubuntu.woff',
          '/images/dlogo.png               /cache/images/dlogo.png',
          '/images/dropbox-logo.png        /cache/images/dropbox-logo.png',
          '/images/favicon.ico             /cache/images/favicon.ico',
          '/images/quarter-backdrop.jpg    /cache/images/quarter-backdrop.jpg']
      }
    }
  });

  ["grunt-contrib-watch", "grunt-contrib-clean", "grunt-elm", "grunt-browserify", "grunt-browserify-bower", "grunt-contrib-copy", "grunt-contrib-connect", "grunt-contrib-stylus", "grunt-autoprefixer", "grunt-appcache"].forEach(function(plugin) {
    grunt.loadNpmTasks(plugin);
  });

  grunt.registerTask("build", ["stylesheets", "browserifyBower", "browserify", "elm", "copy", "appcache"]);
  grunt.registerTask("stylesheets", ["stylus", "autoprefixer"]);

  grunt.registerTask("default", ["clean", "build", "connect", "watch"]);
};<commit_msg>Update app cache settings to use App.js instead of dreamwriter.js<commit_after>module.exports = function(grunt) {
  grunt.initConfig({
    clean: ["dist"],

    watch: {
      elm: {
        files: ["Dreamwriter/**/*.elm", "*.elm"],
        tasks: ["elm"]
      },
      stylus: {
        files: ["src/stylesheets/**/*.styl"],
        tasks: ["stylesheets"]
      },
      html: {
        files: ["src/index.html"],
        tasks: ["copy:index"]
      },
      images: {
        files: ["src/images/*.*"],
        tasks: ["copy:images"]
      },
      fonts: {
        files: ["src/fonts/*.*"],
        tasks: ["copy:fonts"]
      },
      bower: {
        files: ["bower.json"],
        tasks: ["browserifyBower"]
      },
      dist: {
        files: ["dist/**/*", "!dist/dreamwriter.appcache", "!dist/cache/**/*"],
        tasks: ["copy:cache", "appcache"]
      }
    },

    connect: {
      "static": {
        options: {
          port: 8000,
          base: 'dist'
        }
      }
    },

    copy: {
      index: {
        src: "src/index.html",
        dest: "dist/index.html"
      },
      images: {
        expand: true,
        cwd: "src",
        src: "images/**",
        dest: "dist/"
      },
      fonts: {
        expand: true,
        cwd: "src",
        src: "fonts/**",
        dest: "dist/"
      },
      cache: {
        expand: true,
        cwd: "dist",
        src: ["*.*", "fonts/*.*", "images/*.*"],
        dest: "dist/cache/"
      }
    },

    stylus: {
      compile: {
        options: {
          paths: ["src/stylesheets/*.styl"]
        },
        files: {
          "dist/dreamwriter.css": ["src/stylesheets/*.styl"]
        }
      }
    },

    autoprefixer: {
      dreamwriter: {
        options: {
          map: true
        },
        src: "dist/dreamwriter.css",
        dest: "dist/dreamwriter.css"
      }
    },

    elm: {
      dreamwriter: {
        srcDir: "Dreamwriter",
        files: {
          "dist": "App.elm"
        }
      }
    },

    browserify: {
      options: {
        transform: ['browserify-mustache', 'coffeeify'],
        watch: true,
        browserifyOptions: {
          debug: true
        }
      },
      dreamwriter: {
        extensions: ['.coffee', '.mustache', '.json'],
        src: ["./src/**/*.coffee", "./src/**/*.mustache", "./src/**/*.json"],
        dest: "dist/bootstrap-elm.js"
      }
    },

    browserifyBower: {
      options: {
        file: "dist/vendor.js",
        forceResolve: {
          "FileSaver.js": "FileSaver.min.js",
          "db.js": "src/db.js"
        }
      },
      vendor: {}
    },

    appcache: {
      options: {
        basePath: 'dist'
      },
      all: {
        dest: 'dist/dreamwriter.appcache',
        cache: {
          patterns: ['dist/cache/**/*']
        },
        network: '*',
        fallback: [
          '/                               /cache/index.html',
          '/index.html                     /cache/index.html',
          '/dreamwriter.css                /cache/dreamwriter.css',
          '/dreamwriter.css.map            /cache/dreamwriter.css.map',
          '/App.js                         /cache/App.js',
          '/vendor.js                      /cache/vendor.js',
          '/fonts/robot-slab-bold.woff     /cache/fonts/roboto-slab-bold.woff',
          '/fonts/roboto-slab-regular.woff /cache/fonts/roboto-slab-regular.woff',
          '/fonts/ubuntu.woff              /cache/fonts/ubuntu.woff',
          '/images/dlogo.png               /cache/images/dlogo.png',
          '/images/dropbox-logo.png        /cache/images/dropbox-logo.png',
          '/images/favicon.ico             /cache/images/favicon.ico',
          '/images/quarter-backdrop.jpg    /cache/images/quarter-backdrop.jpg']
      }
    }
  });

  ["grunt-contrib-watch", "grunt-contrib-clean", "grunt-elm", "grunt-browserify", "grunt-browserify-bower", "grunt-contrib-copy", "grunt-contrib-connect", "grunt-contrib-stylus", "grunt-autoprefixer", "grunt-appcache"].forEach(function(plugin) {
    grunt.loadNpmTasks(plugin);
  });

  grunt.registerTask("build", ["stylesheets", "browserifyBower", "browserify", "elm", "copy", "appcache"]);
  grunt.registerTask("stylesheets", ["stylus", "autoprefixer"]);

  grunt.registerTask("default", ["clean", "build", "connect", "watch"]);
};<|endoftext|>


<commit_before>"use strict";

var modRewrite = require('connect-modrewrite');

module.exports = function (grunt) {

    var base = grunt.option("baseDir") || "";

    grunt.initConfig({

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

        config: {
            outputDir: "dist/",
            applicationFiles: grunt.file.readJSON("scripts.json").application,
            vendorFiles: grunt.file.readJSON("scripts.json").vendor
        },

        connect: {
            options: {
                hostname: "0.0.0.0",
                port: 8000,
                base: base
            },
            server: {
                options: {
                    livereload: true,
                    middleware: function ( connect, options, middlewares ) {
                        var rules = [
                            "^/app/[^\.]*$ /app/index.html"
                        ];
                        middlewares.unshift( modRewrite( rules ) );
                        return middlewares;
                    }
                }
            },
            servertest: {
                options: {
                    keepalive: false,
                    livereload: false,
                    middleware: function ( connect, options, middlewares ) {
                        var rules = [
                            "^/app/[^\.]*$ /app/index.html"
                        ];
                        middlewares.unshift( modRewrite( rules ) );
                        return middlewares;
                    }
                }
            }
        },

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

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

        jshint: {
            options: {
                jshintrc: ".jshintrc"
            },
            dist: {
                src: ["<%= config.applicationFiles %>"]
            }
        },

        jasmine: {
            options: {
                specs: ["tests/unit/**/*.js"],
                keepRunner: true,
            },
            development: {
                src: ["<%= config.applicationFiles %>"],
                options: {
                    vendor: ["<%= config.vendorFiles %>"],
                    helpers:["app/components/angular-mocks/angular-mocks.js"],
                    template: require("grunt-template-jasmine-istanbul"),
                    templateOptions: {
                        coverage: "coverage/coverage.json",
                        report: [
                            {
                                type: "html",
                                options: {
                                    dir: "coverage/html"
                                }
                            },
                            {
                                type: "text-summary"
                            }
                        ]
                    }
                }
            },
            stage: {
                src: ["<%= config.outputDir %>js/app.js", "app/components/angular-mocks/angular-mocks.js"]
            },
            production: {
                src: ["<%= config.outputDir %>js/app.min.js", "app/components/angular-mocks/angular-mocks.js"]
            }
        },

        protractor: {
            options: {
                configFile: "node_modules/protractor/referenceConf.js",
                keepAlive: false,
                noColor: false
            },
            dist: {
                options: {
                    configFile: "tests/e2e/protractor.conf.js"
                }
            }
        },

        protractor_webdriver: {
            dist: {
                options: {
                    command: "webdriver-manager start",
                }
            }
        },

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

        uglify: {
            options: {
                mangle: true,
                enclose: {},
                compress: {
                    drop_console: true
                },
                sourceMap: true,
                sourceMapIn: "tmp/js/app.js.map",
                sourceMapIncludeSources: true
            },
            production: {
                files: {
                    "<%= config.outputDir %>js/app.min.js": ["tmp/js/app.js"]
                }
            }
        },

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

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

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

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

    });

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

    grunt.registerTask("build:production", [
        "clean:beforeBuild",
        "jshint",
        "minify",
        "jasmine:production",
        "less:production",
        "copy",
        "processhtml:production",
        "yuidoc",
        "clean:afterBuild"
    ]);

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

    grunt.registerTask("minify", [
        "concat:production",
        "uglify"
    ]);

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

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

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

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

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

};
<commit_msg>minor clean up to gruntfile<commit_after>"use strict";

var modRewrite = require('connect-modrewrite');

module.exports = function (grunt) {

    var base = grunt.option("baseDir") || "";

    grunt.initConfig({

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

        config: {
            outputDir: "dist/",
            applicationFiles: grunt.file.readJSON("scripts.json").application,
            vendorFiles: grunt.file.readJSON("scripts.json").vendor
        },

        connect: {
            options: {
                hostname: "0.0.0.0",
                port: 8000,
                base: base
            },
            server: {
                options: {
                    livereload: true,
                    middleware: function ( connect, options, middlewares ) {
                        var rules = [
                            "^/app/[^\.]*$ /app/index.html"
                        ];
                        middlewares.unshift( modRewrite( rules ) );
                        return middlewares;
                    }
                }
            },
            servertest: {
                options: {
                    keepalive: false,
                    livereload: false,
                    middleware: function ( connect, options, middlewares ) {
                        var rules = [
                            "^/app/[^\.]*$ /app/index.html"
                        ];
                        middlewares.unshift( modRewrite( rules ) );
                        return middlewares;
                    }
                }
            }
        },

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

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

        jshint: {
            options: {
                jshintrc: ".jshintrc"
            },
            dist: {
                src: ["<%= config.applicationFiles %>"]
            }
        },

        jasmine: {
            options: {
                specs: ["tests/unit/**/*.js"],
                keepRunner: true,
            },
            development: {
                src: ["<%= config.applicationFiles %>"],
                options: {
                    vendor: ["<%= config.vendorFiles %>"],
                    helpers:["app/components/angular-mocks/angular-mocks.js"],
                    template: require("grunt-template-jasmine-istanbul"),
                    templateOptions: {
                        coverage: "coverage/coverage.json",
                        report: [
                            {
                                type: "html",
                                options: {
                                    dir: "coverage/html"
                                }
                            },
                            {
                                type: "text-summary",
                                options: {
                                    dir: "coverage/text-summary",
                                    file: "text-summary.txt"
                                }
                            },
                            {
                                type: "text-summary"
                            }
                        ]
                    }
                }
            },
            stage: {
                src: ["<%= config.outputDir %>js/app.js", "app/components/angular-mocks/angular-mocks.js"]
            },
            production: {
                src: ["<%= config.outputDir %>js/app.min.js", "app/components/angular-mocks/angular-mocks.js"]
            }
        },

        protractor: {
            options: {
                configFile: "node_modules/protractor/referenceConf.js",
                keepAlive: false,
                noColor: false
            },
            dist: {
                options: {
                    configFile: "tests/e2e/protractor.conf.js"
                }
            }
        },

        protractor_webdriver: {
            dist: {
                options: {
                    command: "webdriver-manager start --standalone",
                }
            }
        },

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

        uglify: {
            options: {
                mangle: true,
                enclose: {},
                compress: {
                    drop_console: true
                },
                sourceMap: true,
                sourceMapIn: "tmp/js/app.js.map",
                sourceMapIncludeSources: true
            },
            production: {
                files: {
                    "<%= config.outputDir %>js/app.min.js": ["tmp/js/app.js"]
                }
            }
        },

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

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

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

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

    });

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

    grunt.registerTask("build:production", [
        "clean:beforeBuild",
        "jshint",
        "minify",
        "jasmine:production",
        "less:production",
        "copy",
        "processhtml:production",
        "yuidoc",
        "clean:afterBuild"
    ]);

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

    grunt.registerTask("minify", [
        "concat:production",
        "uglify"
    ]);

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

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

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

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

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

};
<|endoftext|>


<commit_before>export default {
  name: 'header',

  lookup(req, res, options) {
    let found;

    if (typeof req !== 'undefined') {
      let headers = req.headers;
      if (!headers) return found;

      let lookupExist = options.lookupHeader !== undefined;
      let lookupHeader = lookupExist ? headers[options.lookupHeader] : undefined;

      let locales = [];
      let acceptLanguage = lookupHeader || headers['accept-language'];

      if (acceptLanguage) {
        let lngs = [], i, m;
        const rgx = /(([a-z]{2})-?([A-Z]{2})?)\s*;?\s*(q=([0-9.]+))?/gi;

        do {
          m = rgx.exec(acceptLanguage);
          if (m) {
            const lng = m[1], weight = m[5] || '1', q = Number(weight);
            if (lng && !isNaN(q)) {
              lngs.push({lng, q});
            }
          }
        } while (m);

        lngs.sort(function(a,b) {
          return b.q - a.q;
        });

        for (i = 0; i < lngs.length; i++) {
          locales.push(lngs[i].lng);
        }

        if (locales.length) found = locales;
      }
    }

    return found;
  }
};
<commit_msg>rollback lookupHeader checking<commit_after>export default {
  name: 'header',

  lookup(req, res, options) {
    let found;

    if (typeof req !== 'undefined') {
      let headers = req.headers;
      if (!headers) return found;

      let locales = [];
      let acceptLanguage = options.lookupHeader ? headers[options.lookupHeader] : headers['accept-language'];

      if (acceptLanguage) {
        let lngs = [], i, m;
        const rgx = /(([a-z]{2})-?([A-Z]{2})?)\s*;?\s*(q=([0-9.]+))?/gi;

        do {
          m = rgx.exec(acceptLanguage);
          if (m) {
            const lng = m[1], weight = m[5] || '1', q = Number(weight);
            if (lng && !isNaN(q)) {
              lngs.push({lng, q});
            }
          }
        } while (m);

        lngs.sort(function(a,b) {
          return b.q - a.q;
        });

        for (i = 0; i < lngs.length; i++) {
          locales.push(lngs[i].lng);
        }

        if (locales.length) found = locales;
      }
    }

    return found;
  }
};
<|endoftext|>


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

  grunt.initConfig({
    'json-minify': {
      build: {
        files: 'dist/mathmaps/**/*.json'
      }
    },
    gitclone: {
      'speech-rule-engine': {
        options: {
          repository: 'https://github.com/zorkow/speech-rule-engine.git',
          branch: 'v2.0.0-beta.3',
          cwd: '.'
        }
      }
    },
    'uglify': {
      mathmaps: {
        files: {
          'dist/mathmaps/mathmaps_ie.js': 'dist/mathmaps/mathmaps_ie.js'
        }
      },
      build: {
        files: {
          'dist/accessibility-menu.js': 'extensions/accessibility-menu.js',
          'dist/explorer.js': 'extensions/explorer.js',
          'dist/auto-collapse.js': 'extensions/auto-collapse.js',
          'dist/collapsible.js': 'extensions/collapsible.js',
          'dist/semantic-enrich.js': 'extensions/semantic-enrich.js'
        },
        options: {
          beautify: {
            ascii_only: true
          }
        }
      }
    },
    shell: {
      clean_dist: {
        command: 'rm -rf dist'
      },
      make_dist: {
        command: 'mkdir -p dist'
      },
      clean_sre: {
        command: 'rm -rf speech-rule-engine'
      },
      clean_node: {
        command: 'rm -rf node_modules'
      },
      prepare: {
        command: [
          '<%= shell.clean_dist.command %>',
          '<%= shell.make_dist.command %>'
        ].join('&&')
      },
      clean: {
        command: [
          '<%= shell.clean_node.command %>',
          '<%= shell.clean_sre.command %>',
          '<%= shell.clean_dist.command %>'
        ].join('&&')
      },
      compile: {
        command: [
          'npm install',
          'npm install --only=dev',
          'npm install wicked-good-xpath',
          'make mathjax'
        ].join('&&'),
        options: {
          execOptions: {
            cwd: 'speech-rule-engine'
          }
        }
      },
      copy: [
        'cp speech-rule-engine/lib/mathjax-sre.js dist/mathjax-sre.js',
        'cp speech-rule-engine/node_modules/wicked-good-xpath/dist/wgxpath.install.js dist/',
        'cp -R speech-rule-engine/src/mathmaps dist/',
        'cp extensions/*.ogg dist/',
        'cp extensions/*.mp3 dist/',
        'rm dist/mathmaps/math_map.js'
      ].join('&&')
    }
  });

  // Cloning git repos.
  grunt.loadNpmTasks('grunt-git');
  // Run shell commands.
  grunt.loadNpmTasks('grunt-shell');
  // Minify JSON files.
  grunt.loadNpmTasks('grunt-json-minify');
  // Minify regular files.
  grunt.loadNpmTasks('grunt-contrib-uglify');

  grunt.registerTask('default', [
    'shell:prepare',
    'gitclone',
    'shell:compile',
    'shell:copy',
    'json-minify',
    'uglify',
    'shell:clean_sre'
  ]);

};
<commit_msg>Updates grunt file to handle json files with .js extension.<commit_after>module.exports = function(grunt) {

  grunt.initConfig({
    'json-minify': {
      build: {
        files: 'dist/mathmaps/*/*.js'
      }
    },
    gitclone: {
      'speech-rule-engine': {
        options: {
          repository: 'https://github.com/zorkow/speech-rule-engine.git',
          branch: 'v2.0.0-beta.3',
          cwd: '.'
        }
      }
    },
    'uglify': {
      mathmaps: {
        files: {
          'dist/mathmaps/mathmaps_ie.js': 'dist/mathmaps/mathmaps_ie.js'
        }
      },
      build: {
        files: {
          'dist/accessibility-menu.js': 'extensions/accessibility-menu.js',
          'dist/explorer.js': 'extensions/explorer.js',
          'dist/auto-collapse.js': 'extensions/auto-collapse.js',
          'dist/collapsible.js': 'extensions/collapsible.js',
          'dist/semantic-enrich.js': 'extensions/semantic-enrich.js'
        },
        options: {
          beautify: {
            ascii_only: true
          }
        }
      }
    },
    shell: {
      clean_dist: {
        command: 'rm -rf dist'
      },
      make_dist: {
        command: 'mkdir -p dist'
      },
      clean_sre: {
        command: 'rm -rf speech-rule-engine'
      },
      clean_node: {
        command: 'rm -rf node_modules'
      },
      prepare: {
        command: [
          '<%= shell.clean_dist.command %>',
          '<%= shell.make_dist.command %>'
        ].join('&&')
      },
      clean: {
        command: [
          '<%= shell.clean_node.command %>',
          '<%= shell.clean_sre.command %>',
          '<%= shell.clean_dist.command %>'
        ].join('&&')
      },
      compile: {
        command: [
          'npm install',
          'npm install --only=dev',
          'npm install wicked-good-xpath',
          'make mathjax'
        ].join('&&'),
        options: {
          execOptions: {
            cwd: 'speech-rule-engine'
          }
        }
      },
      copy: [
        'cp speech-rule-engine/lib/mathjax-sre.js dist/mathjax-sre.js',
        'cp speech-rule-engine/node_modules/wicked-good-xpath/dist/wgxpath.install.js dist/',
        'cp -R speech-rule-engine/src/mathmaps dist/',
        'cp extensions/*.ogg dist/',
        'cp extensions/*.mp3 dist/',
        'rm dist/mathmaps/math_map.js'
      ].join('&&')
    }
  });

  // Cloning git repos.
  grunt.loadNpmTasks('grunt-git');
  // Run shell commands.
  grunt.loadNpmTasks('grunt-shell');
  // Minify JSON files.
  grunt.loadNpmTasks('grunt-json-minify');
  // Minify regular files.
  grunt.loadNpmTasks('grunt-contrib-uglify');

  grunt.registerTask('default', [
    'shell:prepare',
    'gitclone',
    'shell:compile',
    'shell:copy',
    'json-minify',
    'uglify',
    'shell:clean_sre'
  ]);

};
<|endoftext|>


<commit_before>module.exports = function (grunt) {
  'use strict';

  // Force use of Unix newlines
  grunt.util.linefeed = '\n';

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

    wuzzle: {
      less: 'src/wuzzle.less',
      css: 'dist/wuzzle.css',
      cssMin: 'dist/wuzzle.min.css',
      banner: '/*! Wuzzle <%= pkg.version %> | <%= _.pluck(pkg.licenses, "type") %> | http//git.io/wuzzle */\n'
    },

    // Tasks configuration
    clean: {
      dist: ['dist']
    },

    less: {
      dist: {
        files: {
          '<%= wuzzle.css %>': '<%= wuzzle.less %>'
        }
      },
      distMin: {
        options: {
          cleancss: true,
          report: 'min'
        },
        files: {
          '<%= wuzzle.cssMin %>': '<%= wuzzle.css %>'
        }
      }
    },

    csscomb: {
      sort: {
        options: {
          sortOrder: '.csscomb.json'
        },
        files: {
          '<%= wuzzle.css %>': ['<%= wuzzle.css %>'],
        }
      }
    },

    usebanner: {
      dist: {
        options: {
          position: 'top',
          banner: '<%= wuzzle.banner %>'
        },
        files: {
          src: [
            '<%= wuzzle.css %>',
            '<%= wuzzle.cssMin %>'
          ]
        }
      }
    },

    watch: {
      less: {
        files: 'src/*.less',
        tasks: ['less']
      }
    }
  });

  // These plugins provide necessary tasks
  require('load-grunt-tasks')(grunt, {scope: 'devDependencies'});

  // Default task
  grunt.registerTask('default', ['clean', 'less', 'csscomb', 'usebanner']);
};<commit_msg>Improve watch task<commit_after>module.exports = function (grunt) {
  'use strict';

  // Force use of Unix newlines
  grunt.util.linefeed = '\n';

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

    wuzzle: {
      less: 'src/wuzzle.less',
      css: 'dist/wuzzle.css',
      cssMin: 'dist/wuzzle.min.css',
      banner: '/*! Wuzzle <%= pkg.version %> | <%= _.pluck(pkg.licenses, "type") %> | http//git.io/wuzzle */\n'
    },

    // Tasks
    clean: {
      dist: ['dist']
    },

    less: {
      dist: {
        files: {
          '<%= wuzzle.css %>': '<%= wuzzle.less %>'
        }
      },
      distMin: {
        options: {
          cleancss: true,
          report: 'min'
        },
        files: {
          '<%= wuzzle.cssMin %>': '<%= wuzzle.css %>'
        }
      }
    },

    csscomb: {
      sort: {
        options: {
          sortOrder: '.csscomb.json'
        },
        files: {
          '<%= wuzzle.css %>': ['<%= wuzzle.css %>'],
        }
      }
    },

    usebanner: {
      dist: {
        options: {
          position: 'top',
          banner: '<%= wuzzle.banner %>'
        },
        files: {
          src: [
            '<%= wuzzle.css %>',
            '<%= wuzzle.cssMin %>'
          ]
        }
      }
    },

    watch: {
      less: {
        files: 'src/*.less',
        tasks: ['less', 'csscomb', 'usebanner']
      }
    }
  });

  // These plugins provide necessary tasks
  require('load-grunt-tasks')(grunt, {scope: 'devDependencies'});

  // Default task
  grunt.registerTask('default', ['clean', 'less', 'csscomb', 'usebanner']);
};<|endoftext|>