<commit_before>module.exports = function(grunt) {
	grunt.loadNpmTasks('grunt-contrib-jshint');
	grunt.loadNpmTasks('grunt-contrib-sass');
	grunt.loadNpmTasks('grunt-contrib-clean');
	grunt.loadNpmTasks('grunt-mocha');
	grunt.loadNpmTasks('grunt-browserify');
	grunt.loadNpmTasks('grunt-contrib-copy');
	grunt.loadNpmTasks('grunt-express');
	grunt.loadNpmTasks('grunt-open');
	grunt.loadNpmTasks('grunt-contrib-watch');

	grunt.initConfig({
		jshint: {
			files: [
				'app/js/**/*.js',
				'routes.js',
				'server.js',
				'test/**/*.js'
			]
		},
		clean: {
			dev: {
				src: [
					'build/',
					'dist/'
				]
			}
		},
    sass: {
      dev: {
        files: {
          'app/styles.css': 'app/styles/styles.scss'
        }
	    }
    },
		mocha: {
			backbonetest: {
				src: ['test/test.html'],
				options: {
					run: true
				}
			}
		},
		browserify: {
			dev: {
				options: {
					transform: [
						'debowerify',
						'hbsify'
					],
					debug: true
				},
				src: ['app/js/**/*.js'],
				dest: 'build/bundle.js'
			},
			backbonetest: {
				options: {
					transform: [
						'debowerify',
						'hbisfy'
					],
					debug: true
				},
				src: ['test/mocha/backbone/**/*.js'],
				dest: 'test/testBundle.js'
			}
		},
		copy: {
			dev: {
				expand: true,
				cwd: 'app/',
				src: [
					'*.html',
					'*.css'
				],
				dest: 'build/',
				filter: 'isFile'
			}
		},
		express: {
      all: {
        options: {
          port: 3000,
          hostname: 'localhost',
          livereload: true,
          bases: 'build/'
        }
      }
    },
    open: {
      all: {
        path: 'http://localhost:<%= express.all.options.port%>'
      }
    },
		watch: {
			all: {
				files: [
					'app/**/*',
					'server.js',
					'routes.js'
				],
				tasks: [
					'jshint',
					'sass:dev',
					'clean:dev',
					'browserify:dev',
					'copy:dev'
				],
				options: {
					livereload: true
				}
			}
		}
		// Add CSSmin and Uglify for dist build
	});
	grunt.registerTask('default', [
		'jshint',
		'sass:dev',
		// 'browserify:backbonetest', // For testing Backbone
		// 'mocha:backbonetest', // For testing Backbone
		'clean:dev',
		'browserify:dev',
		'copy:dev',
		// Localhost and LiveReload init
		'express',
		'open',
		'watch:all'
	]);
};<commit_msg>Making a trivial change to trick Git into paying attention<commit_after>module.exports = function(grunt) {
	grunt.loadNpmTasks('grunt-contrib-jshint');
	grunt.loadNpmTasks('grunt-contrib-sass');
	grunt.loadNpmTasks('grunt-contrib-clean');
	grunt.loadNpmTasks('grunt-mocha');
	grunt.loadNpmTasks('grunt-browserify');
	grunt.loadNpmTasks('grunt-contrib-copy');
	grunt.loadNpmTasks('grunt-express');
	grunt.loadNpmTasks('grunt-open');
	grunt.loadNpmTasks('grunt-contrib-watch');

	grunt.initConfig({
		jshint: {
			files: [
				'app/js/**/*.js',
				'routes.js',
				'server.js',
				'test/**/*.js'
			]
		},
		clean: {
			dev: {
				src: [
					'build/',
					'dist/'
				]
			}
		},
    sass: {
      dev: {
        files: {
          'app/styles.css': 'app/styles/styles.scss'
        }
	    }
    },
		mocha: {
			backbonetest: {
				src: ['test/test.html'],
				options: {
					run: true
				}
			}
		},
		browserify: {
			dev: {
				options: {
					transform: [
						'debowerify',
						'hbsify'
					],
					debug: true
				},
				src: ['app/js/**/*.js'],
				dest: 'build/bundle.js'
			},
			backbonetest: {
				options: {
					transform: [
						'debowerify',
						'hbisfy'
					],
					debug: true
				},
				src: ['test/mocha/backbone/**/*.js'],
				dest: 'test/testBundle.js'
			}
		},
		copy: {
			dev: {
				expand: true,
				cwd: 'app/',
				src: [
					'*.html',
					'*.css'
				],
				dest: 'build/',
				filter: 'isFile'
			}
		},
		express: {
      all: {
        options: {
          port: 3000,
          hostname: 'localhost',
          livereload: true,
          bases: 'build/'
        }
      }
    },
    open: {
      all: {
        path: 'http://localhost:<%= express.all.options.port%>'
      }
    },
		watch: {
			all: {
				files: [
					'app/**/*',
					'server.js',
					'routes.js'
				],
				tasks: [
					'jshint',
					'sass:dev',
					'clean:dev',
					'browserify:dev',
					'copy:dev'
				],
				options: {
					livereload: true
				}
			}
		}
		// Add CSSmin and Uglify for dist build
	});
	grunt.registerTask('default', [
		'jshint',
		'sass:dev',
		// 'browserify:backbonetest', // For testing Backbone
		// 'mocha:backbonetest', // For testing Backbone
		'clean:dev',
		'browserify:dev',
		'copy:dev',
		// Localhost/LiveReload init
		'express',
		'open',
		'watch:all'
	]);
};<|endoftext|>


<commit_before>module.exports = function(grunt) {
  var target = grunt.option('target') || 'gross_economy_test'
  var title = 'Gross Economy Test'
  if (target == 'gross_economy') {
    title = 'Gross Economy'
  }

  // Project configuration.
  grunt.initConfig({
    target: target,
    requirejs: {
      target: {
        options: {
          baseUrl: 'ui/mods',
          mainConfigFile: 'ui/mods/gross_economy/bootstrap.js',
          skipDirOptimize: true,
          optimize: 'none',
          stubModules: ['text'],

          //name: 'lib/ext/almond',
          name: 'gross_economy/main',
          out: '../<%= target %>/ui/mods/gross_economy/bootstrap.js',

          skipModuleInsertion: true,
          onBuildWrite: function( name, path, contents ) {
            return require('amdclean').clean({
              code: contents,
              globalObject: true,
              globalObjectName: 'gross_economy',
            });
          },
        }
      }
    },
    copy: {
      simple: {
        files: [
          {
            src: [
              'LICENSE.txt',
              'README.md',
              'CHANGELOG.md',
              'ui/mods/gross_economy/*.css'],
            dest: '../<%= target %>/',
          },
        ],
      },
      modinfo: {
        files: [
          {
            src: 'modinfo.dev.json',
            dest: '../<%= target %>/modinfo.json',
          },
        ],
        options: {
          process: function(content, srcpath) {
            var info = JSON.parse(content)
            info.date = require('dateformat')(new Date(), 'yyyy/mm/dd')
            info.display_name = title
            info.id = target
            info.identifier = "com.wondible.pa." + target
            info.live_game_econ.shift()
            console.log(info.version, info.date)
            return JSON.stringify(info)
          }
        }
      },
      dev: {
        files: [
          {
            src: 'modinfo.dev.json',
            dest: 'modinfo.json',
          },
        ]
      }
    },
  });

  // Load the plugin that provides the "uglify" task.
  grunt.loadNpmTasks('grunt-contrib-requirejs');
  grunt.loadNpmTasks('grunt-contrib-copy');

  // Default task(s).
  grunt.registerTask('default', ['requirejs', 'copy:simple', 'copy:modinfo']);

};
<commit_msg>pretty print modinfo<commit_after>module.exports = function(grunt) {
  var target = grunt.option('target') || 'gross_economy_test'
  var title = 'Gross Economy Test'
  if (target == 'gross_economy') {
    title = 'Gross Economy'
  }

  // Project configuration.
  grunt.initConfig({
    target: target,
    requirejs: {
      target: {
        options: {
          baseUrl: 'ui/mods',
          mainConfigFile: 'ui/mods/gross_economy/bootstrap.js',
          skipDirOptimize: true,
          optimize: 'none',
          stubModules: ['text'],

          //name: 'lib/ext/almond',
          name: 'gross_economy/main',
          out: '../<%= target %>/ui/mods/gross_economy/bootstrap.js',

          skipModuleInsertion: true,
          onBuildWrite: function( name, path, contents ) {
            return require('amdclean').clean({
              code: contents,
              globalObject: true,
              globalObjectName: 'gross_economy',
            });
          },
        }
      }
    },
    copy: {
      simple: {
        files: [
          {
            src: [
              'LICENSE.txt',
              'README.md',
              'CHANGELOG.md',
              'ui/mods/gross_economy/*.css'],
            dest: '../<%= target %>/',
          },
        ],
      },
      modinfo: {
        files: [
          {
            src: 'modinfo.dev.json',
            dest: '../<%= target %>/modinfo.json',
          },
        ],
        options: {
          process: function(content, srcpath) {
            var info = JSON.parse(content)
            info.date = require('dateformat')(new Date(), 'yyyy/mm/dd')
            info.display_name = title
            info.id = target
            info.identifier = "com.wondible.pa." + target
            info.live_game_econ.shift()
            console.log(info.version, info.date)
            return JSON.stringify(info, null, 2)
          }
        }
      },
      dev: {
        files: [
          {
            src: 'modinfo.dev.json',
            dest: 'modinfo.json',
          },
        ]
      }
    },
  });

  // Load the plugin that provides the "uglify" task.
  grunt.loadNpmTasks('grunt-contrib-requirejs');
  grunt.loadNpmTasks('grunt-contrib-copy');

  // Default task(s).
  grunt.registerTask('default', ['requirejs', 'copy:simple', 'copy:modinfo']);

};
<|endoftext|>


<commit_before>(function() {

function MoveList(board) {
  this.board    = board;
  this.moves    = board.moves;
  this.level    = 0;
  this.position = null;
  this.stops    = null;
}

Dagaz.Model.getMoveList = function(board) {
  board.generate();
  return new MoveList(board);
}

MoveList.prototype.isPassForced = function() {
  return (this.moves.length == 1) && this.moves[0].isPass();
}

MoveList.prototype.isEmpty = function() {
  return this.moves.length == 0;
}

var getMaxPart = function(move) {
  return _.chain(move.actions)
   .map(function(action) {
        return action[3];
    }).push(-1).max().value();
}

MoveList.prototype.getMoves = function() {
  var result = _.filter(this.moves, function(move) {
     return getMaxPart(move) < this.level + 1;
  }, this);
  result = _.uniq(result, false, function(move) {
     return move.toString();
  });
  return result;
}

MoveList.prototype.isDone = function() {
  var result = _.filter(this.moves, function(move) {
     return getMaxPart(move) >= this.level + 1;
  }, this).length == 0;
  return result;
}

MoveList.prototype.canPass = function() {
  var result = _.chain(this.moves).map(getMaxPart).min().value() <= this.level;
  return result;
}

MoveList.prototype.getActions = function(move) {
  return _.filter(move.actions, function(action) {
     return action[3] == this.level + 1;
  }, this);
}

var isMove = function(action) {
  return (action[0] !== null) && (action[1] !== null);
}

var isNoMove = function(action) {
  return (action[0] === null) || (action[1] === null);
}

var isDrop = function(action) {
  return (action[0] === null) && (action[1] !== null);
}

var isCapturing = function(action) {
  return (action[0] !== null) && (action[1] === null);
}

MoveList.prototype.getTargets = function() {
  var result = [];
  if (this.position !== null) {
      _.each(this.moves, function(move) {
          var actions = this.getActions(move);
          if ((actions.length > 0) && isMove(actions[0]) && (_.indexOf(actions[0][0], this.position) >= 0)) {
              result.push(actions[0][1][0]);
          }
      }, this);
  }
  result = _.uniq(result);
  return result;
}

MoveList.prototype.getStarts = function() {
  var result = [];
  _.each(this.moves, function(move) {
      var actions = this.getActions(move);
      if ((actions.length > 0) && isMove(actions[0])) {
          result.push(actions[0][0][0]);
      }
  }, this);
  result = _.uniq(_.union(result, this.getCaptures()));
  return result;
}

MoveList.prototype.getMoveActions = function(move) {
  var result = [];
  var actions = this.getActions(move);
  if  ((actions.length > 0) && isMove(actions[0])) {
      result.push(actions[0]);
  }
  return result;
}

MoveList.prototype.getStops = function() {
  if (this.stops !== null) {
      return this.stops;
  }
  var result = this.getTargets();
  _.each(this.moves, function(move) {
      var actions = this.getMoveActions(move);
      if ((actions.length == 0) || (actions[0][0].length > 1) || (actions[0][1].length > 1)) {
          _.chain(this.getActions(move))
           .filter(isNoMove)
           .each(function(action) {
                if (action[0] !== null) {
                    _.each(action[0], function(pos) {
                        result.push(pos);
                    });
                }
                if (action[1] !== null) {
                    _.each(action[1], function(pos) {
                        result.push(pos);
                    });
                }
            });
      }
  }, this);
  if (Dagaz.Model.smartFrom || Dagaz.Model.smartTo) {
      var positions = [];
      var canPass   = this.canPass();
      _.each(this.moves, function(move) {
            var actions = _.filter(this.getActions(move), isMove);
            if (!canPass && (actions.length > 0) && (actions[0][0].length == 1) && Dagaz.Model.smartFrom) {
                positions.push(actions[0][0][0]);
            }
            if ((actions.length > 0) && (actions[0][1].length == 1) && Dagaz.Model.smartTo) {
                positions.push(actions[0][1][0]);
            }
      }, this);
      positions = _.countBy(positions, _.identity);
      _.each(_.keys(positions), function(pos) {
            if (positions[pos] == 1) {
                result.push(+pos);
            }
      });
  }
  result = _.uniq(result);
  this.stops = result;
  return result;
}

MoveList.prototype.getCaptures = function() {
  var result = [];
  _.each(this.moves, function(move) {
      var actions = this.getMoveActions(move);
      if (((actions.length > 0) && (_.indexOf(actions[0][0], this.position) >= 0)) ||
          ((actions.length == 0) && (this.position === null))) {
          _.chain(this.getActions(move))
           .filter(isCapturing)
           .each(function(action) {
                _.each(action[0], function(pos) {
                    result.push(pos);
                });
            });
      }
  }, this);
  result = _.uniq(result);
  return result;
}

MoveList.prototype.getDrops = function() {
  var result = [];
  _.each(this.moves, function(move) {
      var actions = this.getMoveActions(move);
      if (actions.length == 0) {
          _.chain(this.getActions(move))
           .filter(isDrop)
           .each(function(action) {
                _.each(action[1], function(pos) {
                    result.push(pos);
                });
            });
      }
  }, this);
  return _.uniq(result);
}

MoveList.prototype.getDropPieces = function(pos) {
  var result = null;
  _.each(this.moves, function(move) {
      _.each(move.actions, function(action) {
          if ((action[0] === null) && (action[1] !== null) && (action[1][0] == pos)) {
              result = action[2];
          }
      });
  });
  return result;
}

var isEq = function(x, y) {
  if (x === null) return y === null;
  if (y === null) return false;
  return _.intersection(x, y).length > 0;
}

MoveList.prototype.copyActions = function(move, actions, mode) {
  move.mode = mode;
  if (actions.length == 0) return;
  if (move.isPass()) {
      _.each(actions, function(action) {
          move.actions.push([ action[0], action[1], action[2], 1 ]);
      });
  } else {
      var result = [];
      _.each(actions, function(action) {
          _.each(move.actions, function(a) {
               if (isEq(action[0], a[0]) && isEq(action[1], a[1])) {
                   result.push([ action[0], action[1], action[2], 1 ]);
               }
          });
      });
      move.actions = result;
  }
}

MoveList.prototype.setPosition = function(pos) {
  var result = Dagaz.Model.createMove();
  if (_.indexOf(this.getStops(), pos) >= 0) {
      var moves = _.filter(this.moves, function(move) {
          var actions = this.getActions(move);
          var m = this.getMoveActions(move);
          if (m.length > 0) {
              if ((_.indexOf(m[0][0], this.position) >= 0) && (_.indexOf(m[0][1], pos) >= 0)) {
                  // Regular move
                  m[0][0] = [ this.position ];
                  m[0][1] = [ pos ];
                  this.copyActions(result, actions, move.mode);
                  return true;
              }
              if (Dagaz.Model.smartFrom && (this.position == null) && (_.indexOf(m[0][0], pos) >= 0)) {
                  // Smart from move
                  m[0][0] = [ pos ];
                  this.copyActions(result, actions, move.mode);
                  return true;
              }
              if (Dagaz.Model.smartTo && (this.position == null) && (_.indexOf(m[0][1], pos) >= 0)) {
                  // Smart from move
                  m[0][1] = [ pos ];
                  this.copyActions(result, actions, move.mode);
                  return true;
              }
          } else {
              var n = _.chain(actions)
               .filter(isNoMove)
               .filter(function(action) {
                   if ((action[0] !== null) && (_.indexOf(action[0], pos) >= 0)) {
                       // Capture move
                       action[0] = [ pos ];
                       return true;
                   }
                   if ((action[1] !== null) && (_.indexOf(action[1], pos) >= 0)) {
                       // Drop move
                       action[1] = [ pos ];
                       return true;
                   }
                   return false;
                }).value();
              if (n.length > 0) {
                  this.copyActions(result, actions, move.mode);
                  return true;
              }
          }
      }, this);
      if (moves.length != 0) {
          this.moves = moves;
          this.level++;
      }
      this.position = null;
  }
  if (_.indexOf(this.getStarts(), pos) >= 0) {
      if (this.position == pos) {
          this.position = null;
      } else {
          this.position = pos;
      }
  }
  this.stops = null;
  return result;
}

})();
<commit_msg>move-list-v3 (fix)<commit_after>(function() {

function MoveList(board) {
  this.board    = board;
  this.moves    = board.moves;
  this.level    = 0;
  this.position = null;
  this.stops    = null;
}

Dagaz.Model.getMoveList = function(board) {
  board.generate();
  return new MoveList(board);
}

MoveList.prototype.isPassForced = function() {
  return (this.moves.length == 1) && this.moves[0].isPass();
}

MoveList.prototype.isEmpty = function() {
  return this.moves.length == 0;
}

var getMaxPart = function(move) {
  return _.chain(move.actions)
   .map(function(action) {
        return action[3];
    }).push(-1).max().value();
}

MoveList.prototype.getMoves = function() {
  var result = _.filter(this.moves, function(move) {
     return getMaxPart(move) < this.level + 1;
  }, this);
  result = _.uniq(result, false, function(move) {
     return move.toString();
  });
  return result;
}

MoveList.prototype.isDone = function() {
  var result = _.filter(this.moves, function(move) {
     return getMaxPart(move) >= this.level + 1;
  }, this).length == 0;
  return result;
}

MoveList.prototype.canPass = function() {
  var result = _.chain(this.moves).map(getMaxPart).min().value() <= this.level;
  return result;
}

MoveList.prototype.getActions = function(move) {
  return _.filter(move.actions, function(action) {
     return action[3] == this.level + 1;
  }, this);
}

var isMove = function(action) {
  return (action[0] !== null) && (action[1] !== null);
}

var isNoMove = function(action) {
  return (action[0] === null) || (action[1] === null);
}

var isDrop = function(action) {
  return (action[0] === null) && (action[1] !== null);
}

var isCapturing = function(action) {
  return (action[0] !== null) && (action[1] === null);
}

MoveList.prototype.getTargets = function() {
  var result = [];
  if (this.position !== null) {
      _.each(this.moves, function(move) {
          var actions = this.getActions(move);
          if ((actions.length > 0) && isMove(actions[0]) && (_.indexOf(actions[0][0], this.position) >= 0)) {
              result.push(actions[0][1][0]);
          }
      }, this);
  }
  result = _.uniq(result);
  return result;
}

MoveList.prototype.getStarts = function() {
  var result = [];
  _.each(this.moves, function(move) {
      var actions = this.getActions(move);
      if ((actions.length > 0) && isMove(actions[0])) {
          result.push(actions[0][0][0]);
      }
  }, this);
  result = _.uniq(_.union(result, this.getCaptures()));
  return result;
}

MoveList.prototype.getMoveActions = function(move) {
  var result = [];
  var actions = this.getActions(move);
  if  ((actions.length > 0) && isMove(actions[0])) {
      result.push(actions[0]);
  }
  return result;
}

MoveList.prototype.getStops = function() {
  if (this.stops !== null) {
      return this.stops;
  }
  var result = this.getTargets();
  _.each(this.moves, function(move) {
      var actions = this.getMoveActions(move);
      if ((actions.length == 0) || (actions[0][0].length > 1) || (actions[0][1].length > 1)) {
          _.chain(this.getActions(move))
           .filter(isNoMove)
           .each(function(action) {
                if (action[0] !== null) {
                    _.each(action[0], function(pos) {
                        result.push(pos);
                    });
                }
                if (action[1] !== null) {
                    _.each(action[1], function(pos) {
                        result.push(pos);
                    });
                }
            });
      }
  }, this);
  if (Dagaz.Model.smartFrom || Dagaz.Model.smartTo) {
      var positions = [];
      var canPass   = this.canPass();
      _.each(this.moves, function(move) {
            var actions = _.filter(this.getActions(move), isMove);
            if (!canPass && (actions.length > 0) && (actions[0][0].length == 1) && Dagaz.Model.smartFrom) {
                positions.push(actions[0][0][0]);
            }
            if ((actions.length > 0) && (actions[0][1].length == 1) && Dagaz.Model.smartTo) {
                positions.push(actions[0][1][0]);
            }
      }, this);
      positions = _.countBy(positions, _.identity);
      _.each(_.keys(positions), function(pos) {
            if (positions[pos] == 1) {
                result.push(+pos);
            }
      });
  }
  result = _.uniq(result);
  this.stops = result;
  return result;
}

MoveList.prototype.getCaptures = function() {
  var result = [];
  _.each(this.moves, function(move) {
      var actions = this.getMoveActions(move);
      if (((actions.length > 0) && (_.indexOf(actions[0][0], this.position) >= 0)) ||
          ((actions.length == 0) && (this.position === null))) {
          _.chain(this.getActions(move))
           .filter(isCapturing)
           .each(function(action) {
                _.each(action[0], function(pos) {
                    result.push(pos);
                });
            });
      }
  }, this);
  result = _.uniq(result);
  return result;
}

MoveList.prototype.getDrops = function() {
  var result = [];
  if (this.position === null) {
      _.each(this.moves, function(move) {
          var actions = this.getMoveActions(move);
          if (actions.length == 0) {
              _.chain(this.getActions(move))
               .filter(isDrop)
               .each(function(action) {
                    _.each(action[1], function(pos) {
                        result.push(pos);
                    });
                });
          }
      }, this);
  }
  return _.uniq(result);
}

MoveList.prototype.getDropPieces = function(pos) {
  var result = null;
  _.each(this.moves, function(move) {
      _.each(move.actions, function(action) {
          if ((action[0] === null) && (action[1] !== null) && (action[1][0] == pos)) {
              result = action[2];
          }
      });
  });
  return result;
}

var isEq = function(x, y) {
  if (x === null) return y === null;
  if (y === null) return false;
  return _.intersection(x, y).length > 0;
}

MoveList.prototype.copyActions = function(move, actions, mode) {
  move.mode = mode;
  if (actions.length == 0) return;
  if (move.isPass()) {
      _.each(actions, function(action) {
          move.actions.push([ action[0], action[1], action[2], 1 ]);
      });
  } else {
      var result = [];
      _.each(actions, function(action) {
          _.each(move.actions, function(a) {
               if (isEq(action[0], a[0]) && isEq(action[1], a[1])) {
                   result.push([ action[0], action[1], action[2], 1 ]);
               }
          });
      });
      move.actions = result;
  }
}

MoveList.prototype.setPosition = function(pos) {
  var result = Dagaz.Model.createMove();
  if (_.indexOf(this.getStops(), pos) >= 0) {
      var moves = _.filter(this.moves, function(move) {
          var actions = this.getActions(move);
          var m = this.getMoveActions(move);
          if (m.length > 0) {
              if ((_.indexOf(m[0][0], this.position) >= 0) && (_.indexOf(m[0][1], pos) >= 0)) {
                  // Regular move
                  m[0][0] = [ this.position ];
                  m[0][1] = [ pos ];
                  this.copyActions(result, actions, move.mode);
                  return true;
              }
              if (Dagaz.Model.smartFrom && (this.position == null) && (_.indexOf(m[0][0], pos) >= 0)) {
                  // Smart from move
                  m[0][0] = [ pos ];
                  this.copyActions(result, actions, move.mode);
                  return true;
              }
              if (Dagaz.Model.smartTo && (this.position == null) && (_.indexOf(m[0][1], pos) >= 0)) {
                  // Smart from move
                  m[0][1] = [ pos ];
                  this.copyActions(result, actions, move.mode);
                  return true;
              }
          } else {
              var n = _.chain(actions)
               .filter(isNoMove)
               .filter(function(action) {
                   if ((action[0] !== null) && (_.indexOf(action[0], pos) >= 0)) {
                       // Capture move
                       action[0] = [ pos ];
                       return true;
                   }
                   if ((action[1] !== null) && (_.indexOf(action[1], pos) >= 0)) {
                       // Drop move
                       action[1] = [ pos ];
                       return true;
                   }
                   return false;
                }).value();
              if ((this.position === null) && (n.length > 0)) {
                  this.copyActions(result, actions, move.mode);
                  return true;
              }
          }
      }, this);
      if (moves.length != 0) {
          this.moves = moves;
          this.level++;
      }
      this.position = null;
  }
  if (_.indexOf(this.getStarts(), pos) >= 0) {
      if (this.position == pos) {
          this.position = null;
      } else {
          this.position = pos;
      }
  }
  this.stops = null;
  return result;
}

})();
<|endoftext|>


<commit_before>'use strict';

const loadGruntConfig = require('load-grunt-config');
const path = require('path');

module.exports = (grunt) => {
	loadGruntConfig(grunt, {
		pkg: grunt.file.readJSON('package.json'), // Loads grunt tasks defined in package.json
		configPath: path.join(process.cwd(), 'grunt-config'), // path to task.js files, defaults to grunt dir
		init: true, // auto grunt.initConfig

		config: {
			// additional config vars
		},
		loadGruntTasks: {
			pattern: ['grunt-*', '@*/grunt-*']
		}
	});

	// Tasks
	grunt.registerTask('coverage', ['mocha_istanbul:coverage']);

	grunt.registerTask('lint', ['eslint']);

	// Default task
	grunt.registerTask('default', []);
};
<commit_msg>remove arrow function<commit_after>'use strict';

const loadGruntConfig = require('load-grunt-config');
const path = require('path');

module.exports = function (grunt) {
	loadGruntConfig(grunt, {
		pkg: grunt.file.readJSON('package.json'), // Loads grunt tasks defined in package.json
		configPath: path.join(process.cwd(), 'grunt-config'), // path to task.js files, defaults to grunt dir
		init: true, // auto grunt.initConfig

		config: {
			// additional config vars
		},
		loadGruntTasks: {
			pattern: ['grunt-*', '@*/grunt-*']
		}
	});

	// Tasks
	grunt.registerTask('coverage', ['mocha_istanbul:coverage']);

	grunt.registerTask('lint', ['eslint']);

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


<commit_before>var randomBackground = randomBackground || {};

(function( $ ){

  //  Default config settings

  randomBackground.config = {
      parent: '.hero'
     ,path: 'path/to/image/'
     ,images : ['image01.jpg', 'image02.jpg', 'image03.jpg']
    };

  randomBackground.init = function(config) {

    // provide for custom configuration via init()
    if (config && typeof(config) === 'object') {
      $.extend(randomBackground.config, config);
    }

    var _images = randomBackground.config.images,
        _randomNumber = Math.floor(Math.random()*(_images.length));

    $(randomBackground.config.parent).css('background-image', 'url("+randomBackground.config.path+_images[_randomNumber]+")');

    // If you need to check the image being outputted.
    // Remove the comments from the line below:
    //console.log(_images[_randomNumber]);

  };

/**
 *  Code to be placed on web page to initialise the plugin.
 *
 *  To extend the default config settings
 *  pass a object as an argument for the init function
 *  eg. randomBackground.init({ images: 'image01.jpg', 'image02.jpg' });
 */

  /*  Initialise and extend on page load

  $(document).ready(function() {

    randomBackground.init( { parent: '.hero', path: 'demo/img/', images: ['background_01.png', 'background_02.jpg', 'background_03.jpg'] });

  }); */

})( jQuery );
<commit_msg>Fixes mismatch of quote marks<commit_after>var randomBackground = randomBackground || {};

(function( $ ){

  //  Default config settings

  randomBackground.config = {
      parent: '.hero'
     ,path: 'path/to/image/'
     ,images : ['image01.jpg', 'image02.jpg', 'image03.jpg']
    };

  randomBackground.init = function(config) {

    // provide for custom configuration via init()
    if (config && typeof(config) === 'object') {
      $.extend(randomBackground.config, config);
    }

    var _images = randomBackground.config.images,
        _randomNumber = Math.floor(Math.random()*(_images.length));

    $(randomBackground.config.parent).css('background-image', 'url('+randomBackground.config.path+_images[_randomNumber]+')');

    // If you need to check the image being outputted.
    // Remove the comments from the line below:
    //console.log(_images[_randomNumber]);

  };

/**
 *  Code to be placed on web page to initialise the plugin.
 *
 *  To extend the default config settings
 *  pass a object as an argument for the init function
 *  eg. randomBackground.init({ images: 'image01.jpg', 'image02.jpg' });
 */

  /*  Initialise and extend on page load

  $(document).ready(function() {

    randomBackground.init( { parent: '.hero', path: 'demo/img/', images: ['background_01.png', 'background_02.jpg', 'background_03.jpg'] });

  }); */

})( jQuery );
<|endoftext|>


<commit_before>/** @babel */

import Opener from '../opener'
import url from 'url'

const DBUS_NAMES = {
  applicationObject: '/org/gnome/evince/Evince',
  applicationInterface: 'org.gnome.evince.Application',

  daemonService: 'org.gnome.evince.Daemon',
  daemonObject: '/org/gnome/evince/Daemon',
  daemonInterface: 'org.gnome.evince.Daemon',

  windowInterface: 'org.gnome.evince.Window',

  fdApplicationObject: '/org/gtk/Application/anonymous',
  fdApplicationInterface: 'org.freedesktop.Application'
}

function syncSource (uri, point) {
  const filePath = decodeURI(url.parse(uri).pathname)
  atom.workspace.open(filePath).then(editor => editor.setCursorBufferPosition(point))
}

export default class EvinceOpener extends Opener {
  windows = new Map()

  constructor (name = 'Evince', dbusNames = DBUS_NAMES) {
    super(() => {
      for (const texPath of Array.from(this.windows.keys())) {
        this.disposeWindow(texPath)
      }
    })
    this.name = name
    this.dbusNames = dbusNames
    this.initialize()
  }

  async initialize () {
    try {
      if (process.platform === 'linux') {
        const dbus = require('dbus-native')
        this.bus = dbus.sessionBus()
        this.daemon = await this.getInterface(this.dbusNames.daemonService, this.dbusNames.daemonObject, this.dbusNames.daemonInterface)
      }
    } catch (e) {}
  }

  async getWindow (filePath, texPath) {
    if (this.windows.has(filePath)) {
      return this.windows.get(filePath)
    }

    // First find the internal document name
    const documentName = await this.findDocument(filePath)

    // Get the application interface and get the window list of the application
    const evinceApplication = await this.getInterface(documentName, this.dbusNames.applicationObject, this.dbusNames.applicationInterface)
    const windowNames = await this.getWindowList(evinceApplication)

    // Get the window interface of the of the first (only) window
    const onClosed = () => this.disposeWindow(texPath)
    const windowInstance = {
      evinceWindow: await this.getInterface(documentName, windowNames[0], this.dbusNames.windowInterface),
      onClosed
    }

    if (this.dbusNames.fdApplicationObject) {
      // Get the GTK/FreeDesktop application interface so we can activate the window
      windowInstance.fdApplication = await this.getInterface(documentName, this.dbusNames.fdApplicationObject, this.dbusNames.fdApplicationInterface)
    }

    windowInstance.evinceWindow.on('SyncSource', syncSource)
    windowInstance.evinceWindow.on('Closed', windowInstance.onClosed)
    this.windows.set(filePath, windowInstance)

    // This seems to help with future syncs
    await this.syncView(windowInstance.evinceWindow, texPath, [0, 0], 0)

    return windowInstance
  }

  disposeWindow (texPath) {
    const windowInstance = this.windows.get(texPath)
    if (windowInstance) {
      windowInstance.evinceWindow.removeListener('SyncSource', syncSource)
      windowInstance.evinceWindow.removeListener('Closed', windowInstance.onClosed)
      this.windows.delete(texPath)
    }
  }

  async open (filePath, texPath, lineNumber) {
    try {
      const windowInstance = await this.getWindow(filePath, texPath)
      if (!this.shouldOpenInBackground() && windowInstance.fdApplication) {
        windowInstance.fdApplication.Activate({})
      }

      // SyncView seems to want to activate the window sometimes
      await this.syncView(windowInstance.evinceWindow, texPath, [lineNumber, 0], 0)

      return true
    } catch (error) {
      latex.log.error(`An error occured while trying to run ${this.name} opener`)
      return false
    }
  }

  canOpen (filePath) {
    return !!this.daemon
  }

  hasSynctex () {
    return true
  }

  canOpenInBackground () {
    return true
  }

  getInterface (serviceName, objectPath, interfaceName) {
    return new Promise((resolve, reject) => {
      this.bus.getInterface(serviceName, objectPath, interfaceName, (error, interfaceInstance) => {
        if (error) {
          reject(error)
        } else {
          resolve(interfaceInstance)
        }
      })
    })
  }

  getWindowList (evinceApplication) {
    return new Promise((resolve, reject) => {
      evinceApplication.GetWindowList((error, windowNames) => {
        if (error) {
          reject(error)
        } else {
          resolve(windowNames)
        }
      })
    })
  }

  syncView (evinceWindow, source, point, timestamp) {
    return new Promise((resolve, reject) => {
      evinceWindow.SyncView(source, point, timestamp, (error) => {
        console.log(`${source} ${error}`)
        if (error) {
          reject(error)
        } else {
          resolve()
        }
      })
    })
  }

  findDocument (filePath) {
    return new Promise((resolve, reject) => {
      const uri = url.format({
        protocol: 'file:',
        slashes: true,
        pathname: encodeURI(filePath)
      })

      this.daemon.FindDocument(uri, true, (error, documentName) => {
        if (error) {
          reject(error)
        } else {
          resolve(documentName)
        }
      })
    })
  }
}
<commit_msg>Fix syncView call<commit_after>/** @babel */

import Opener from '../opener'
import url from 'url'

const DBUS_NAMES = {
  applicationObject: '/org/gnome/evince/Evince',
  applicationInterface: 'org.gnome.evince.Application',

  daemonService: 'org.gnome.evince.Daemon',
  daemonObject: '/org/gnome/evince/Daemon',
  daemonInterface: 'org.gnome.evince.Daemon',

  windowInterface: 'org.gnome.evince.Window',

  fdApplicationObject: '/org/gtk/Application/anonymous',
  fdApplicationInterface: 'org.freedesktop.Application'
}

function syncSource (uri, point) {
  const filePath = decodeURI(url.parse(uri).pathname)
  atom.workspace.open(filePath).then(editor => editor.setCursorBufferPosition(point))
}

export default class EvinceOpener extends Opener {
  windows = new Map()

  constructor (name = 'Evince', dbusNames = DBUS_NAMES) {
    super(() => {
      for (const texPath of Array.from(this.windows.keys())) {
        this.disposeWindow(texPath)
      }
    })
    this.name = name
    this.dbusNames = dbusNames
    this.initialize()
  }

  async initialize () {
    try {
      if (process.platform === 'linux') {
        const dbus = require('dbus-native')
        this.bus = dbus.sessionBus()
        this.daemon = await this.getInterface(this.dbusNames.daemonService, this.dbusNames.daemonObject, this.dbusNames.daemonInterface)
      }
    } catch (e) {}
  }

  async getWindow (filePath, texPath) {
    if (this.windows.has(filePath)) {
      return this.windows.get(filePath)
    }

    // First find the internal document name
    const documentName = await this.findDocument(filePath)

    // Get the application interface and get the window list of the application
    const evinceApplication = await this.getInterface(documentName, this.dbusNames.applicationObject, this.dbusNames.applicationInterface)
    const windowNames = await this.getWindowList(evinceApplication)

    // Get the window interface of the of the first (only) window
    const onClosed = () => this.disposeWindow(texPath)
    const windowInstance = {
      evinceWindow: await this.getInterface(documentName, windowNames[0], this.dbusNames.windowInterface),
      onClosed
    }

    if (this.dbusNames.fdApplicationObject) {
      // Get the GTK/FreeDesktop application interface so we can activate the window
      windowInstance.fdApplication = await this.getInterface(documentName, this.dbusNames.fdApplicationObject, this.dbusNames.fdApplicationInterface)
    }

    windowInstance.evinceWindow.on('SyncSource', syncSource)
    windowInstance.evinceWindow.on('Closed', windowInstance.onClosed)
    this.windows.set(filePath, windowInstance)

    // This seems to help with future syncs
    await this.syncView(windowInstance.evinceWindow, texPath, [0, 0], 0)

    return windowInstance
  }

  disposeWindow (texPath) {
    const windowInstance = this.windows.get(texPath)
    if (windowInstance) {
      windowInstance.evinceWindow.removeListener('SyncSource', syncSource)
      windowInstance.evinceWindow.removeListener('Closed', windowInstance.onClosed)
      this.windows.delete(texPath)
    }
  }

  async open (filePath, texPath, lineNumber) {
    try {
      const windowInstance = await this.getWindow(filePath, texPath)
      if (!this.shouldOpenInBackground() && windowInstance.fdApplication) {
        windowInstance.fdApplication.Activate({})
      }

      // SyncView seems to want to activate the window sometimes
      await this.syncView(windowInstance.evinceWindow, texPath, [lineNumber, 0], 0)

      return true
    } catch (error) {
      latex.log.error(`An error occured while trying to run ${this.name} opener`)
      return false
    }
  }

  canOpen (filePath) {
    return !!this.daemon
  }

  hasSynctex () {
    return true
  }

  canOpenInBackground () {
    return true
  }

  getInterface (serviceName, objectPath, interfaceName) {
    return new Promise((resolve, reject) => {
      this.bus.getInterface(serviceName, objectPath, interfaceName, (error, interfaceInstance) => {
        if (error) {
          reject(error)
        } else {
          resolve(interfaceInstance)
        }
      })
    })
  }

  getWindowList (evinceApplication) {
    return new Promise((resolve, reject) => {
      evinceApplication.GetWindowList((error, windowNames) => {
        if (error) {
          reject(error)
        } else {
          resolve(windowNames)
        }
      })
    })
  }

  syncView (evinceWindow, source, point, timestamp) {
    return new Promise((resolve, reject) => {
      evinceWindow.SyncView(source, point, timestamp, (error) => {
        if (error) {
          reject(error)
        } else {
          resolve()
        }
      })
    })
  }

  findDocument (filePath) {
    return new Promise((resolve, reject) => {
      const uri = url.format({
        protocol: 'file:',
        slashes: true,
        pathname: encodeURI(filePath)
      })

      this.daemon.FindDocument(uri, true, (error, documentName) => {
        if (error) {
          reject(error)
        } else {
          resolve(documentName)
        }
      })
    })
  }
}
<|endoftext|>


<commit_before>const aws4 = require('aws4')
const AWS = require('aws-sdk')
const path = require('path')
const os = require('os')

let credentials // lazily loaded, see below

const aws4signer = (esRequest, parent) => {
  // Consider deprecating - insecure to use on command line and credentials can be found by default at ~/.aws/credentials or as environment variables
  const useAwsCredentials = ((typeof parent.options.awsAccessKeyId === 'string') && (typeof parent.options.awsSecretAccessKey === 'string'))
  // Consider deprecating - can be achieved with awsChain and setting AWS_PROFILE and AWS_CONFIG_FILE environment variables as needed
  const useAwsProfile = (typeof parent.options.awsIniFileProfile === 'string')
  const useAwsChain = (parent.options.awsChain === true)
  const awsUrlRegex = new RegExp(parent.options.awsUrlRegex || /^https?:\/\/.*\.amazonaws\.com.*$/)

  if (!awsUrlRegex.test(esRequest.url) && !awsUrlRegex.test(esRequest.uri)) {
    return
  }

  if (useAwsCredentials || useAwsProfile || useAwsChain) {
    // Lazy load credentials object depending on our flavor of credential loading
    // Assumption is that loading only needs to happen once per execution and if refreshing is
    // needed, credentials object should implement credentials.refresh() callback
    if (!credentials) {
      if (useAwsChain) {
        new AWS.CredentialProviderChain().resolve((err, resolved) => {
          if (err) { throw err } else {
            credentials = resolved
          }
        })
      } else if (useAwsCredentials) {
        credentials = {
          accessKeyId: parent.options.awsAccessKeyId,
          secretAccessKey: parent.options.awsSecretAccessKey,
          sessionToken: parent.options.sessionToken
        }
      } else if (useAwsProfile) {
        credentials = new AWS.SharedIniFileCredentials({
          profile: parent.options.awsIniFileProfile,
          filename: path.join(os.homedir(), '.aws', parent.options.awsIniFileName ? parent.options.awsIniFileName : 'config')
        })
      }
    }

    // get aws required stuff from uri or url
    let esURL = ''
    if ((esRequest.uri !== undefined) && (esRequest.uri !== null)) {
      esURL = esRequest.uri
    } else if ((esRequest.url !== undefined) && (esRequest.url !== null)) {
      esURL = esRequest.url
    }

    const urlObj = new URL(esURL)

    if (parent.options.awsService) {
      esRequest.service = parent.options.awsService
    }

    if (parent.options.awsRegion) {
      esRequest.region = parent.options.awsRegion
    }

    esRequest.headers = Object.assign({ host: urlObj.hostname, 'Content-Type': 'application/json' }, esRequest.headers)
    esRequest.path = `${urlObj.pathname}?${urlObj.searchParams.toString()}`
    aws4.sign(esRequest, credentials)
  }
}

module.exports = aws4signer
<commit_msg>check if credential has expired and trigger a refresh<commit_after>const aws4 = require('aws4')
const AWS = require('aws-sdk')
const path = require('path')
const os = require('os')

let credentials // lazily loaded, see below

const aws4signer = (esRequest, parent) => {
  // Consider deprecating - insecure to use on command line and credentials can be found by default at ~/.aws/credentials or as environment variables
  const useAwsCredentials = ((typeof parent.options.awsAccessKeyId === 'string') && (typeof parent.options.awsSecretAccessKey === 'string'))
  // Consider deprecating - can be achieved with awsChain and setting AWS_PROFILE and AWS_CONFIG_FILE environment variables as needed
  const useAwsProfile = (typeof parent.options.awsIniFileProfile === 'string')
  const useAwsChain = (parent.options.awsChain === true)
  const awsUrlRegex = new RegExp(parent.options.awsUrlRegex || /^https?:\/\/.*\.amazonaws\.com.*$/)

  if (!awsUrlRegex.test(esRequest.url) && !awsUrlRegex.test(esRequest.uri)) {
    return
  }

  if (useAwsCredentials || useAwsProfile || useAwsChain) {
    // Lazy load credentials object depending on our flavor of credential loading
    // Assumption is that loading only needs to happen once per execution and if refreshing is
    // needed, credentials object should implement credentials.refresh() callback
    if (!credentials) {
      if (useAwsChain) {
        new AWS.CredentialProviderChain().resolve((err, resolved) => {
          if (err) { throw err } else {
            credentials = resolved
          }
        })
      } else if (useAwsCredentials) {
        credentials = {
          accessKeyId: parent.options.awsAccessKeyId,
          secretAccessKey: parent.options.awsSecretAccessKey,
          sessionToken: parent.options.sessionToken
        }
      } else if (useAwsProfile) {
        credentials = new AWS.SharedIniFileCredentials({
          profile: parent.options.awsIniFileProfile,
          filename: path.join(os.homedir(), '.aws', parent.options.awsIniFileName ? parent.options.awsIniFileName : 'config')
        })
      }
    }

    // get aws required stuff from uri or url
    let esURL = ''
    if ((esRequest.uri !== undefined) && (esRequest.uri !== null)) {
      esURL = esRequest.uri
    } else if ((esRequest.url !== undefined) && (esRequest.url !== null)) {
      esURL = esRequest.url
    }

    const urlObj = new URL(esURL)

    if (parent.options.awsService) {
      esRequest.service = parent.options.awsService
    }

    if (parent.options.awsRegion) {
      esRequest.region = parent.options.awsRegion
    }

    // refreshes the token if has expired.
    credentials.get(err => {
      if (err) throw err
    })

    esRequest.headers = Object.assign({ host: urlObj.hostname, 'Content-Type': 'application/json' }, esRequest.headers)
    esRequest.path = `${urlObj.pathname}?${urlObj.searchParams.toString()}`
    aws4.sign(esRequest, credentials)
  }
}

module.exports = aws4signer
<|endoftext|>


<commit_before>"use strict";

var LIVERELOAD_PORT = 35729;
var lrSnippet = require("connect-livereload")({
  port: LIVERELOAD_PORT
});

var mountFolder = function (connect, dir) {
  return connect.static(require("path").resolve(dir));
};

var webpack = require("webpack");
var fs = require("fs");

module.exports = function (grunt) {
  // Let *load-grunt-tasks* require everything
  require("load-grunt-tasks")(grunt);
  // Read configuration from package.json
  var pkgConfig = grunt.file.readJSON("package.json");
  var jshintConfig = grunt.file.readJSON(".jshintrc");

  var loaders = [{
    test: /\.css$/,
    loader: "style-loader!css-loader"
  }, {
    test: /\.s[ac]ss$/,
    loader: "style!css!sass"
  }, {
    test: /\.gif/,
    loader: "url-loader?minetype=image/gif"
  }, {
    test: /\.jpg/,
    loader: "url-loader?minetype=image/jpg"
  }, {
    test: /\.png/,
    loader: "url-loader?minetype=image/png"
  }, {
    test: /\.js$/,
    loader: "msx-loader"
  }, {
    test: /\.woff$/,
    loader: "url-loader?prefix=/assets/&minetype=application/font-woff"
  }, {
    test: /\.ttf$/,
    loader: "file-loader?prefix=/assets/"
  }, {
    test: /\.eot$/,
    loader: "file-loader?prefix=/assets/"
  }, {
    test: /\.svg$/,
    loader: "file-loader?prefix=/assets/"
  }];

  var handle404 = function(src) {
    return function(req, res) {
      var file = src + "/index.html";
      if (grunt.file.exists(file)) {
        return fs.createReadStream(file).pipe(res);
      }
      res.statusCode(404); // where's index.html?
      res.end();
    };
  };

  var DEVELOPMENT_PATH = "build/development";
  var PRODUCTION_PATH = "build/production/public";

  grunt.initConfig({
    pkg: pkgConfig,
    env: {
      development: {
        NODE_ENV: "development"
      },
      production: {
        NODE_ENV: "production"
      }
    },
    webpack: {
      options: {
        cache: true,
        stats: {
          colors: true,
          reasons: true
        },
        jshint: grunt.util._.merge(jshintConfig, {
          emitErrors: false,
          failOnHint: false
        }),
        module: {
          preLoaders: [{
            test: '\\.js$',
            exclude: 'node_modules',
            loader: 'jshint'
          }],
          loaders: loaders
        }
      },
      development: {
        debug: true,
        entry: {
          main: "./client/app.js"
        },
        output: {
          path: DEVELOPMENT_PATH+"/assets",
          filename: "[name].js"
        }
      },
      production: {
        debug: false,
        entry: {
          main: "./client/app.js"
        },
        output: {
          path: PRODUCTION_PATH+"/assets",
          filename: "[name].js",
          publicPath: "https://s3.amazonaws.com/www.curatescience.org/assets/"
        },
        plugins: [
          new webpack.optimize.OccurenceOrderPlugin(),
          new webpack.optimize.DedupePlugin()
        ]
      }
    },
    copy: {
      development: {
        files: [
          {src: "client/favicon.ico", dest: DEVELOPMENT_PATH + "/favicon.ico"},
          {src: "client/google_auth.jpg", dest: DEVELOPMENT_PATH + "/google_auth.jpg"}
        ]
      },
      production: {
        files: [
          {src: "client/favicon.ico", dest: PRODUCTION_PATH + "/favicon.ico"},
          {src: "client/google_auth.jpg", dest: PRODUCTION_PATH + "/google_auth.jpg"}
        ]
      }
    },
    watch: {
      webpack: {
        files: [
          "./client/**/*.js",
          "./client/**/*.scss"
        ],
        tasks: ["webpack:development"]
      },
      livereload: {
        options: {
          livereload: LIVERELOAD_PORT
        },
        files: [
          DEVELOPMENT_PATH + "/{,*/}*.html",
          DEVELOPMENT_PATH + "/assets/main.js"
        ]
      }
    },
    connect: {
      options: {
        port: 8000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: "localhost"
      },
      livereload: {
        options: {
          middleware: function (connect, options) {
            return [
              lrSnippet,
              mountFolder(connect, DEVELOPMENT_PATH +"/assets"),
              mountFolder(connect, DEVELOPMENT_PATH),
              handle404(DEVELOPMENT_PATH)
            ];
          }
        }
      },
      production: {
        options: {
          middleware: function (connect) {
            return [
              mountFolder(connect, PRODUCTION_PATH),
              handle404(PRODUCTION_PATH)
            ];
          }
        }
      }
    },
    preprocess: {
      development: {
        src: "client/index.html",
        dest: DEVELOPMENT_PATH + "/index.html"
      },
      production: {
        src: "client/index.html",
        dest: PRODUCTION_PATH + "/index.html"
      }
    },
    webfont: {
      icons: {
        src: "client/icons/*.svg",
        dest: "client/fonts",
        destCss: "client",
        options: {
          hashes: false,
          htmlDemo: false
        }
      }
    },
    open: {
      server: {
        url: "http://localhost:<%= connect.options.port %>/#/"
      }
    },
    aws: grunt.file.readJSON('./aws.json'),
    s3: {
      options: {
        key: '<%= aws.key %>',
        secret: '<%= aws.secret %>',
        bucket: '<%= aws.bucket %>',
        access: 'public-read',
        headers: {
          // Two Year cache policy (1000 * 60 * 60 * 24 * 730)
          "Cache-Control": "max-age=630720000, public",
          "Expires": new Date(Date.now() + 63072000000).toUTCString()
        }
      },
      production: {
        options: { gzip: true },
        upload: [
          {
            src: './build/production/public/index.html',
            dest: 'index.html'
          },
          {
            src: './build/production/public/favicon.ico',
            dest: 'favicon.ico'
          },
          {
            src: './build/production/public/google_auth.jpg',
            dest: 'google_auth.jpg'
          },
          {
            src: './build/production/public/assets/*',
            dest: 'assets/'
          },
          {
            src: './build/production/public/assets/assets/*',
            dest: 'assets/'
          }
        ]
      }
    },
    clean: {
      development: {
        src: [DEVELOPMENT_PATH+"/assets"]
      },
      production: {
        src: [PRODUCTION_PATH+"/assets"]
      }
    }
  });

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

    grunt.task.run([
      "connect:livereload",
      "build:development",
      "open",
      "watch"
    ]);
  });

  grunt.registerTask("build:development", ["clean:development", "env:development", "preprocess:development", "copy:development", "webfont", "webpack:development"]);
  grunt.registerTask("build:production", ["clean:production", "env:production", "preprocess:production", "copy:production", "webfont", "webpack:production"]);
  grunt.registerTask("deploy", ["build:production", "s3:production"]);

  grunt.registerTask("default", []);
};
<commit_msg>Gruntfile: add file-size limits back<commit_after>"use strict";

var LIVERELOAD_PORT = 35729;
var lrSnippet = require("connect-livereload")({
  port: LIVERELOAD_PORT
});

var mountFolder = function (connect, dir) {
  return connect.static(require("path").resolve(dir));
};

var webpack = require("webpack");
var fs = require("fs");

module.exports = function (grunt) {
  // Let *load-grunt-tasks* require everything
  require("load-grunt-tasks")(grunt);
  // Read configuration from package.json
  var pkgConfig = grunt.file.readJSON("package.json");
  var jshintConfig = grunt.file.readJSON(".jshintrc");

  var loaders = [{
    test: /\.css$/,
    loader: "style-loader!css-loader"
  }, {
    test: /\.s[ac]ss$/,
    loader: "style!css!sass"
  }, {
    test: /\.gif/,
    loader: "url-loader?limit=10000&minetype=image/gif"
  }, {
    test: /\.jpg/,
    loader: "url-loader?limit=10000&minetype=image/jpg"
  }, {
    test: /\.png/,
    loader: "url-loader?limit=10000&minetype=image/png"
  }, {
    test: /\.js$/,
    loader: "msx-loader"
  }, {
    test: /\.woff$/,
    loader: "url-loader?prefix=/assets/&limit=10000&minetype=application/font-woff"
  }, {
    test: /\.ttf$/,
    loader: "file-loader?prefix=/assets/"
  }, {
    test: /\.eot$/,
    loader: "file-loader?prefix=/assets/"
  }, {
    test: /\.svg$/,
    loader: "file-loader?prefix=/assets/"
  }];

  var handle404 = function(src) {
    return function(req, res) {
      var file = src + "/index.html";
      if (grunt.file.exists(file)) {
        return fs.createReadStream(file).pipe(res);
      }
      res.statusCode(404); // where's index.html?
      res.end();
    };
  };

  var DEVELOPMENT_PATH = "build/development";
  var PRODUCTION_PATH = "build/production/public";

  grunt.initConfig({
    pkg: pkgConfig,
    env: {
      development: {
        NODE_ENV: "development"
      },
      production: {
        NODE_ENV: "production"
      }
    },
    webpack: {
      options: {
        cache: true,
        stats: {
          colors: true,
          reasons: true
        },
        jshint: grunt.util._.merge(jshintConfig, {
          emitErrors: false,
          failOnHint: false
        }),
        module: {
          preLoaders: [{
            test: '\\.js$',
            exclude: 'node_modules',
            loader: 'jshint'
          }],
          loaders: loaders
        }
      },
      development: {
        debug: true,
        entry: {
          main: "./client/app.js"
        },
        output: {
          path: DEVELOPMENT_PATH+"/assets",
          filename: "[name].js"
        }
      },
      production: {
        debug: false,
        entry: {
          main: "./client/app.js"
        },
        output: {
          path: PRODUCTION_PATH+"/assets",
          filename: "[name].js",
          publicPath: "https://s3.amazonaws.com/www.curatescience.org/assets/"
        },
        plugins: [
          new webpack.optimize.OccurenceOrderPlugin(),
          new webpack.optimize.DedupePlugin()
        ]
      }
    },
    copy: {
      development: {
        files: [
          {src: "client/favicon.ico", dest: DEVELOPMENT_PATH + "/favicon.ico"},
          {src: "client/google_auth.jpg", dest: DEVELOPMENT_PATH + "/google_auth.jpg"}
        ]
      },
      production: {
        files: [
          {src: "client/favicon.ico", dest: PRODUCTION_PATH + "/favicon.ico"},
          {src: "client/google_auth.jpg", dest: PRODUCTION_PATH + "/google_auth.jpg"}
        ]
      }
    },
    watch: {
      webpack: {
        files: [
          "./client/**/*.js",
          "./client/**/*.scss"
        ],
        tasks: ["webpack:development"]
      },
      livereload: {
        options: {
          livereload: LIVERELOAD_PORT
        },
        files: [
          DEVELOPMENT_PATH + "/{,*/}*.html",
          DEVELOPMENT_PATH + "/assets/main.js"
        ]
      }
    },
    connect: {
      options: {
        port: 8000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: "localhost"
      },
      livereload: {
        options: {
          middleware: function (connect, options) {
            return [
              lrSnippet,
              mountFolder(connect, DEVELOPMENT_PATH +"/assets"),
              mountFolder(connect, DEVELOPMENT_PATH),
              handle404(DEVELOPMENT_PATH)
            ];
          }
        }
      },
      production: {
        options: {
          middleware: function (connect) {
            return [
              mountFolder(connect, PRODUCTION_PATH),
              handle404(PRODUCTION_PATH)
            ];
          }
        }
      }
    },
    preprocess: {
      development: {
        src: "client/index.html",
        dest: DEVELOPMENT_PATH + "/index.html"
      },
      production: {
        src: "client/index.html",
        dest: PRODUCTION_PATH + "/index.html"
      }
    },
    webfont: {
      icons: {
        src: "client/icons/*.svg",
        dest: "client/fonts",
        destCss: "client",
        options: {
          hashes: false,
          htmlDemo: false
        }
      }
    },
    open: {
      server: {
        url: "http://localhost:<%= connect.options.port %>/#/"
      }
    },
    aws: grunt.file.readJSON('./aws.json'),
    s3: {
      options: {
        key: '<%= aws.key %>',
        secret: '<%= aws.secret %>',
        bucket: '<%= aws.bucket %>',
        access: 'public-read',
        headers: {
          // Two Year cache policy (1000 * 60 * 60 * 24 * 730)
          "Cache-Control": "max-age=630720000, public",
          "Expires": new Date(Date.now() + 63072000000).toUTCString()
        }
      },
      production: {
        options: { gzip: true },
        upload: [
          {
            src: './build/production/public/index.html',
            dest: 'index.html'
          },
          {
            src: './build/production/public/favicon.ico',
            dest: 'favicon.ico'
          },
          {
            src: './build/production/public/google_auth.jpg',
            dest: 'google_auth.jpg'
          },
          {
            src: './build/production/public/assets/*',
            dest: 'assets/'
          },
          {
            src: './build/production/public/assets/assets/*',
            dest: 'assets/'
          }
        ]
      }
    },
    clean: {
      development: {
        src: [DEVELOPMENT_PATH+"/assets"]
      },
      production: {
        src: [PRODUCTION_PATH+"/assets"]
      }
    }
  });

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

    grunt.task.run([
      "connect:livereload",
      "build:development",
      "open",
      "watch"
    ]);
  });

  grunt.registerTask("build:development", ["clean:development", "env:development", "preprocess:development", "copy:development", "webfont", "webpack:development"]);
  grunt.registerTask("build:production", ["clean:production", "env:production", "preprocess:production", "copy:production", "webfont", "webpack:production"]);
  grunt.registerTask("deploy", ["build:production", "s3:production"]);

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


<commit_before>#!/usr/bin/env node
'use strict';

var nodemon = require('nodemon');
var ps = require('portscanner');
var async = require('async');
var fork = require('child_process').fork;

var options = require('./options');

var inspector = false;

var debug_port = 0;
var web_port = 0;

async.series([find_ports, main_part]);

function find_ports(callback){
	ps.findAPortNotInUse(options.port_range_start, options.port_range_end, '127.0.0.1', function(err, port){
		debug_port = port;
		ps.findAPortNotInUse(debug_port+1, options.port_range_end, '127.0.0.1', function(err, port){
			web_port = port;
			callback();
		});
	});
}

function main_part(callback){

	process.argv = process.argv.slice(2);

	var new_args = [];
	var debug_set_flag = false;
	for(var i=0; i < process.argv.length; i++){
		var arg = process.argv[i];
		if(arg.indexOf('--debug-brk') == 0 && debug_set_flag == false){
			new_args.push('--debug-brk='+debug_port);
			debug_set_flag = true;
		}else if(arg.indexOf('--debug') == 0 && debug_set_flag == false){
			new_args.push('--debug='+debug_port);
			debug_set_flag = true;
		} else {
			new_args.push(arg);
		}
	}

	if(!debug_set_flag){
		new_args.unshift('--debug='+debug_port);
	}

	process.argv = new_args;

	var str = ' ';
	for(var i=0; i < process.argv.length; i++){
		str += process.argv[i] + ' ';
	}

	nodemon(str);

	nodemon.on('start', function(){
		if(inspector != false) return;
		var inspectorArgs = ['--debug-port='+debug_port, '--web-port='+web_port];
		var forkOptions = { silent: false };
		inspector = fork(
			require.resolve('node-inspector/bin/inspector'),
			inspectorArgs,
			forkOptions
		);
	}).on('restart', function(){
		console.warn('Please refresh node-inspector window...');
	}).on('quit',function(){

	});
	callback();
}

<commit_msg>Node inspector parameter fine tunning<commit_after>#!/usr/bin/env node
'use strict';

var nodemon = require('nodemon');
var ps = require('portscanner');
var async = require('async');
var fork = require('child_process').fork;

var options = require('./options');

var inspector = false;

var debug_port = 0;
var web_port = 0;

async.series([find_ports, main_part]);

function find_ports(callback){
	ps.findAPortNotInUse(options.port_range_start, options.port_range_end, '127.0.0.1', function(err, port){
		debug_port = port;
		ps.findAPortNotInUse(debug_port+1, options.port_range_end, '127.0.0.1', function(err, port){
			web_port = port;
			callback();
		});
	});
}

function main_part(callback){

	process.argv = process.argv.slice(2);

	var new_args = [];
	var debug_set_flag = false;
	for(var i=0; i < process.argv.length; i++){
		var arg = process.argv[i];
		if(arg.indexOf('--debug-brk') == 0 && debug_set_flag == false){
			new_args.push('--debug-brk='+debug_port);
			debug_set_flag = true;
		}else if(arg.indexOf('--debug') == 0 && debug_set_flag == false){
			new_args.push('--debug='+debug_port);
			debug_set_flag = true;
		} else {
			new_args.push(arg);
		}
	}

	if(!debug_set_flag){
		new_args.unshift('--debug='+debug_port);
	}

	process.argv = new_args;

	var str = ' ';
	for(var i=0; i < process.argv.length; i++){
		str += process.argv[i] + ' ';
	}

	nodemon(str);

	nodemon.on('start', function(){
		if(inspector != false) return;
		var inspectorArgs = ['--debug-port='+debug_port, '--web-port='+web_port, '--no-preload', '--save-live-edit'];
		var forkOptions = { silent: false };
		inspector = fork(
			require.resolve('node-inspector/bin/inspector'),
			inspectorArgs,
			forkOptions
		);
	}).on('restart', function(){
		console.warn('Please refresh node-inspector window...');
	}).on('quit',function(){

	});
	callback();
}

<|endoftext|>


<commit_before>// grunt-contrib-livereload Middleware
'use strict';
var path = require('path');
var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;

var folderMount = function folderMount(connect, point) {
    return connect.static(path.resolve(point));
};

// Configuration
module.exports = function(grunt) {
    grunt.initConfig({
        pkg: '<json:package.json>',

        jshint: {
            all: ['scripts/plugins.js', 'scripts/main.js']
        },

        htmllint: {
            all: ['*.html']
        },

        clean: {
            deploy: ['dist']
        },

        connect: {
            livereload: {
                options: {
                    port: 9001,
                    middleware: function(connect, options) {
                        return [lrSnippet, folderMount(connect, '.')];
                    }
                }
            }
        },

        modernizr: {
            'devFile' : 'scripts/vendor/modernizr-2.6.2.min.js',
            'outputFile' : 'dist/scripts/vendor/modernizr-2.6.2.min.js',
            'extra' : {
                'shiv' : false,
                'printshiv' : true,
                'load' : false,
                'mq' : true,
                'cssclasses' : true
            },
            'extensibility' : {
                'addtest' : false,
                'prefixed' : false,
                'teststyles' : false,
                'testprops' : false,
                'testallprops' : false,
                'hasevents' : false,
                'prefixes' : false,
                'domprefixes' : false
            },
            'uglify' : true,
            'tests' : [],
            // parseFiles = true: crawl all *.js, *.css, *.scss files;
            // override by defining "files" array
            'parseFiles' : true,
            // 'files' : [],
            'matchCommunityTests' : false,
            'customTests' : [],
            'excludeFiles' : ['grunt.js','package.json']
        },

        concat: {
            dev: {
                src: ['scripts/plugins.js', 'scripts/main.js'],
                dest: 'scripts/master.js'
            }
        },

        uglify: {
            deploy: {
                src: 'scripts/master.js',
                dest: 'dist/scripts/master.js'
            },
            colorbox: {
                src: 'scripts/plugins/jquery.colorbox.js',
                dest: 'dist/scripts/plugins/jquery.colorbox.js'
            },
            syncheight: {
                src: 'scripts/plugins/jquery.syncheight.js',
                dest: 'dist/scripts/plugins/jquery.syncheight.js'
            },
            tabs: {
                src: 'scripts/plugins/jquery.tabs.js',
                dest: 'dist/scripts/plugins/jquery.tabs.js'
            },
            tipsy: {
                src: 'scripts/plugins/jquery.tipsy.js',
                dest: 'dist/scripts/plugins/jquery.tipsy.js'
            },
            slideshow: {
                src: 'scripts/plugins/responsiveslides.js',
                dest: 'dist/scripts/plugins/responsiveslides.js'
            }
        },

        compass: {
            dev: {
                options: {
                    sassDir: 'scss',
                    cssDir: 'styles',
                    imagesDir: 'img',
                    outputStyle: 'nested',
                    noLineComments: true,
                    force: true,
                    debugInfo: false
                }
            },
            deploy: {
                options: {
                    sassDir: 'scss',
                    cssDir: 'dist/styles',
                    imagesDir: 'img',
                    outputStyle: 'compressed',
                    noLineComments: true,
                    force: true,
                    debugInfo: false
                }
            }
        },

        imagemin: {
            deploy: {
                options: {
                    optimizationLevel: 3,
                    progressive: false
                },
                // Tweak if project requires complex directory structure
                files: {
                    'dist/img/': 'img/*'
                }
            }
        },

        copy: {
            deploy: {
                files: [
                    {
                        src: ['*.html',
                              '.htaccess',
                              'robots.txt',
                              'scripts/vendor/jquery-1.8.3.min.js',
                              'scripts/vendor/boxsizing.htc'],
                        dest: 'dist/'
                    }
                ]
            }
        },

        regarde: {
            html: {
                files: '*.html',
                tasks: ['concat:dev', 'compass:dev', 'livereload']
            },
            js: {
                files: ['scripts/plugins.js', 'scripts/main.js'],
                tasks: ['concat:dev', 'compass:dev', 'livereload']
            },
            scss: {
                files: 'scss/**/*.scss',
                tasks: ['concat:dev', 'compass:dev', 'livereload']
            }
        },

        hashres: {
            options: {
                encoding: 'utf-8',
                fileNameFormat: '${hash}.${ext}',
                renameFiles: true
            },
            deploy: {
                src: [
                    'dist/scripts/master.js',
                    'dist/styles/master.css',
                    'dist/styles/oldie.css'],
                dest: 'dist/*.html',

            }
        }
    });
    // Load required tasks
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-compass');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-connect');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-imagemin');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-livereload');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-hashres');
    grunt.loadNpmTasks('grunt-html');
    grunt.loadNpmTasks('grunt-modernizr');
    grunt.loadNpmTasks('grunt-regarde');
    // Default
    grunt.registerTask('default', ['livereload-start', 'connect', 'regarde']);
    // Development
    grunt.registerTask('check', ['htmllint', 'jshint']);
    // Deployment
    grunt.registerTask('deploy', ['clean:deploy', 'copy:deploy', 'concat:dev', 'compass:deploy', 'uglify', 'imagemin:deploy', 'modernizr', 'hashres:deploy']);
};
<commit_msg>Use a more conservative optimization level for imagemin.<commit_after>// grunt-contrib-livereload Middleware
'use strict';
var path = require('path');
var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;

var folderMount = function folderMount(connect, point) {
    return connect.static(path.resolve(point));
};

// Configuration
module.exports = function(grunt) {
    grunt.initConfig({
        pkg: '<json:package.json>',

        jshint: {
            all: ['scripts/plugins.js', 'scripts/main.js']
        },

        htmllint: {
            all: ['*.html']
        },

        clean: {
            deploy: ['dist']
        },

        connect: {
            livereload: {
                options: {
                    port: 9001,
                    middleware: function(connect, options) {
                        return [lrSnippet, folderMount(connect, '.')];
                    }
                }
            }
        },

        modernizr: {
            'devFile' : 'scripts/vendor/modernizr-2.6.2.min.js',
            'outputFile' : 'dist/scripts/vendor/modernizr-2.6.2.min.js',
            'extra' : {
                'shiv' : false,
                'printshiv' : true,
                'load' : false,
                'mq' : true,
                'cssclasses' : true
            },
            'extensibility' : {
                'addtest' : false,
                'prefixed' : false,
                'teststyles' : false,
                'testprops' : false,
                'testallprops' : false,
                'hasevents' : false,
                'prefixes' : false,
                'domprefixes' : false
            },
            'uglify' : true,
            'tests' : [],
            // parseFiles = true: crawl all *.js, *.css, *.scss files;
            // override by defining "files" array
            'parseFiles' : true,
            // 'files' : [],
            'matchCommunityTests' : false,
            'customTests' : [],
            'excludeFiles' : ['grunt.js','package.json']
        },

        concat: {
            dev: {
                src: ['scripts/plugins.js', 'scripts/main.js'],
                dest: 'scripts/master.js'
            }
        },

        uglify: {
            deploy: {
                src: 'scripts/master.js',
                dest: 'dist/scripts/master.js'
            },
            colorbox: {
                src: 'scripts/plugins/jquery.colorbox.js',
                dest: 'dist/scripts/plugins/jquery.colorbox.js'
            },
            syncheight: {
                src: 'scripts/plugins/jquery.syncheight.js',
                dest: 'dist/scripts/plugins/jquery.syncheight.js'
            },
            tabs: {
                src: 'scripts/plugins/jquery.tabs.js',
                dest: 'dist/scripts/plugins/jquery.tabs.js'
            },
            tipsy: {
                src: 'scripts/plugins/jquery.tipsy.js',
                dest: 'dist/scripts/plugins/jquery.tipsy.js'
            },
            slideshow: {
                src: 'scripts/plugins/responsiveslides.js',
                dest: 'dist/scripts/plugins/responsiveslides.js'
            }
        },

        compass: {
            dev: {
                options: {
                    sassDir: 'scss',
                    cssDir: 'styles',
                    imagesDir: 'img',
                    outputStyle: 'nested',
                    noLineComments: true,
                    force: true,
                    debugInfo: false
                }
            },
            deploy: {
                options: {
                    sassDir: 'scss',
                    cssDir: 'dist/styles',
                    imagesDir: 'img',
                    outputStyle: 'compressed',
                    noLineComments: true,
                    force: true,
                    debugInfo: false
                }
            }
        },

        imagemin: {
            deploy: {
                options: {
                    optimizationLevel: 0,
                    progressive: false
                },
                // Tweak if project requires complex directory structure
                files: {
                    'dist/img/': 'img/*'
                }
            }
        },

        copy: {
            deploy: {
                files: [
                    {
                        src: ['*.html',
                              '.htaccess',
                              'robots.txt',
                              'scripts/vendor/jquery-1.8.3.min.js',
                              'scripts/vendor/boxsizing.htc'],
                        dest: 'dist/'
                    }
                ]
            }
        },

        regarde: {
            html: {
                files: '*.html',
                tasks: ['concat:dev', 'compass:dev', 'livereload']
            },
            js: {
                files: ['scripts/plugins.js', 'scripts/main.js'],
                tasks: ['concat:dev', 'compass:dev', 'livereload']
            },
            scss: {
                files: 'scss/**/*.scss',
                tasks: ['concat:dev', 'compass:dev', 'livereload']
            }
        },

        hashres: {
            options: {
                encoding: 'utf-8',
                fileNameFormat: '${hash}.${ext}',
                renameFiles: true
            },
            deploy: {
                src: [
                    'dist/scripts/master.js',
                    'dist/styles/master.css',
                    'dist/styles/oldie.css'],
                dest: 'dist/*.html',

            }
        }
    });
    // Load required tasks
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-compass');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-connect');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-imagemin');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-livereload');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-hashres');
    grunt.loadNpmTasks('grunt-html');
    grunt.loadNpmTasks('grunt-modernizr');
    grunt.loadNpmTasks('grunt-regarde');
    // Default
    grunt.registerTask('default', ['livereload-start', 'connect', 'regarde']);
    // Development
    grunt.registerTask('check', ['htmllint', 'jshint']);
    // Deployment
    grunt.registerTask('deploy', ['clean:deploy', 'copy:deploy', 'concat:dev', 'compass:deploy', 'uglify', 'imagemin:deploy', 'modernizr', 'hashres:deploy']);
};
<|endoftext|>


<commit_before>(function(window, $, Argument, JsZip, require, app) {
    var Array = window.Array;
    var Node = window.Node;
    var Text = window.Text;
    var console = window.console;
    var minify = require('html-minifier').minify;
    var encodeURIComponent = window.encodeURIComponent;

    /**
     * Creates a new Exporter.
     *
     * @class
     */
    function Exporter() {
        var $html;

        /**
         * Get an Array of all Nodes, including their decendant Nodes.
         *
         * @param   {NodeList}  nodes
         * @returns {Array}
         */
        var getAllNodes = function(nodes) {
            var nodeArray = [];

            // Loop over nodes
            for (var i = 0; i < nodes.length; i++) {
                var node = nodes.item(i);

                // If node has childNodes, recurse function on childNodes and merge the result with the nodeArray.
                if (node.hasChildNodes()) {
                    nodeArray = nodeArray.concat(getAllNodes(node.childNodes));
                }
            }

            // Add the current set of nodes to the nodeArray
            return nodeArray.concat(Array.from(nodes));
        };

        var getCloneContainer = function() {
            if (typeof $html === 'undefined' || ! $html.length) {
                $html = $('#html');
            }

            return $html;
        };

        var clearHtml = function() {
            getCloneContainer().html('');
        };

        /**
         * Ensure none of the textContent is actually in ALL CAPS. Good for SEO.
         *
         * @param   {Node}  node
         */
        var normalizeCapitalisation = function(node) {
            var regex = /\b(?:[A-Z]{2,}(?:\W+[A-Z]+)*|[A-Z]+(?:\W+[A-Z]{2,})+)\b/g; // Regex to capture ALL CAPS substrings.
            var parentNode = node.parentNode;

            var $parent = $(parentNode);
            var $uppercaseElement = $parent.filter(function() {
                return $(this).css('text-transform') === 'uppercase';
            });

            // If the parentNode has text-transform: uppercase, normalize the textContent's capitalisation to ucwords.
            if ($uppercaseElement.length) {
                node.textContent = node.textContent.toLowerCase().ucwords();
            } else {
                var text = node.textContent;
                var matches = text.match(regex);

                // If we have ALL CAPS substrings
                if (matches) {
                    // normalize the capitalisation to ucwords and wrap in an .upperCase span
                    text = text.replace(regex, function(match) {
                        return '' + match.toLowerCase().ucwords() + '';
                    });

                    // Turn the resulting string back into an Array of Nodes.
                    var newNodes = Array.from($.parseHTML(text));

                    // Grab the last Node of the Array.
                    var replaceNode = newNodes.pop();

                    // Replace the original node with the last Node from the array.
                    parentNode.replaceChild(replaceNode, node);

                    // Insert all other Nodes before the replaced Node. Seems to be the only way to do this through the native DOM API.
                    for (var j = 0; j < newNodes.length; j++) {
                        parentNode.insertBefore(newNodes[j], replaceNode);
                    }
                }
            }
        };

        /**
         * Ensure braces are always outside em tags and colon always inside em tag.
         *
         * @param   {jQuery}  $container
         */
        var normalizeEmContent = function($container) {
            $container.find('em').each(function() {
                var em = this;
                var prev = em.previousSibling;
                var next = em.nextSibling;
                var parent = em.parentNode;

                var $em = $(em);
                var matches;

                // If there is a nextSibling and it starts with a colon, move the colon inside the em tag.
                if (next && next.textContent.match(/^:/)) {
                    next.textContent = next.textContent.slice(1, next.textContent.length);
                    $em.text($(em).text() + ':');
                }

                matches = $(em).text().match(/^(\s*(?:\(|\[|{|\s)+\s*)/);

                // If the content starts with a brace, optionally preceded by whitespace, move it to the previousSibling Node.
                if (matches) {
                    // If there is no previous sibling, create a new Text Node.
                    if (! prev) {
                        prev = new Text();

                        parent.insertBefore(prev, em);
                    }

                    prev.textContent = prev.textContent + matches[1];
                    $em.text($(em).text().replace(matches[1], ''));
                }

                matches = $(em).text().match(/(\s*(?:\)|\]|}|\s)+\s*)$/);

                // If the content ends with a brace, optionally proceded by whitespace, move it to the nextSibling Node.
                if (matches) {
                    // If there is no next sibling, create a new Text Node.
                    if (! next) {
                        next = new Text();

                        parent.appendChild(next);
                    }

                    next.textContent = matches[1] + next.textContent;
                    $em.text($(em).text().replace(matches[1], ''));
                }
            });
        };

        var removeVideo = function() {
            getCloneContainer().find('.videoLoader').children().remove();
        };

        var trimBreakTags = function() {
            getCloneContainer().find('br:first-child, br:last-child').remove();
        };

        var removeStyleAttributes = function() {
            getCloneContainer().find('[style]:not(.videoLoader)').removeAttr('style');
        };

        var prepareCtaForTemplate = function() {
            var $ctaLinks = getCloneContainer().find('a[data-magtool]');

            $ctaLinks.each(function() {
                var $this = $(this);

                $this.attr('href', "${CtaLinkXML['" + $this.data('magtool') + "'].@url}");
            });
        };

        var cleanUp = function() {
            var $container = app.Page.getContent();
            var nodes = getAllNodes($container.get(0).childNodes);

            // Loop over all Nodes and normalize Text Nodes' content.
            for (var i = 0; i < nodes.length; i++) {
                var node = nodes[i];

                if (node.nodeType == Node.TEXT_NODE) {
                    normalizeCapitalisation(node);
                }
            }

            normalizeEmContent($container);
        };

        var cleanUpForServer = function($container) {
            removeVideo();
            trimBreakTags();
            removeStyleAttributes();
            prepareCtaForTemplate();
        };

        var getHtml = function($elements) {
            var $cloneContainer = getCloneContainer();
            var html;

            cleanUp();

            clearHtml();
            $elements.clone().appendTo($cloneContainer);

            cleanUpForServer($cloneContainer);

            html = $cloneContainer.html();
            html = minify(html, {
                removeComments: true,
                collapseWhitespace: true,
                collapseBooleanAttributes: true,
                removeRedundantAttributes: true,
                removeEmptyAttributes: true,
                quoteCharacter: '"'
            });

            return html;
        };

        var getCreditsHtml = function() {
            return getHtml(app.Page.get().find('[class*="credits"]'));
        };

        var getContentHtml = function() {
            return getHtml(app.Page.get().find('.magazineContent > div:not([class*="credits"]):not(.edLetterList):not(.videoHolder)'));
        };

        var getScriptHtml = function() {
            var $elements = app.Page.getContent().find('script');
            $elements.add(app.Page.get().find('.videoHolder'));

            return getHtml($elements);
        };

        /**
         * Get the current page as an Object.
         *
         * @returns {object}
         */
        this.toJSON = function() {
            return {
                infoBlocks: getContentHtml(),
                credits: getCreditsHtml(),
                script: getScriptHtml()
            };
        };

        /**
         * Export the page to console. Mainly for testing.
         */
        this.toConsole = function(files) {
            files = Argument.default(files, ['infoBlocks', 'credits', 'script']);

            if ($.inArray('infoBlocks', files) > -1) {
                console.file('infoBlocks.html', getContentHtml());
            }

            if ($.inArray('credits', files) > -1) {
                console.file('credits.html', getCreditsHtml());
            }

            if ($.inArray('script', files) > -1) {
                console.file('script.html', getScriptHtml());
            }
        };

        // Holy shit this is possible this is so freaking cool.
        /**
         * Download the page files as a zip.
         */
        this.toFile = function(files) {
            files = Argument.default(files, ['infoBlocks', 'credits', 'script']);

            var zip = new JsZip();
            var page = 'page_' + app.Page.getNumber();
            var lang = app.getLanguage();
            var $a = $('');

            $a.hide().appendTo($('#magtoolComponents'));

            if ($.inArray('infoBlocks', files) > -1) {
                zip.file(page + '/' + lang + '/infoBlocks.html', getContentHtml());
            }

            if ($.inArray('credits', files) > -1) {
                zip.file(page + '/' + lang + '/credits.html', getCreditsHtml());
            }

            if ($.inArray('script', files) > -1) {
                zip.file(page + '/common/script.html', getScriptHtml());
            }

            $a.attr('href', 'data:application/zip;base64,' + zip.generate({type: 'base64'}))
                .attr('download', page + '.zip');

            $a.get(0).click();
            $a.remove();
        };
    }

    app.registerModule('Exporter', Exporter);
})(window, jQuery, Argument, JSZip, require, MagTool);
<commit_msg>Less strict Exporter.toFile args<commit_after>(function(window, $, Argument, JsZip, require, app) {
    var Array = window.Array;
    var Node = window.Node;
    var Text = window.Text;
    var console = window.console;
    var minify = require('html-minifier').minify;
    var encodeURIComponent = window.encodeURIComponent;

    /**
     * Creates a new Exporter.
     *
     * @class
     */
    function Exporter() {
        var $html;

        /**
         * Get an Array of all Nodes, including their decendant Nodes.
         *
         * @param   {NodeList}  nodes
         * @returns {Array}
         */
        var getAllNodes = function(nodes) {
            var nodeArray = [];

            // Loop over nodes
            for (var i = 0; i < nodes.length; i++) {
                var node = nodes.item(i);

                // If node has childNodes, recurse function on childNodes and merge the result with the nodeArray.
                if (node.hasChildNodes()) {
                    nodeArray = nodeArray.concat(getAllNodes(node.childNodes));
                }
            }

            // Add the current set of nodes to the nodeArray
            return nodeArray.concat(Array.from(nodes));
        };

        var getCloneContainer = function() {
            if (typeof $html === 'undefined' || ! $html.length) {
                $html = $('#html');
            }

            return $html;
        };

        var clearHtml = function() {
            getCloneContainer().html('');
        };

        /**
         * Ensure none of the textContent is actually in ALL CAPS. Good for SEO.
         *
         * @param   {Node}  node
         */
        var normalizeCapitalisation = function(node) {
            var regex = /\b(?:[A-Z]{2,}(?:\W+[A-Z]+)*|[A-Z]+(?:\W+[A-Z]{2,})+)\b/g; // Regex to capture ALL CAPS substrings.
            var parentNode = node.parentNode;

            var $parent = $(parentNode);
            var $uppercaseElement = $parent.filter(function() {
                return $(this).css('text-transform') === 'uppercase';
            });

            // If the parentNode has text-transform: uppercase, normalize the textContent's capitalisation to ucwords.
            if ($uppercaseElement.length) {
                node.textContent = node.textContent.toLowerCase().ucwords();
            } else {
                var text = node.textContent;
                var matches = text.match(regex);

                // If we have ALL CAPS substrings
                if (matches) {
                    // normalize the capitalisation to ucwords and wrap in an .upperCase span
                    text = text.replace(regex, function(match) {
                        return '' + match.toLowerCase().ucwords() + '';
                    });

                    // Turn the resulting string back into an Array of Nodes.
                    var newNodes = Array.from($.parseHTML(text));

                    // Grab the last Node of the Array.
                    var replaceNode = newNodes.pop();

                    // Replace the original node with the last Node from the array.
                    parentNode.replaceChild(replaceNode, node);

                    // Insert all other Nodes before the replaced Node. Seems to be the only way to do this through the native DOM API.
                    for (var j = 0; j < newNodes.length; j++) {
                        parentNode.insertBefore(newNodes[j], replaceNode);
                    }
                }
            }
        };

        /**
         * Ensure braces are always outside em tags and colon always inside em tag.
         *
         * @param   {jQuery}  $container
         */
        var normalizeEmContent = function($container) {
            $container.find('em').each(function() {
                var em = this;
                var prev = em.previousSibling;
                var next = em.nextSibling;
                var parent = em.parentNode;

                var $em = $(em);
                var matches;

                // If there is a nextSibling and it starts with a colon, move the colon inside the em tag.
                if (next && next.textContent.match(/^:/)) {
                    next.textContent = next.textContent.slice(1, next.textContent.length);
                    $em.text($(em).text() + ':');
                }

                matches = $(em).text().match(/^(\s*(?:\(|\[|{|\s)+\s*)/);

                // If the content starts with a brace, optionally preceded by whitespace, move it to the previousSibling Node.
                if (matches) {
                    // If there is no previous sibling, create a new Text Node.
                    if (! prev) {
                        prev = new Text();

                        parent.insertBefore(prev, em);
                    }

                    prev.textContent = prev.textContent + matches[1];
                    $em.text($(em).text().replace(matches[1], ''));
                }

                matches = $(em).text().match(/(\s*(?:\)|\]|}|\s)+\s*)$/);

                // If the content ends with a brace, optionally proceded by whitespace, move it to the nextSibling Node.
                if (matches) {
                    // If there is no next sibling, create a new Text Node.
                    if (! next) {
                        next = new Text();

                        parent.appendChild(next);
                    }

                    next.textContent = matches[1] + next.textContent;
                    $em.text($(em).text().replace(matches[1], ''));
                }
            });
        };

        var removeVideo = function() {
            getCloneContainer().find('.videoLoader').children().remove();
        };

        var trimBreakTags = function() {
            getCloneContainer().find('br:first-child, br:last-child').remove();
        };

        var removeStyleAttributes = function() {
            getCloneContainer().find('[style]:not(.videoLoader)').removeAttr('style');
        };

        var prepareCtaForTemplate = function() {
            var $ctaLinks = getCloneContainer().find('a[data-magtool]');

            $ctaLinks.each(function() {
                var $this = $(this);

                $this.attr('href', "${CtaLinkXML['" + $this.data('magtool') + "'].@url}");
            });
        };

        var cleanUp = function() {
            var $container = app.Page.getContent();
            var nodes = getAllNodes($container.get(0).childNodes);

            // Loop over all Nodes and normalize Text Nodes' content.
            for (var i = 0; i < nodes.length; i++) {
                var node = nodes[i];

                if (node.nodeType == Node.TEXT_NODE) {
                    normalizeCapitalisation(node);
                }
            }

            normalizeEmContent($container);
        };

        var cleanUpForServer = function($container) {
            removeVideo();
            trimBreakTags();
            removeStyleAttributes();
            prepareCtaForTemplate();
        };

        var getHtml = function($elements) {
            var $cloneContainer = getCloneContainer();
            var html;

            cleanUp();

            clearHtml();
            $elements.clone().appendTo($cloneContainer);

            cleanUpForServer($cloneContainer);

            html = $cloneContainer.html();
            html = minify(html, {
                removeComments: true,
                collapseWhitespace: true,
                collapseBooleanAttributes: true,
                removeRedundantAttributes: true,
                removeEmptyAttributes: true,
                quoteCharacter: '"'
            });

            return html;
        };

        var getCreditsHtml = function() {
            return getHtml(app.Page.get().find('[class*="credits"]'));
        };

        var getContentHtml = function() {
            return getHtml(app.Page.get().find('.magazineContent > div:not([class*="credits"]):not(.edLetterList):not(.videoHolder)'));
        };

        var getScriptHtml = function() {
            var $elements = app.Page.getContent().find('script');
            $elements.add(app.Page.get().find('.videoHolder'));

            return getHtml($elements);
        };

        /**
         * Get the current page as an Object.
         *
         * @returns {object}
         */
        this.toJSON = function() {
            return {
                infoBlocks: getContentHtml(),
                credits: getCreditsHtml(),
                script: getScriptHtml()
            };
        };

        /**
         * Export the page to console. Mainly for testing.
         */
        this.toConsole = function(files) {
            files = Argument.default(files, ['infoBlocks', 'credits', 'script']);

            if ($.inArray('infoBlocks', files) > -1) {
                console.file('infoBlocks.html', getContentHtml());
            }

            if ($.inArray('credits', files) > -1) {
                console.file('credits.html', getCreditsHtml());
            }

            if ($.inArray('script', files) > -1) {
                console.file('script.html', getScriptHtml());
            }
        };

        // Holy shit this is possible this is so freaking cool.
        /**
         * Download the page files as a zip.
         */
        this.toFile = function(files) {
            files = Argument.default(files, ['infoBlocks', 'credits', 'script']);

            var zip = new JsZip();
            var page = 'page_' + app.Page.getNumber();
            var lang = app.getLanguage();
            var $a = $('');

            $a.hide().appendTo($('#magtoolComponents'));

            if (typeof files === 'string') {
                files = files.split(/[,\s]+/);
            }

            if ($.inArray('infoBlocks', files) > -1 || $.inArray('infoblocks', files) > -1) {
                zip.file(page + '/' + lang + '/infoBlocks.html', getContentHtml());
            }

            if ($.inArray('credits', files) > -1) {
                zip.file(page + '/' + lang + '/credits.html', getCreditsHtml());
            }

            if ($.inArray('script', files) > -1) {
                zip.file(page + '/common/script.html', getScriptHtml());
            }

            $a.attr('href', 'data:application/zip;base64,' + zip.generate({type: 'base64'}))
                .attr('download', page + '.zip');

            $a.get(0).click();
            $a.remove();
        };
    }

    app.registerModule('Exporter', Exporter);
})(window, jQuery, Argument, JSZip, require, MagTool);
<|endoftext|>