<commit_before>module.exports = function(grunt) {
	"use strict";
	// Project configuration.
	grunt.initConfig({
		// Metadata.
		pkg: grunt.file.readJSON('package.json'),
		banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
			'<%= grunt.template.today("yyyy-mm-dd") %>\n' +
			'<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
			'* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
			' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
		// Task configuration.
		concat: {
			options: {
				banner: '<%= banner %>',
				stripBanners: true,
				process: false
			},
			dist: {
				src: ['src/apeye.js' ],
				dest: 'dist/apeye.js'
			},
			codemirror: {
				src: [
					'src/codemirror/lib/codemirror.js',
					'src/codemirror/mode/xml/xml.js',
					'src/codemirror/mode/http/http.js',
					'src/codemirror/lib/util/formatting.js',
					'src/codemirror/lib/util/multiplex.js'
				],
				dest: 'dist/codemirror.js'
			}
		},
		uglify: {
			dist: {
				options: { banner: '<%= banner %>' },
				src: '<%= concat.dist.dest %>',
				dest: 'dist/apeye.min.js'
			},
			codemirror: {
				src: '<%= concat.codemirror.dest %>',
				dest: 'dist/codemirror.min.js'
			}
		},
		qunit: {
			all: ['tests/runner.html']
		},
		jshint: {
			options: {
				curly: false,
				camelcase: true,
				eqnull: true,
				eqeqeq: true,
				undef: true,
				forin: true,
				latedef: true,
				newcap: true,
				unused: true,
				strict: true,
				jquery: true,
				browser: true,
				globals: {
					CodeMirror: false,
					DOMParser: false
				}
			},
			gruntfile: {
				options: { globals: { 'module': false } },
				src: 'Gruntfile.js'
			},
			src: {
				src: 'src/apeye*.js'
			},
			test: {
				options: {
					unused: false,
					strict: false,
					sub: true,
					globals: {
						// we create a global, modifiable APEye instance in tests for simplicity
						apeye: true,
						// following are standard QUnit globals
						module: false,
						assertInvisible: false,
						assertVisible: false,
						assertFieldValue: false,
						sinon: false,
						test: false,
						ok: false,
						strictEqual: false,
						deepEqual: false
					}
				},
				src: 'tests/apeye*.js'
			}
		},
		less: {
			compile: {
				options: {
					compress: true
				},
				files: {
					'dist/apeye.css': 'src/apeye.less'
				}
			}
		},
		watch: {
			gruntfile: {
				files: '<%= jshint.gruntfile.src %>',
				tasks: ['jshint:gruntfile']
			},
			src: {
				files: '<%= jshint.src.src %>',
				tasks: ['jshint:src', 'qunit']
			},
			test: {
				files: '<%= jshint.test.src %>',
				tasks: ['jshint:test', 'qunit']
			}
		}
	});

	// These plugins provide necessary tasks.
	grunt.loadNpmTasks('grunt-contrib-jshint');
	grunt.loadNpmTasks('grunt-contrib-qunit');
	grunt.loadNpmTasks('grunt-contrib-concat');
	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.loadNpmTasks('grunt-contrib-less');

	// Default task.
	grunt.registerTask('default', ['jshint', 'less', 'qunit', 'concat', 'uglify']);
};
<commit_msg>Change Gruntfile to copy codemirror.css to dist/, and to stop prepending the banner to codemirror.js<commit_after>module.exports = function(grunt) {
	"use strict";
	// Project configuration.
	grunt.initConfig({
		// Metadata.
		pkg: grunt.file.readJSON('package.json'),
		banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
			'<%= grunt.template.today("yyyy-mm-dd") %>\n' +
			'<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
			'* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
			' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
		// Task configuration.
		concat: {
			apeye: {
				options: {
					banner: '<%= banner %>',
					stripBanners: true
				},
				src: ['src/apeye.js' ],
				dest: 'dist/apeye.js'
			},
			codemirror: {
				files: {
					'dist/codemirror.js': [
						'src/codemirror/lib/codemirror.js',
						'src/codemirror/mode/xml/xml.js',
						'src/codemirror/mode/http/http.js',
						'src/codemirror/lib/util/formatting.js',
						'src/codemirror/lib/util/multiplex.js'
					],
					'dist/codemirror.css': 'src/codemirror/lib/codemirror.css'
				}
			}
		},
		uglify: {
			dist: {
				options: { banner: '<%= banner %>' },
				src: 'dist/apeye.js',
				dest: 'dist/apeye.min.js'
			},
			codemirror: {
				src: 'dist/codemirror.js',
				dest: 'dist/codemirror.min.js'
			}
		},
		qunit: {
			all: ['tests/runner.html']
		},
		jshint: {
			options: {
				curly: false,
				camelcase: true,
				eqnull: true,
				eqeqeq: true,
				undef: true,
				forin: true,
				latedef: true,
				newcap: true,
				unused: true,
				strict: true,
				jquery: true,
				browser: true,
				globals: {
					CodeMirror: false,
					DOMParser: false
				}
			},
			gruntfile: {
				options: { globals: { 'module': false } },
				src: 'Gruntfile.js'
			},
			src: {
				src: 'src/apeye*.js'
			},
			test: {
				options: {
					unused: false,
					strict: false,
					sub: true,
					globals: {
						// we create a global, modifiable APEye instance in tests for simplicity
						apeye: true,
						// following are standard QUnit globals
						module: false,
						assertInvisible: false,
						assertVisible: false,
						assertFieldValue: false,
						sinon: false,
						test: false,
						ok: false,
						strictEqual: false,
						deepEqual: false
					}
				},
				src: 'tests/apeye*.js'
			}
		},
		less: {
			compile: {
				options: {
					compress: true
				},
				files: {
					'dist/apeye.css': 'src/apeye.less'
				}
			}
		},
		watch: {
			gruntfile: {
				files: '<%= jshint.gruntfile.src %>',
				tasks: ['jshint:gruntfile']
			},
			src: {
				files: '<%= jshint.src.src %>',
				tasks: ['jshint:src', 'qunit']
			},
			test: {
				files: '<%= jshint.test.src %>',
				tasks: ['jshint:test', 'qunit']
			}
		}
	});

	// These plugins provide necessary tasks.
	grunt.loadNpmTasks('grunt-contrib-jshint');
	grunt.loadNpmTasks('grunt-contrib-qunit');
	grunt.loadNpmTasks('grunt-contrib-concat');
	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.loadNpmTasks('grunt-contrib-less');

	// Default task.
	grunt.registerTask('default', ['jshint', 'less', 'qunit', 'concat', 'uglify']);
};
<|endoftext|>


<commit_before>/* jshint camelcase: false */
module.exports = function (grunt) {
  'use strict';

  grunt.initConfig({

    // load module meta data
    pkg: grunt.file.readJSON('package.json'),

    // define a src set of files for other tasks
    src: {
      lint: ['Gruntfile.js', 'index.js', 'lib/**/*.js', 'test/*.js'],
      complexity: ['index.js', 'lib/**/*.js'],
      test: ['test/*.js'],
      src: ['index.js', 'lib/**/*.js']
    },

    // clean automatically generated helper files & docs
    clean: {
      coverage: ['coverage', 'report/coverage'],
      report: ['report/complexity', 'report/api', 'report/docs'],
      reportZip: ['report.zip']
    },

    // linting
    jshint: {
      options: {
        jshintrc: '.jshintrc'
      },
      all: '<%= src.lint %>'
    },

    // testing
    mochaTest: {
      test: {
        options: {
          reporter: 'spec',
          require: 'coverage/blanket'
        },
        src: '<%= src.test %>'
      },
      coverage: {
        options: {
          reporter: 'html-cov',
          quiet: true,
          captureFile: 'report/coverage/index.html'
        },
        src: '<%= src.test %>'
      },
      jsoncoverage: {
        options: {
          reporter: 'json-cov',
          quiet: true,
          captureFile: 'report/coverage/coverage.json'
        },
        src: '<%= src.test %>'
      }
    },

    // code metrics
    complexity: {
      generic: {
        src: '<%= src.complexity %>',
        options: {
          cyclomatic: 4,
          halstead: 20,
          maintainability: 60
        }
      }
    },
    plato: {
      generic: {
        options : {
          jshint : grunt.file.readJSON('.jshintrc')
        },
        files: {
          'report/complexity': '<%= src.complexity %>',
        }
      }
    },

    // api docs
    yuidoc: {
      compile: {
        name: '<%= pkg.name %>',
        description: '<%= pkg.description %>',
        version: '<%= pkg.version %>',
        url: '<%= pkg.homepage %>',
        options: {
          paths: '.',
          outdir: 'report/api'
        }
      }
    },

    // user docs
    documantix: {
      options: {
        header: 'dalekjs/dalekjs.com/master/assets/header.html',
        footer: 'dalekjs/dalekjs.com/master/assets/footer.html',
        target: 'report/docs'
      },
      src: ['index.js']
    },

    // add current timestamp to the html document
    includereplace: {
      dist: {
        options: {
          globals: {
            timestamp: '<%= grunt.template.today("dddd, mmmm dS, yyyy, h:MM:ss TT") %>'
          },
        },
        src: 'report/docs/*.html',
        dest: '.'
      }
    },

    // compress artifacts
    compress: {
      main: {
        options: {
          archive: 'report.zip'
        },
        files: [
          {src: ['report/**'], dest: '/'}
        ]
      }
    }

  });

  // prepare files & folders for grunt:plato & coverage
  grunt.registerTask('preparePlato', function () {
    var fs = require('fs');

    var platoDummyFolders = ['report', 'report/complexity', 'report/complexity/files', 'report/complexity/files/index_js', 'report/complexity/files/lib', 'report/complexity/files/lib/commands', 'report/complexity/files/lib_commands_marionette', 'report/complexity/files/lib_commands_webdriver', 'report/complexity/files/lib_webdriver_js', 'report/complexity/files/lib_marionette_js'];
    var platoDummyFiles = ['/report/complexity/report.history.json', '/report/complexity/files/report.history.json', '/report/complexity/files/index_js/report.history.json', '/report/complexity/files/lib_webdriver_js/report.history.json', '/report/complexity/files/lib_marionette_js/report.history.json'];

    // loopy loop
    ['/lib/commands/marionette/', '/lib/commands/webdriver/'].forEach(function (folder) {
      fs.readdirSync(__dirname + folder).forEach(function (file) {
        var platoFolder = '/report/complexity/files/' + folder.substring(1).replace(/\//g, '_') + file.replace('.js', '_js');
        platoDummyFolders.push(platoFolder);
        platoDummyFiles.push(platoFolder + '/report.history.json');
      });
    });

    // generate dirs for docs & reports
    platoDummyFolders.forEach(function (path) {
      if (!fs.existsSync(__dirname + '/' + path)) {
        fs.mkdirSync(__dirname + '/' + path);
      }
    });

    // store some dummy reports, so that grunt plato doesnt complain
    platoDummyFiles.forEach(function (file) {
      if (!fs.existsSync(__dirname + file)) {
        fs.writeFileSync(__dirname + file, '{}');
      }
    });
  });

  // prepare files & folders for coverage
  grunt.registerTask('prepareCoverage', function () {
    var fs = require('fs');

    // generate folders
    ['coverage', 'report', 'report/coverage'].forEach(function (folder) {
      if (!fs.existsSync(__dirname + '/' + folder)) {
        fs.mkdirSync(__dirname + '/' + folder);
      }
    });

    // generate code coverage helper file
    var coverageHelper = 'require("blanket")({pattern: [require("fs").realpathSync(__dirname + "/../index.js"), require("fs").realpathSync(__dirname + "/../lib/")]});';
    if (!fs.existsSync(__dirname + '/coverage/blanket.js')) {
      fs.writeFileSync(__dirname + '/coverage/blanket.js', coverageHelper);
    }
  });

  // generates a coverage badge
  grunt.registerTask('generateCoverageBadge', function () {
    var fs = require('fs');
    if (fs.existsSync(__dirname + '/node_modules/coverage-badge')) {
      if (fs.existsSync(__dirname + '/report/coverage/coverage.json')) {
        var green = [147,188,59];
        var yellow = [166,157,0];
        var red = [189,0,2];

        var getColor = function (coverage) {
          if (coverage > 90) {
            return mixColors(yellow, green, (coverage-90)/10);
          }

          if (coverage > 80) {
            return mixColors(red, yellow, (coverage-80)/10);
          }

          return createColor(red);
        };

        var mixColors = function (from, to, ratio) {
          var result = [], i;
          for (i=0; i<3; i++) {
            result[i] = Math.round(from[i] + (ratio * (to[i]-from[i])));
          }
          return createColor(result);
        };

        var createColor = function (values) {
          return 'rgba('+values[0]+','+values[1]+','+values[2]+',1)';
        };

        var Badge = require(__dirname + '/node_modules/coverage-badge/lib/Badge.js');
        var badgeFn = function(coverage) {
          coverage = Math.floor(Number(coverage));
          var badge = new Badge({
            box_color: getColor(coverage),
            box_text: coverage+'%',
            label_text: 'cov',
            height: 18,
            width: 49,
            box_width: 25,
            rounding: 0,
            padding: 0,
            label_font: '7pt DejaVu Sans',
            box_font: 'bold 7pt DejaVu Sans'
          });
          return badge.stream();
        };

        var coverage = JSON.parse(fs.readFileSync(__dirname + '/report/coverage/coverage.json')).coverage;
        var file = fs.createWriteStream(__dirname + '/report/coverage/coverage.png');
        badgeFn(coverage).pipe(file);
      }
    }
  });

  // load 3rd party tasks
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-yuidoc');
  grunt.loadNpmTasks('grunt-contrib-compress');
  grunt.loadNpmTasks('grunt-mocha-test');
  grunt.loadNpmTasks('grunt-complexity');
  grunt.loadNpmTasks('grunt-documantix');
  grunt.loadNpmTasks('grunt-plato');

  // define runner tasks
  grunt.registerTask('lint', 'jshint');
  grunt.registerTask('test', ['clean:coverage', 'prepareCoverage', 'lint', 'mochaTest', 'generateCoverageBadge', 'complexity']);
  grunt.registerTask('docs', ['clean:reportZip', 'clean:report', 'preparePlato', 'plato', 'documantix', 'includereplace', 'yuidoc', 'compress']);
  grunt.registerTask('all', ['clean', 'test', 'docs']);

};
<commit_msg>Fixed build<commit_after>/* jshint camelcase: false */
module.exports = function (grunt) {
  'use strict';

  grunt.initConfig({

    // load module meta data
    pkg: grunt.file.readJSON('package.json'),

    // define a src set of files for other tasks
    src: {
      lint: ['Gruntfile.js', 'index.js', 'lib/**/*.js', 'test/*.js'],
      complexity: ['index.js', 'lib/**/*.js'],
      test: ['test/*.js'],
      src: ['index.js', 'lib/**/*.js']
    },

    // clean automatically generated helper files & docs
    clean: {
      coverage: ['coverage', 'report/coverage'],
      report: ['report/complexity', 'report/api', 'report/docs'],
      reportZip: ['report.zip']
    },

    // linting
    jshint: {
      options: {
        jshintrc: '.jshintrc'
      },
      all: '<%= src.lint %>'
    },

    // testing
    mochaTest: {
      test: {
        options: {
          reporter: 'spec',
          require: 'coverage/blanket'
        },
        src: '<%= src.test %>'
      },
      coverage: {
        options: {
          reporter: 'html-cov',
          quiet: true,
          captureFile: 'report/coverage/index.html'
        },
        src: '<%= src.test %>'
      },
      jsoncoverage: {
        options: {
          reporter: 'json-cov',
          quiet: true,
          captureFile: 'report/coverage/coverage.json'
        },
        src: '<%= src.test %>'
      }
    },

    // code metrics
    complexity: {
      generic: {
        src: '<%= src.complexity %>',
        options: {
          cyclomatic: 4,
          halstead: 20,
          maintainability: 60
        }
      }
    },
    plato: {
      generic: {
        options : {
          jshint : grunt.file.readJSON('.jshintrc')
        },
        files: {
          'report/complexity': '<%= src.complexity %>',
        }
      }
    },

    // api docs
    yuidoc: {
      compile: {
        name: '<%= pkg.name %>',
        description: '<%= pkg.description %>',
        version: '<%= pkg.version %>',
        url: '<%= pkg.homepage %>',
        options: {
          paths: '.',
          outdir: 'report/api'
        }
      }
    },

    // user docs
    documantix: {
      options: {
        header: 'dalekjs/dalekjs.com/master/assets/header.html',
        footer: 'dalekjs/dalekjs.com/master/assets/footer.html',
        target: 'report/docs'
      },
      src: ['index.js']
    },

    // add current timestamp to the html document
    includereplace: {
      dist: {
        options: {
          globals: {
            timestamp: '<%= grunt.template.today("dddd, mmmm dS, yyyy, h:MM:ss TT") %>'
          },
        },
        src: 'report/docs/*.html',
        dest: '.'
      }
    },

    // compress artifacts
    compress: {
      main: {
        options: {
          archive: 'report.zip'
        },
        files: [
          {src: ['report/**'], dest: '/'}
        ]
      }
    }

  });

  // prepare files & folders for grunt:plato & coverage
  grunt.registerTask('preparePlato', function () {
    var fs = require('fs');

    var platoDummyFolders = ['report', 'report/complexity', 'report/complexity/files', 'report/complexity/files/index_js', 'report/complexity/files/lib', 'report/complexity/files/lib/commands', 'report/complexity/files/lib_commands_marionette', 'report/complexity/files/lib_commands_webdriver', 'report/complexity/files/lib_webdriver_js', 'report/complexity/files/lib_marionette_js'];
    var platoDummyFiles = ['/report/complexity/report.history.json', '/report/complexity/files/report.history.json', '/report/complexity/files/index_js/report.history.json', '/report/complexity/files/lib_webdriver_js/report.history.json', '/report/complexity/files/lib_marionette_js/report.history.json'];

    // loopy loop
    ['/lib/commands/marionette/', '/lib/commands/webdriver/'].forEach(function (folder) {
      fs.readdirSync(__dirname + folder).forEach(function (file) {
        var platoFolder = '/report/complexity/files/' + folder.substring(1).replace(/\//g, '_') + file.replace('.js', '_js');
        platoDummyFolders.push(platoFolder);
        platoDummyFiles.push(platoFolder + '/report.history.json');
      });
    });

    // generate dirs for docs & reports
    platoDummyFolders.forEach(function (path) {
      if (!fs.existsSync(__dirname + '/' + path)) {
        fs.mkdirSync(__dirname + '/' + path);
      }
    });

    // store some dummy reports, so that grunt plato doesnt complain
    platoDummyFiles.forEach(function (file) {
      if (!fs.existsSync(__dirname + file)) {
        fs.writeFileSync(__dirname + file, '{}');
      }
    });
  });

  // prepare files & folders for coverage
  grunt.registerTask('prepareCoverage', function () {
    var fs = require('fs');

    // generate folders
    ['coverage', 'report', 'report/coverage'].forEach(function (folder) {
      if (!fs.existsSync(__dirname + '/' + folder)) {
        fs.mkdirSync(__dirname + '/' + folder);
      }
    });

    // generate code coverage helper file
    var coverageHelper = 'require("blanket")({pattern: [require("fs").realpathSync(__dirname + "/../index.js"), require("fs").realpathSync(__dirname + "/../lib/")]});';
    if (!fs.existsSync(__dirname + '/coverage/blanket.js')) {
      fs.writeFileSync(__dirname + '/coverage/blanket.js', coverageHelper);
    }
  });

  // generates a coverage badge
  grunt.registerTask('generateCoverageBadge', function () {
    var fs = require('fs');
    if (fs.existsSync(__dirname + '/node_modules/coverage-badge')) {
      if (fs.existsSync(__dirname + '/report/coverage/coverage.json')) {
        var green = [147,188,59];
        var yellow = [166,157,0];
        var red = [189,0,2];

        var getColor = function (coverage) {
          if (coverage > 90) {
            return mixColors(yellow, green, (coverage-90)/10);
          }

          if (coverage > 80) {
            return mixColors(red, yellow, (coverage-80)/10);
          }

          return createColor(red);
        };

        var mixColors = function (from, to, ratio) {
          var result = [], i;
          for (i=0; i<3; i++) {
            result[i] = Math.round(from[i] + (ratio * (to[i]-from[i])));
          }
          return createColor(result);
        };

        var createColor = function (values) {
          return 'rgba('+values[0]+','+values[1]+','+values[2]+',1)';
        };

        var Badge = require(__dirname + '/node_modules/coverage-badge/lib/Badge.js');
        var badgeFn = function(coverage) {
          coverage = Math.floor(Number(coverage));
          var badge = new Badge({
            box_color: getColor(coverage),
            box_text: coverage+'%',
            label_text: 'cov',
            height: 18,
            width: 49,
            box_width: 25,
            rounding: 0,
            padding: 0,
            label_font: '7pt DejaVu Sans',
            box_font: 'bold 7pt DejaVu Sans'
          });
          return badge.stream();
        };

        var coverage = JSON.parse(fs.readFileSync(__dirname + '/report/coverage/coverage.json')).coverage;
        var file = fs.createWriteStream(__dirname + '/report/coverage/coverage.png');
        badgeFn(coverage).pipe(file);
      }
    }
  });

  // load 3rd party tasks
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-yuidoc');
  grunt.loadNpmTasks('grunt-contrib-compress');
  grunt.loadNpmTasks('grunt-mocha-test');
  grunt.loadNpmTasks('grunt-complexity');
  grunt.loadNpmTasks('grunt-documantix');
  grunt.loadNpmTasks('grunt-plato');
  grunt.loadNpmTasks('grunt-include-replace');

  // define runner tasks
  grunt.registerTask('lint', 'jshint');
  grunt.registerTask('test', ['clean:coverage', 'prepareCoverage', 'lint', 'mochaTest', 'generateCoverageBadge', 'complexity']);
  grunt.registerTask('docs', ['clean:reportZip', 'clean:report', 'preparePlato', 'plato', 'documantix', 'includereplace', 'yuidoc', 'compress']);
  grunt.registerTask('all', ['clean', 'test', 'docs']);

};
<|endoftext|>


<commit_before>#!/usr/bin/env node

const Listr = require('listr')
const updateRenderer = require('listr-update-renderer')
const verboseRenderer = require('listr-verbose-renderer')
const chalk = require('chalk')
const Promise = require('bluebird')
const program = require('commander')
const { parse } = require('babylon')
const { File } = require('babel-core')
const traverse = require('babel-traverse').default
const generate = require('prettier').__debug.formatAST
const t = require('babel-types')
const path = require('path')
const mkdirp = require('mkdirp-then')
const fs = require('mz/fs')
const login = require('plug-login')
const got = require('got')

const pkg = require('../package.json')
const cleanAst = require('./clean-ast')
const createMappingFile = require('./create-mapping')

let _v

program
  .usage('[options]')
  .version(pkg.version)
  .option('-m, --mapping [file]', 'File containing the mapping JSON ' +
            '(optional, it\'s auto-generated if no file is given)')
  .option('-o, --out [dir]', 'Output directory [out/]', 'out/')
  .option('-v, --verbose', 'Use verbose output instead of bullet list', false)
  .parse(process.argv)

function fetchAppFile (url, progress) {
  return new Promise((resolve, reject) => {
    let contents = ''

    const stream = got.stream(url)
    stream.on('response', (res) => {
      const size = parseInt(res.headers['content-length'], 10)
      progress(0, size)
      stream.on('data', (chunk) => {
        contents += chunk.toString('utf8')
        progress(contents.length, size)
      })
    })

    stream.on('error', reject)
    stream.on('end', () => {
      progress(contents.length, contents.length)
      resolve(contents)
    })
  })
}

function variableNameFor (dep, mapping) {
  const libraryNames = {
    jquery: '$',
    backbone: 'Backbone',
    handlebars: 'Handlebars',
    underscore: '_'
  }
  return dep in libraryNames
       ? libraryNames[dep]
       : dep.indexOf('hbs!templates/') === 0
       ? 'template' + dep.split('/').pop()
       : dep in mapping
       ? mapping[dep].split('/').pop().replace(/-/g, '_')
       : dep
}

function sliceTokens (tokens, loc) {
  let start = 0
  while (tokens[start].start < loc.start) {
    start++
  }
  let end = start
  while (tokens[end].end < loc.end) {
    end++
  }
  return tokens.slice(start, end)
}

function parseModules (str, progress) {
  const ast = parse(str)
  const modules = {}
  traverse(ast, {
    CallExpression ({ node }) {
      if (t.isIdentifier(node.callee, { name: 'define' })) {
        let [ name, deps, factory ] = node.arguments
        if (t.isArrayExpression(deps)) {
          deps = deps.elements
        } else {
          factory = deps
          deps = []
        }

        const tokens = sliceTokens(ast.tokens, node)
        const code = str.slice(node.start, node.end)

        const comments = []
        const program = t.file(
          t.program([ t.expressionStatement(factory) ]),
          comments,
          tokens
        )

        const file = new File({
          options: {},
          passes: []
        })
        file.addAst(program)
        progress(name.value)
        modules[name.value] = {
          deps,
          file,
          code,
          ast: factory
        }
      }
    }
  })

  progress(null)
  return modules
}

function findReturnVar (ast) {
  const lastSt = ast.body[ast.body.length - 1]
  if (t.isReturnStatement(lastSt)) {
    const retVal = lastSt.argument
    return t.isNewExpression(retVal)
      ? retVal.callee
      : t.isIdentifier(retVal) && retVal.name !== 'undefined'
      ? retVal
      : null
  }
}

async function cleanModules (modules, progress) {
  const names = Object.keys(modules)
  for (let i = 0; i < names.length; i += 1) {
    const name = names[i]

    cleanAst(modules[name].file.ast)

    await progress(i + 1, names.length)
  }
}

async function remapModuleNames (modules, mapping, progress) {
  const names = Object.keys(modules)

  for (let index = 0; index < names.length; index += 1) {
    const name = names[index]
    const { ast, deps } = modules[name]
    const params = ast.params && ast.params.map((param) => param.name)

    if (!params) {
      await progress(index + 1, names.length)
      continue
    }

    const renames = []
    // build ast of dependency require()s
    const depsAst = deps.map((dep, i) => {
      if (!params[i]) {
        params[i] = '__' + i
      }

      let newName = 'unknown'
      // rename variables according to their module names
      if (mapping[dep.value]) {
        newName = variableNameFor(dep.value, mapping)
        renames.push({ from: params[i], to: newName })
      } else if (/^hbs!templates\//.test(dep.value)) {
        newName = 'template' + dep.value.split('/').pop()
        renames.push({ from: params[i], to: newName })
      }

      if (dep.value in mapping) {
        const originalName = dep.value
        dep.value = mapping[originalName]
        dep.trailingComments = [
          { type: 'Block', value: ` was ${originalName}` }
        ]
      } else {
        dep.trailingComments = [
          { type: 'Block', value: ' Unknown module' }
        ]
      }

      return t.variableDeclaration('var', [
        t.variableDeclarator(
          t.identifier(params[i]),
          t.callExpression(t.identifier('require'), [dep])
        )
      ])
    })

    // move dependencies from the define() call
    // to the factory body
    ast.body.body = depsAst.concat(ast.body.body)
    ast.params = [
      t.identifier('require'),
      t.identifier('exports'),
      t.identifier('module')
    ]

    const returnVar = findReturnVar(ast.body)
    if (returnVar) {
      renames.push({
        from: returnVar.name,
        to: variableNameFor(name, mapping)
      })
    }

    processRenames(modules[name].file.ast, renames)

    await progress(index + 1, names.length)
  }
}

function getDependents (modules, name) {
  const isDep = (d) => d.value === name

  return Object.keys(modules).filter((name) =>
    modules[name].deps.some(isDep)
  )
}

function findMemberExpressionName (ast) {
  const body = ast.body
  for (let i = 0, l = body.length; i < l; i++) {
    if (t.isExpressionStatement(body[i]) &&
        t.isAssignmentExpression(body[i].expression) &&
        t.isMemberExpression(body[i].expression.left) &&
        t.isIdentifier(body[i].expression.left.object)) {
      return body[i].expression.left.property
    }
  }
}

function addMappingForUnknownModules (modules, mapping) {
  for (const orig in mapping) {
    if (mapping[orig] === 'plug/server/socketReceiver') {
      // websocket event receiver modules don't export anything,
      // so they cannot be identified individually by plug-modules.
      // however, we have accesss to their full source here, so
      // we can extract them anyway!
      // socket event receivers set properties on a shared object,
      // which will actually be require()d by plug.dj source code,
      // and which can also be identified by plug-modules. here, we
      // can find all modules that depend on socketReceiver, and find
      // the relevant assignments.
      getDependents(modules, orig).forEach((name) => {
        const prop = findMemberExpressionName(modules[name].ast.body)
        if (prop) {
          // some of these modules have multiple event receivers, so we
          // rename them to be a bit more clear.
          const niceName = {
            // contains a bunch of booth/wait list moderation events
            modAddDJ: 'plug/server/socket/modBooth',
            // contains subscription, XP, and PP events
            earn: 'plug/server/socket/currency',
            // contains multiple events for updates to the current room
            roomNameUpdate: 'plug/server/socket/roomUpdate',
            // this is actually the websocket manager module,
            // and it sets the window._gws property to undefined.
            // it really is just a false positive but we can abuse
            // it to get the proper module, anyway.
            // TODO detect this in a less stupid way
            _gws: 'plug/server/socket'
          }[prop.name] || 'plug/server/socket/' + prop.name
          mapping[name] = niceName
        }
      })
    } else if (mapping[orig] === 'plug/util/API') {
      getDependents(modules, orig).forEach((name) => {
        const prop = findMemberExpressionName(modules[name].ast.body)
        if (prop) {
          const niceName = {
            getAdmins: 'admins',
            getAmbassadors: 'ambassadors',
            getAudience: 'audience',
            getBannedUsers: 'bannedUsers',
            getDJ: 'dj',
            getHistory: 'history',
            getHost: 'host',
            getMedia: 'media',
            getNextMedia: 'nextMedia',
            getScore: 'score',
            getStaff: 'staff',
            getTimeElapsed: 'playTime',
            getUser: 'users',
            getWaitList: 'waitlist',
            moderateForceSkip: 'moderator',
            sendChat: 'chat',
            setVolume: 'volume'
          }[prop.name] || prop.name
          mapping[name] = 'plug/util/api/' + niceName
        }
      })
    }
  }
}

function processRenames (ast, renames) {
  traverse(ast, {
    FunctionExpression (path) {
      renames.forEach(({ from, to }) => {
        if (path.scope.hasBinding(to)) {
          path.scope.rename(to, path.scope.generateUid(to))
        }
        path.scope.rename(from, to)
      })
      path.stop()
    }
  })
  return ast
}

function extract (modules, mapping, progress) {
  const moduleNames = Object.keys(modules)
  return Promise.each(moduleNames, (name, i) => {
    const mod = modules[name]

    const moduleIdentifier = t.stringLiteral(name)
    moduleIdentifier.raw = JSON.stringify(name)
    if (name in mapping) {
      moduleIdentifier.value = mapping[name]
      moduleIdentifier.trailingComments = [
        { type: 'Block', value: ` was ${name}` }
      ]
    } else {
      moduleIdentifier.trailingComments = [
        { type: 'Block', value: ' Unknown module' }
      ]
    }

    const ast = t.program([
      t.expressionStatement(
        t.callExpression(t.identifier('define'), [
          moduleIdentifier,
          mod.ast
        ])
      )
    ])
    const code = generate(ast, { originalText: '', singleQuote: true })
    return outputFile(name, mapping, code.formatted).then(() => {
      progress(i + 1, moduleNames.length)
    })
  })
}

function writeFile (name, content) {
  return mkdirp(path.dirname(name))
    .then(() => fs.writeFile(name, content))
}

function outputFile (name, mapping, code) {
  const file = path.join(program.out, `${name}.js`)
  return writeFile(file, code).then(() => {
    // set up symlinks from nicer paths
    if (mapping[name] && mapping[name].indexOf('plug/') === 0) {
      const niceFile = path.join(program.out, `${mapping[name]}.js`)
      return writeFile(niceFile, code)
    }
  })
}

function progress (task) {
  const title = task.title
  return (current, total) => {
    if (typeof current === 'string') {
      task.title = `${title} ${chalk.gray(current)}`
    } else if (typeof current === 'number' && current < total) {
      const percent = chalk.gray(`${Math.floor((current / total) * 100)}%`)
      task.title = `${title} ${percent}`
    } else {
      task.title = title
    }
  }
}

const renderer = program.verbose
  ? verboseRenderer
  : updateRenderer
const main = new Listr([
  {
    title: 'Logging in to plug.dj',
    task: (ctx) =>
      Promise.resolve(login.guest()).tap((result) => {
        ctx.session = result
      })
  },
  {
    title: 'Generating module name mapping',
    task: (ctx) => createMappingFile(ctx.session.cookie, ctx)
  },
  {
    title: 'Downloading application file',
    task: (ctx, task) => fetchAppFile(ctx.appUrl, progress(task)).then((src) => {
      ctx.src = src
    })
  },
  {
    title: 'Parsing modules',
    task: (ctx, task) => Promise.delay(100).then(() => {
      ctx.modules = parseModules(ctx.src, progress(task))
    }).delay(100)
  },
  {
    title: 'Cleaning modules',
    task: (ctx, task) => cleanModules(ctx.modules, progress(task))
  },
  {
    title: 'Finding correct names for special modules',
    task: (ctx) => Promise.delay(100).then(() => {
      addMappingForUnknownModules(ctx.modules, ctx.mapping)
    }).delay(100)
  },
  {
    title: 'Remapping module names',
    task: (ctx, task) => remapModuleNames(ctx.modules, ctx.mapping, progress(task))
  },
  {
    title: 'Extracting files',
    task: (ctx, task) =>
      extract(ctx.modules, ctx.mapping, progress(task))
        .tap(() => fs.writeFile(path.join(program.out, 'source.js'), ctx.src))
        .tap(() => fs.writeFile(path.join(program.out, 'mapping.json'),
          JSON.stringify(ctx.mapping, null, 2)))
        .then(() => outputFile('version', {}, `window._v = '${_v}';`))
        .then(() => console.log(`v${_v} done`))
  }
], { renderer: renderer })

main.run().catch((e) => {
  setImmediate(() => {
    throw e
  })
})
<commit_msg>fix module string renaming and original name comments<commit_after>#!/usr/bin/env node

const Listr = require('listr')
const updateRenderer = require('listr-update-renderer')
const verboseRenderer = require('listr-verbose-renderer')
const chalk = require('chalk')
const Promise = require('bluebird')
const program = require('commander')
const { parse } = require('babylon')
const { File } = require('babel-core')
const traverse = require('babel-traverse').default
const generate = require('prettier').__debug.formatAST
const t = require('babel-types')
const path = require('path')
const mkdirp = require('mkdirp-then')
const fs = require('mz/fs')
const login = require('plug-login')
const got = require('got')

const pkg = require('../package.json')
const cleanAst = require('./clean-ast')
const createMappingFile = require('./create-mapping')

let _v

program
  .usage('[options]')
  .version(pkg.version)
  .option('-m, --mapping [file]', 'File containing the mapping JSON ' +
            '(optional, it\'s auto-generated if no file is given)')
  .option('-o, --out [dir]', 'Output directory [out/]', 'out/')
  .option('-v, --verbose', 'Use verbose output instead of bullet list', false)
  .parse(process.argv)

function fetchAppFile (url, progress) {
  return new Promise((resolve, reject) => {
    let contents = ''

    const stream = got.stream(url)
    stream.on('response', (res) => {
      const size = parseInt(res.headers['content-length'], 10)
      progress(0, size)
      stream.on('data', (chunk) => {
        contents += chunk.toString('utf8')
        progress(contents.length, size)
      })
    })

    stream.on('error', reject)
    stream.on('end', () => {
      progress(contents.length, contents.length)
      resolve(contents)
    })
  })
}

function variableNameFor (dep, mapping) {
  const libraryNames = {
    jquery: '$',
    backbone: 'Backbone',
    handlebars: 'Handlebars',
    underscore: '_'
  }
  return dep in libraryNames
       ? libraryNames[dep]
       : dep.indexOf('hbs!templates/') === 0
       ? 'template' + dep.split('/').pop()
       : dep in mapping
       ? mapping[dep].split('/').pop().replace(/-/g, '_')
       : dep
}

function sliceTokens (tokens, loc) {
  let start = 0
  while (tokens[start].start < loc.start) {
    start++
  }
  let end = start
  while (tokens[end].end < loc.end) {
    end++
  }
  return tokens.slice(start, end)
}

function parseModules (str, progress) {
  const ast = parse(str)
  const modules = {}
  traverse(ast, {
    CallExpression ({ node }) {
      if (t.isIdentifier(node.callee, { name: 'define' })) {
        let [ name, deps, factory ] = node.arguments
        if (t.isArrayExpression(deps)) {
          deps = deps.elements
        } else {
          factory = deps
          deps = []
        }

        const tokens = sliceTokens(ast.tokens, node)
        const code = str.slice(node.start, node.end)

        const comments = []
        const program = t.file(
          t.program([ t.expressionStatement(factory) ]),
          comments,
          tokens
        )

        const file = new File({
          options: {},
          passes: []
        })
        file.addAst(program)
        progress(name.value)
        modules[name.value] = {
          deps,
          file,
          code,
          ast: factory
        }
      }
    }
  })

  progress(null)
  return modules
}

function findReturnVar (ast) {
  const lastSt = ast.body[ast.body.length - 1]
  if (t.isReturnStatement(lastSt)) {
    const retVal = lastSt.argument
    return t.isNewExpression(retVal)
      ? retVal.callee
      : t.isIdentifier(retVal) && retVal.name !== 'undefined'
      ? retVal
      : null
  }
}

async function cleanModules (modules, progress) {
  const names = Object.keys(modules)
  for (let i = 0; i < names.length; i += 1) {
    const name = names[i]

    cleanAst(modules[name].file.ast)

    await progress(i + 1, names.length)
  }
}

async function remapModuleNames (modules, mapping, progress) {
  const names = Object.keys(modules)

  for (let index = 0; index < names.length; index += 1) {
    const name = names[index]
    const { ast, deps } = modules[name]
    const params = ast.params && ast.params.map((param) => param.name)

    if (!params) {
      await progress(index + 1, names.length)
      continue
    }

    const renames = []
    // build ast of dependency require()s
    const depsAst = deps.map((dep, i) => {
      if (!params[i]) {
        params[i] = '__' + i
      }

      let newName = 'unknown'
      // rename variables according to their module names
      if (mapping[dep.value]) {
        newName = variableNameFor(dep.value, mapping)
        renames.push({ from: params[i], to: newName })
      } else if (/^hbs!templates\//.test(dep.value)) {
        newName = 'template' + dep.value.split('/').pop()
        renames.push({ from: params[i], to: newName })
      }

      if (dep.value in mapping) {
        const originalName = dep.value
        dep.value = mapping[originalName]
        dep.extra.raw = JSON.stringify(dep.value)
        dep.comments = [
          { type: 'Block', value: ` was ${originalName}`, trailing: true }
        ]
      } else {
        dep.comments = [
          { type: 'Block', value: ' Unknown module', trailing: true }
        ]
      }

      return t.variableDeclaration('var', [
        t.variableDeclarator(
          t.identifier(params[i]),
          t.callExpression(t.identifier('require'), [dep])
        )
      ])
    })

    // move dependencies from the define() call
    // to the factory body
    ast.body.body = depsAst.concat(ast.body.body)
    ast.params = [
      t.identifier('require'),
      t.identifier('exports'),
      t.identifier('module')
    ]

    const returnVar = findReturnVar(ast.body)
    if (returnVar) {
      renames.push({
        from: returnVar.name,
        to: variableNameFor(name, mapping)
      })
    }

    processRenames(modules[name].file.ast, renames)

    await progress(index + 1, names.length)
  }
}

function getDependents (modules, name) {
  const isDep = (d) => d.value === name

  return Object.keys(modules).filter((name) =>
    modules[name].deps.some(isDep)
  )
}

function findMemberExpressionName (ast) {
  const body = ast.body
  for (let i = 0, l = body.length; i < l; i++) {
    if (t.isExpressionStatement(body[i]) &&
        t.isAssignmentExpression(body[i].expression) &&
        t.isMemberExpression(body[i].expression.left) &&
        t.isIdentifier(body[i].expression.left.object)) {
      return body[i].expression.left.property
    }
  }
}

function addMappingForUnknownModules (modules, mapping) {
  for (const orig in mapping) {
    if (mapping[orig] === 'plug/server/socketReceiver') {
      // websocket event receiver modules don't export anything,
      // so they cannot be identified individually by plug-modules.
      // however, we have accesss to their full source here, so
      // we can extract them anyway!
      // socket event receivers set properties on a shared object,
      // which will actually be require()d by plug.dj source code,
      // and which can also be identified by plug-modules. here, we
      // can find all modules that depend on socketReceiver, and find
      // the relevant assignments.
      getDependents(modules, orig).forEach((name) => {
        const prop = findMemberExpressionName(modules[name].ast.body)
        if (prop) {
          // some of these modules have multiple event receivers, so we
          // rename them to be a bit more clear.
          const niceName = {
            // contains a bunch of booth/wait list moderation events
            modAddDJ: 'plug/server/socket/modBooth',
            // contains subscription, XP, and PP events
            earn: 'plug/server/socket/currency',
            // contains multiple events for updates to the current room
            roomNameUpdate: 'plug/server/socket/roomUpdate',
            // this is actually the websocket manager module,
            // and it sets the window._gws property to undefined.
            // it really is just a false positive but we can abuse
            // it to get the proper module, anyway.
            // TODO detect this in a less stupid way
            _gws: 'plug/server/socket'
          }[prop.name] || 'plug/server/socket/' + prop.name
          mapping[name] = niceName
        }
      })
    } else if (mapping[orig] === 'plug/util/API') {
      getDependents(modules, orig).forEach((name) => {
        const prop = findMemberExpressionName(modules[name].ast.body)
        if (prop) {
          const niceName = {
            getAdmins: 'admins',
            getAmbassadors: 'ambassadors',
            getAudience: 'audience',
            getBannedUsers: 'bannedUsers',
            getDJ: 'dj',
            getHistory: 'history',
            getHost: 'host',
            getMedia: 'media',
            getNextMedia: 'nextMedia',
            getScore: 'score',
            getStaff: 'staff',
            getTimeElapsed: 'playTime',
            getUser: 'users',
            getWaitList: 'waitlist',
            moderateForceSkip: 'moderator',
            sendChat: 'chat',
            setVolume: 'volume'
          }[prop.name] || prop.name
          mapping[name] = 'plug/util/api/' + niceName
        }
      })
    }
  }
}

function processRenames (ast, renames) {
  traverse(ast, {
    FunctionExpression (path) {
      renames.forEach(({ from, to }) => {
        if (path.scope.hasBinding(to)) {
          path.scope.rename(to, path.scope.generateUid(to))
        }
        path.scope.rename(from, to)
      })
      path.stop()
    }
  })
  return ast
}

function extract (modules, mapping, progress) {
  const moduleNames = Object.keys(modules)
  return Promise.each(moduleNames, (name, i) => {
    const mod = modules[name]

    const moduleIdentifier = t.stringLiteral(name)
    if (name in mapping) {
      moduleIdentifier.raw = JSON.stringify(mapping[name])
      moduleIdentifier.value = mapping[name]
      moduleIdentifier.comments = [
        { type: 'Block', value: ` was ${name}`, trailing: true }
      ]
    } else {
      moduleIdentifier.raw = JSON.stringify(name)
      moduleIdentifier.comments = [
        { type: 'Block', value: ' Unknown module', trailing: true }
      ]
    }

    const ast = t.program([
      t.expressionStatement(
        t.callExpression(t.identifier('define'), [
          moduleIdentifier,
          mod.ast
        ])
      )
    ])
    const code = generate(ast, { originalText: '', singleQuote: true })
    return outputFile(name, mapping, code.formatted).then(() => {
      progress(i + 1, moduleNames.length)
    })
  })
}

function writeFile (name, content) {
  return mkdirp(path.dirname(name))
    .then(() => fs.writeFile(name, content))
}

function outputFile (name, mapping, code) {
  const file = path.join(program.out, `${name}.js`)
  return writeFile(file, code).then(() => {
    // set up symlinks from nicer paths
    if (mapping[name] && mapping[name].indexOf('plug/') === 0) {
      const niceFile = path.join(program.out, `${mapping[name]}.js`)
      return writeFile(niceFile, code)
    }
  })
}

function progress (task) {
  const title = task.title
  return (current, total) => {
    if (typeof current === 'string') {
      task.title = `${title} ${chalk.gray(current)}`
    } else if (typeof current === 'number' && current < total) {
      const percent = chalk.gray(`${Math.floor((current / total) * 100)}%`)
      task.title = `${title} ${percent}`
    } else {
      task.title = title
    }
  }
}

const renderer = program.verbose
  ? verboseRenderer
  : updateRenderer
const main = new Listr([
  {
    title: 'Logging in to plug.dj',
    task: (ctx) =>
      Promise.resolve(login.guest()).tap((result) => {
        ctx.session = result
      })
  },
  {
    title: 'Generating module name mapping',
    task: (ctx) => createMappingFile(ctx.session.cookie, ctx)
  },
  {
    title: 'Downloading application file',
    task: (ctx, task) => fetchAppFile(ctx.appUrl, progress(task)).then((src) => {
      ctx.src = src
    })
  },
  {
    title: 'Parsing modules',
    task: (ctx, task) => Promise.delay(100).then(() => {
      ctx.modules = parseModules(ctx.src, progress(task))
    }).delay(100)
  },
  {
    title: 'Cleaning modules',
    task: (ctx, task) => cleanModules(ctx.modules, progress(task))
  },
  {
    title: 'Finding correct names for special modules',
    task: (ctx) => Promise.delay(100).then(() => {
      addMappingForUnknownModules(ctx.modules, ctx.mapping)
    }).delay(100)
  },
  {
    title: 'Remapping module names',
    task: (ctx, task) => remapModuleNames(ctx.modules, ctx.mapping, progress(task))
  },
  {
    title: 'Extracting files',
    task: (ctx, task) =>
      extract(ctx.modules, ctx.mapping, progress(task))
        .tap(() => fs.writeFile(path.join(program.out, 'source.js'), ctx.src))
        .tap(() => fs.writeFile(path.join(program.out, 'mapping.json'),
          JSON.stringify(ctx.mapping, null, 2)))
        .then(() => outputFile('version', {}, `window._v = '${_v}';`))
        .then(() => console.log(`v${_v} done`))
  }
], { renderer: renderer })

main.run().catch((e) => {
  setImmediate(() => {
    throw e
  })
})
<|endoftext|>


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

    "use strict";

    // this saves us having to load each plugin individually
    require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);

    grunt.initConfig({

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

        less: {
            development: {
                options: {
                    compress: true,
                    strictMath: true,
                    strictUnits: true,
                    cleancss: true
                },
                files: {
                    "style.css": "styles/style.less"
                }
            }
        },

        autoprefixer: {
            single_file: {
                options: {
                    browsers: ["last 2 version"]
                },
                src: "style.css",
                dest: "style.css"
            },
        },

        csslint: {
            options: {
                csslintrc: ".csslintrc"
            },
            strict: {
                src: ["style.css"]
            }
        },

        cssmin: {
            minify: {
                src: "style.css",
                dest: "style.css"
            }
        },

        jshint: {
            options: {
                curly: true,
                eqeqeq: true,
                strict: true,
                evil: true,
                indent: 4,
                undef: true,
                white: true,
                browser: true,
                quotmark: "double",
                trailing: true,
                globals: {
                    jQuery: true,
                    console: true,
                    module: true,
                    require: true
                },
            },
            all: [
                ".jshintrc",
                "Gruntfile.js",
                "js/project.js"
            ]
        },

        concat: {
            dist: {
                src: [
                    "components/jquery/jquery.js",
                    "components/modernizr/modernizr.js",
                    "js/project.js"
                ],
                dest: "js/production.js"
            }
        },

        uglify: {
            my_target: {
                files: {
                    "js/production.js": ["js/production.js"]
                }
            }
        }
    });

    // List of available tasks
    grunt.registerTask("default", []);
    grunt.registerTask("buildcss", ["less", "autoprefixer", "csslint", "cssmin"]);
    grunt.registerTask("buildjs", ["jshint", "concat", "uglify"]);

};
<commit_msg>create watch tasks for less and js<commit_after>module.exports = function (grunt) {

    "use strict";

    // this saves us having to load each plugin individually
    require("matchdep").filterDev("grunt-*").forEach(grunt.loadNpmTasks);

    grunt.initConfig({

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

        less: {
            development: {
                options: {
                    compress: true,
                    strictMath: true,
                    strictUnits: true,
                    cleancss: true
                },
                files: {
                    "style.css": "styles/style.less"
                }
            }
        },

        autoprefixer: {
            single_file: {
                options: {
                    browsers: ["last 2 version"]
                },
                src: "style.css",
                dest: "style.css"
            },
        },

        csslint: {
            options: {
                csslintrc: ".csslintrc"
            },
            strict: {
                src: ["style.css"]
            }
        },

        cssmin: {
            minify: {
                src: "style.css",
                dest: "style.css"
            }
        },

        jshint: {
            options: {
                curly: true,
                eqeqeq: true,
                strict: true,
                evil: true,
                indent: 4,
                undef: true,
                white: true,
                browser: true,
                quotmark: "double",
                trailing: true,
                globals: {
                    jQuery: true,
                    console: true,
                    module: true,
                    require: true
                },
            },
            all: [
                ".jshintrc",
                "Gruntfile.js",
                "js/project.js"
            ]
        },

        concat: {
            dist: {
                src: [
                    "components/jquery/jquery.js",
                    "components/modernizr/modernizr.js",
                    "js/project.js"
                ],
                dest: "js/production.js"
            }
        },

        uglify: {
            my_target: {
                files: {
                    "js/production.js": ["js/production.js"]
                }
            }
        },

        watch: {
            css: {
                files: "styles/*.less",
                tasks: "buildcss"
            },
            scripts: {
                files: "js/project.js",
                tasks: "buildjs"
            }
        }
    });

    // List of available tasks
    grunt.registerTask("default", []);
    grunt.registerTask("buildcss", ["less", "autoprefixer", "csslint", "cssmin"]);
    grunt.registerTask("buildjs", ["jshint", "concat", "uglify"]);

};
<|endoftext|>


<commit_before>import commander from 'commander';
import containerInit from './init';
import fs from 'fs';
import path from 'path';

commander
  .command('serve')
  .alias('s')
  .description('serve ap-npm')
  .option('--config', "config file to use")
  .action(function(config) {
    let container;
    if (fs.existsSync(config)) {
      console.log("using config: " + config + '\n');
      container = containerInit(config);
    }
    else if (typeof config === 'string') {
      if (fs.existsSync(path.join(__dirname, '../', config))) {
        let configLocation = path.join(__dirname, '../', config);
        console.log("using config: " + configLocation + '\n');
        container = containerInit(configLocation);
      }
    }
    else {
      console.log("using default config\n");
      container = containerInit("../config.json");
    }

    let command = container.get('command-serve');
    command.run();
  });

commander.parse(process.argv);

if (!process.argv.slice(2).length) {
  commander.outputHelp();
}<commit_msg>Add set and init command to ap-npm<commit_after>import commander from 'commander';
import containerInit from './init';
import fs from 'fs';
import path from 'path';

commander
  .command('serve')
  .alias('s')
  .description('serve ap-npm')
  .option('-c, --config', "config file to use")
  .action(function(config) {
    let container;

    if (fs.existsSync(config)) {
      console.log("using config: " + config + '\n');
      container = containerInit(config);
    } else {
      console.log("using default config\n");
      let configLocation = path.join(__dirname, '../', 'config.json');
      container = containerInit(configLocation);
    }

    let command = container.get('command-serve');
    command.run();
  });

commander
  .command('set <prop> <value>')
  .description('sets default config property')
  .action(function(property, value) {
    let container = containerInit(path.join(__dirname, '../', 'config.json'));
    let command = container.get('command-set');
    command.run(property, value);
  });

commander
  .command('init')
  .description('init a npm project using ap-npm config')
  .action(function() {
    let container = containerInit(path.join(__dirname, '../', 'config.json'));
    let command = container.get('command-init');
    command.run(process.cwd());
  });

commander.parse(process.argv);

if (!process.argv.slice(2).length) {
  commander.outputHelp();
}<|endoftext|>


<commit_before>/*global module:false*/

module.exports = function(grunt) {
  grunt.initConfig({
    jshint: {
      src: [
        'Gruntfile.js',
        'lib/**/*.js',
        'bin/fakeminder',
        'test/**/*.js',
        'sample_target/app.js',
        'sample_target/routes/*.js'
      ],
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        node: true,
        globals: {
          require: true,
          define: true,
          requirejs: true,
          describe: true,
          expect: true,
          it: true,
          beforeEach: true,
          afterEach: true
        }
      }
    },
    simplemocha: {
      all: {
        src: ['test/**/*.js'],
        options: {
          globals: ['expect'],
          timeout: 2000,
          ignoreLeaks: false,
          reporter: 'dot'
        }
      }
    },
    watch: {
      files: ['<%= jshint.src %>'],
      tasks: ['jshint', 'simplemocha']
    },
    casperjs: {
      options: {},
      files: {src: ['sample_target/test/**/*.js']}
    },
    express: {
      options: {
        output: "Express server listening on port .+"
      },
      sample_target: {
        options: {
          script: 'sample_target/app.js'
        }
      }
    },
    gitpush: {
      github: {
        options: {
          remote: 'github',
          branch: 'master'
        }
      }
    },
    coverage: {
      options: {
        thresholds: {
          statements: 90,
          branches: 90,
          lines: 90,
          functions: 90
        },
        dir: 'coverage'
      }
    },
    clean: ['coverage'],
    open: {
      cover: {
        path: 'coverage/lcov-report/index.html',
        app: 'Google Chrome'
      }
    }
  });

  // Load JSHint task
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-simple-mocha');
  grunt.loadNpmTasks('grunt-casperjs');
  grunt.loadNpmTasks('grunt-express-server');
  grunt.loadNpmTasks('grunt-clear');
  grunt.loadNpmTasks('grunt-git');
  grunt.loadNpmTasks('grunt-istanbul-coverage');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-open');

  // Default task.
  grunt.registerTask('default', ['clear', 'jshint', 'simplemocha']);
  grunt.registerTask('test', ['clear', 'simplemocha']);
  grunt.registerTask('int-test', 'Execute integration tests against the sample app through the proxy', function() {
    // Make sure failed automation tests don't break the entire task
    // so we can shutdown both the FakeMinder and Express apps.
    grunt.option('force', true);
    grunt.task.run('clear');
    grunt.task.run('fakeminder-start');
    grunt.task.run('express:sample_target');
    grunt.task.run('casperjs');
    grunt.task.run('express:sample_target:stop');
    grunt.task.run('fakeminder-stop');
  });
  grunt.registerTask('cover', ['clear', 'clean', 'istanbul', 'open:cover']);
  grunt.registerTask('cover-check', ['clear', 'clean', 'istanbul', 'coverage']);

  var server;
  var regex = new RegExp(/FakeMinder listening on port/);

  // Run the FakeMinder server
  grunt.registerTask('fakeminder-start', 'Start an instance of FakeMinder using the default config.', function() {
    var done = this.async();

    server = grunt.util.spawn({
      cmd: './bin/fakeminder',
      args: ['start', 'config.json']
    }, done);

    server.stderr.on('data', function(data) {
      var message = '' + data;
      if (message.match(regex)) {
        done();
      }
    });

    server.stdout.pipe(process.stdout);
    server.stderr.pipe(process.stderr);
  });

  // End the FakeMinder server
  grunt.registerTask('fakeminder-stop', 'Stop the running instance of FakeMinder.', function() {
    if (server && server.kill) {
      server.kill('SIGTERM');
      server = null;
    }
  });

  // Commit changes to Github.
  grunt.registerTask('commit', 'Commit changes to Github', function(env) {
    grunt.task.run('clear');
    grunt.task.run('default');
    grunt.task.run('int-test');
    grunt.task.run('gitpush:github');

    grunt.log.ok('Changes successfully committed to Github.');
  });

  // Run mocha tests while also generating code coverage using istanbul
  grunt.registerTask('istanbul', 'Generate coverage using istanbul from mocha tests', function() {
    var done = this.async();

    server = grunt.util.spawn({
      cmd: './node_modules/.bin/istanbul',
      args: ['cover', '_mocha', '--']
    }, done);

    server.stdout.pipe(process.stdout);
    server.stderr.pipe(process.stderr);
  });
};
<commit_msg>Fix bad regex for detecting whether FakeMinder is running<commit_after>/*global module:false*/

module.exports = function(grunt) {
  grunt.initConfig({
    jshint: {
      src: [
        'Gruntfile.js',
        'lib/**/*.js',
        'bin/fakeminder',
        'test/**/*.js',
        'sample_target/app.js',
        'sample_target/routes/*.js'
      ],
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        node: true,
        globals: {
          require: true,
          define: true,
          requirejs: true,
          describe: true,
          expect: true,
          it: true,
          beforeEach: true,
          afterEach: true
        }
      }
    },
    simplemocha: {
      all: {
        src: ['test/**/*.js'],
        options: {
          globals: ['expect'],
          timeout: 2000,
          ignoreLeaks: false,
          reporter: 'dot'
        }
      }
    },
    watch: {
      files: ['<%= jshint.src %>'],
      tasks: ['jshint', 'simplemocha']
    },
    casperjs: {
      options: {},
      files: {src: ['sample_target/test/**/*.js']}
    },
    express: {
      options: {
        output: "Express server listening on port .+"
      },
      sample_target: {
        options: {
          script: 'sample_target/app.js'
        }
      }
    },
    gitpush: {
      github: {
        options: {
          remote: 'github',
          branch: 'master'
        }
      }
    },
    coverage: {
      options: {
        thresholds: {
          statements: 90,
          branches: 90,
          lines: 90,
          functions: 90
        },
        dir: 'coverage'
      }
    },
    clean: ['coverage'],
    open: {
      cover: {
        path: 'coverage/lcov-report/index.html',
        app: 'Google Chrome'
      }
    }
  });

  // Load JSHint task
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-simple-mocha');
  grunt.loadNpmTasks('grunt-casperjs');
  grunt.loadNpmTasks('grunt-express-server');
  grunt.loadNpmTasks('grunt-clear');
  grunt.loadNpmTasks('grunt-git');
  grunt.loadNpmTasks('grunt-istanbul-coverage');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-open');

  // Default task.
  grunt.registerTask('default', ['clear', 'jshint', 'simplemocha']);
  grunt.registerTask('test', ['clear', 'simplemocha']);
  grunt.registerTask('int-test', 'Execute integration tests against the sample app through the proxy', function() {
    // Make sure failed automation tests don't break the entire task
    // so we can shutdown both the FakeMinder and Express apps.
    grunt.option('force', true);
    grunt.task.run('clear');
    grunt.task.run('fakeminder-start');
    grunt.task.run('express:sample_target');
    grunt.task.run('casperjs');
    grunt.task.run('express:sample_target:stop');
    grunt.task.run('fakeminder-stop');
  });
  grunt.registerTask('cover', ['clear', 'clean', 'istanbul', 'open:cover']);
  grunt.registerTask('cover-check', ['clear', 'clean', 'istanbul', 'coverage']);

  var server;
  var regex = new RegExp(/Listening on port/);

  // Run the FakeMinder server
  grunt.registerTask('fakeminder-start', 'Start an instance of FakeMinder using the default config.', function() {
    var done = this.async();

    server = grunt.util.spawn({
      cmd: './bin/fakeminder',
      args: ['start', 'config.json']
    }, done);

    server.stderr.on('data', function(data) {
      var message = '' + data;
      if (message.match(regex)) {
        done();
      }
    });

    server.stdout.pipe(process.stdout);
    server.stderr.pipe(process.stderr);
  });

  // End the FakeMinder server
  grunt.registerTask('fakeminder-stop', 'Stop the running instance of FakeMinder.', function() {
    if (server && server.kill) {
      server.kill('SIGTERM');
      server = null;
    }
  });

  // Commit changes to Github.
  grunt.registerTask('commit', 'Commit changes to Github', function(env) {
    grunt.task.run('clear');
    grunt.task.run('default');
    grunt.task.run('int-test');
    grunt.task.run('gitpush:github');

    grunt.log.ok('Changes successfully committed to Github.');
  });

  // Run mocha tests while also generating code coverage using istanbul
  grunt.registerTask('istanbul', 'Generate coverage using istanbul from mocha tests', function() {
    var done = this.async();

    server = grunt.util.spawn({
      cmd: './node_modules/.bin/istanbul',
      args: ['cover', '_mocha', '--']
    }, done);

    server.stdout.pipe(process.stdout);
    server.stderr.pipe(process.stderr);
  });
};
<|endoftext|>


<commit_before>"use strict";

var airlineScrapers = require("./index.js");

/**
 * airline destinations
 */

var getAllDestinations = airlineScrapers.getAllDestinations;
var getScraperTypeForAll = airlineScrapers.getScraperTypeForAll;
var getAllRoutes = airlineScrapers.getAllRoutes;

var options = {
  "urls": "https://en.wikipedia.org/w/index.php?title=Category:Lists_of_airline_destinations",
  "destinationsFile": "./data/destination_pages.json"
};

getAllDestinations(options, function (err, airlines) {
  if (err) {throw err;}

  console.log("Destinations File Created"); // eslint-disable-line no-console

  getScraperTypeForAll({"airlines": airlines}, function (err, airlineScrapers) {
    if (err) {throw err;}

    console.log("scrapers finished");// eslint-disable-line no-console

    getAllRoutes(airlineScrapers, function (err, airlines) {
      if (err) {throw err;}
      console.log("Routes Files Generated");// eslint-disable-line no-console
      writeJson(airlines);
    });

  });
});

var fs = require("fs");

var writeJson = function (airlines) {
  var fileName = "airlines_destinations.json";

  fs.writeFile(fileName,
    JSON.stringify(airlines, null, 2),
    function (err) {
      if (err) {
        throw err;
      }
      console.log("saved airlines file");
    }
  );
};

<commit_msg>saving final file to data folder<commit_after>"use strict";

var airlineScrapers = require("./index.js");

/**
 * airline destinations
 */

var getAllDestinations = airlineScrapers.getAllDestinations;
var getScraperTypeForAll = airlineScrapers.getScraperTypeForAll;
var getAllRoutes = airlineScrapers.getAllRoutes;

var options = {
  "urls": "https://en.wikipedia.org/w/index.php?title=Category:Lists_of_airline_destinations",
  "destinationsFile": "./data/destination_pages.json"
};

getAllDestinations(options, function (err, airlines) {
  if (err) {throw err;}

  console.log("Destinations File Created"); // eslint-disable-line no-console

  getScraperTypeForAll({"airlines": airlines}, function (err, airlineScrapers) {
    if (err) {throw err;}

    console.log("scrapers finished");// eslint-disable-line no-console

    getAllRoutes(airlineScrapers, function (err, airlines) {
      if (err) {throw err;}
      console.log("Routes Files Generated");// eslint-disable-line no-console
      writeJson(airlines);
    });

  });
});

var fs = require("fs");

var writeJson = function (airlines) {
  var fileName = "data/airlines_destinations.json";

  fs.writeFile(fileName,
    JSON.stringify(airlines, null, 2),
    function (err) {
      if (err) {
        throw err;
      }
      console.log("saved airlines file");
    }
  );
};

<|endoftext|>


<commit_before>/* jshint camelcase: false */
module.exports = function (grunt) {
  'use strict';

  grunt.initConfig({

    // load module meta data
    pkg: grunt.file.readJSON('package.json'),

    // define a src set of files for other tasks
    src: {
      lint: ['Gruntfile.js', 'index.js', 'lib/**/*.js', 'test/*.js'],
      complexity: ['index.js', 'lib/**/*.js', 'test/*.js'],
      test: ['test/*.js'],
      src: ['index.js', 'lib/**/*.js']
    },

    // clean automatically generated helper files & docs
    clean: {
      coverage: ['coverage', 'report/coverage'],
      report: ['report/complexity', 'report/api', 'report/docs'],
      reportZip: ['report.zip']
    },

    // linting
    jshint: {
      options: {
        jshintrc: '.jshintrc'
      },
      all: '<%= src.lint %>'
    },

    // testing
    mochaTest: {
      test: {
        options: {
          reporter: 'spec',
          require: 'coverage/blanket'
        },
        src: '<%= src.test %>'
      },
      coverage: {
        options: {
          reporter: 'html-cov',
          quiet: true,
          captureFile: 'report/coverage/index.html'
        },
        src: '<%= src.test %>'
      },
      jsoncoverage: {
        options: {
          reporter: 'json-cov',
          quiet: true,
          captureFile: 'report/coverage/coverage.json'
        },
        src: '<%= src.test %>'
      }
    },

    // code metrics
    complexity: {
      generic: {
        src: '<%= src.complexity %>',
        options: {
          cyclomatic: 4,
          halstead: 20,
          maintainability: 100
        }
      }
    },
    plato: {
      generic: {
        options : {
          jshint : grunt.file.readJSON('.jshintrc')
        },
        files: {
          'report/complexity': '<%= src.complexity %>',
        }
      }
    },

    // api docs
    yuidoc: {
      compile: {
        name: '<%= pkg.name %>',
        description: '<%= pkg.description %>',
        version: '<%= pkg.version %>',
        url: '<%= pkg.homepage %>',
        options: {
          paths: '.',
          outdir: 'report/api'
        }
      }
    },

    // user docs
    documantix: {
      options: {
        header: 'dalekjs/dalekjs.com/master/assets/header.html',
        footer: 'dalekjs/dalekjs.com/master/assets/footer.html',
        target: 'report/docs'
      },
      src: ['index.js']
    },

    // add current timestamp to the html document
    includereplace: {
      dist: {
        options: {
          globals: {
            timestamp: '<%= grunt.template.today("dddd, mmmm dS, yyyy, h:MM:ss TT") %>'
          },
        },
        src: 'report/docs/*.html',
        dest: '.'
      }
    },

    // compress artifacts
    compress: {
      main: {
        options: {
          archive: 'report.zip'
        },
        files: [
          {src: ['report/**'], dest: '/'}
        ]
      }
    }

  });

  // prepare files & folders for grunt:plato
  grunt.registerTask('preparePlato', function () {
    var fs = require('fs');

    var platoDummyFolders = [
      'report', 'report/complexity',
      'report/complexity/files', 'report/complexity/files/test',
      'report/complexity/files/index_js',
      'report/complexity/files/lib_commands_cookie_js',
      'report/complexity/files/lib_commands_element_js',
      'report/complexity/files/lib_commands_frame_js',
      'report/complexity/files/lib_commands_page_js',
      'report/complexity/files/lib_commands_screenshot_js',
      'report/complexity/files/lib_commands_window_js',
      'report/complexity/files/lib_commands_url_js'
    ];
    var platoDummyFiles = ['/report/complexity/report.history.json', '/report/complexity/files/report.history.json',
      '/report/complexity/files/index_js/report.history.json',
      '/report/complexity/files/lib_commands_cookie_js/report.history.json',
      '/report/complexity/files/lib_commands_element_js/report.history.json',
      '/report/complexity/files/lib_commands_frame_js/report.history.json',
      '/report/complexity/files/lib_commands_page_js/report.history.json',
      '/report/complexity/files/lib_commands_screenshot_js/report.history.json',
      '/report/complexity/files/lib_commands_url_js/report.history.json',
      '/report/complexity/files/lib_commands_window_js/report.history.json'
    ];

    // generate dirs for docs & reports
    platoDummyFolders.forEach(function (path) {
      if (!fs.existsSync(__dirname + '/' + path)) {
        fs.mkdirSync(__dirname + '/' + path);
      }
    });

    // store some dummy reports, so that grunt plato doesnt complain
    platoDummyFiles.forEach(function (file) {
      if (!fs.existsSync(__dirname + file)) {
        fs.writeFileSync(__dirname + file, '{}');
      }
    });
  });

  // prepare files & folders for coverage
  grunt.registerTask('prepareCoverage', function () {
    var fs = require('fs');

    // generate folders
    ['coverage', 'report', 'report/coverage'].forEach(function (folder) {
      if (!fs.existsSync(__dirname + '/' + folder)) {
        fs.mkdirSync(__dirname + '/' + folder);
      }
    });

    // generate code coverage helper file
    var coverageHelper = 'require("blanket")({pattern: [require("fs").realpathSync(__dirname + "/../index.js"), require("fs").realpathSync(__dirname + "/../lib/")]});';
    if (!fs.existsSync(__dirname + '/coverage/blanket.js')) {
      fs.writeFileSync(__dirname + '/coverage/blanket.js', coverageHelper);
    }
  });

  // generates a coverage badge
  grunt.registerTask('generateCoverageBadge', function () {
    var fs = require('fs');
    if (fs.existsSync(__dirname + '/node_modules/coverage-badge')) {
      if (fs.existsSync(__dirname + '/report/coverage/coverage.json')) {
        var green = [147,188,59];
        var yellow = [166,157,0];
        var red = [189,0,2];

        var getColor = function (coverage) {
          if (coverage > 90) {
            return mixColors(yellow, green, (coverage-90)/10);
          }

          if (coverage > 80) {
            return mixColors(red, yellow, (coverage-80)/10);
          }

          return createColor(red);
        };

        var mixColors = function (from, to, ratio) {
          var result = [], i;
          for (i=0; i<3; i++) {
            result[i] = Math.round(from[i] + (ratio * (to[i]-from[i])));
          }
          return createColor(result);
        };

        var createColor = function (values) {
          return 'rgba('+values[0]+','+values[1]+','+values[2]+',1)';
        };

        var Badge = require(__dirname + '/node_modules/coverage-badge/lib/Badge.js');
        var badgeFn = function(coverage) {
          coverage = Math.floor(Number(coverage));
          var badge = new Badge({
            box_color: getColor(coverage),
            box_text: coverage+'%',
            label_text: 'cov',
            height: 18,
            width: 49,
            box_width: 25,
            rounding: 0,
            padding: 0,
            label_font: '7pt DejaVu Sans',
            box_font: 'bold 7pt DejaVu Sans'
          });
          return badge.stream();
        };

        var coverage = JSON.parse(fs.readFileSync(__dirname + '/report/coverage/coverage.json')).coverage;
        var file = fs.createWriteStream(__dirname + '/report/coverage/coverage.png');
        badgeFn(coverage).pipe(file);
      }
    }
  });

  // load 3rd party tasks
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-yuidoc');
  grunt.loadNpmTasks('grunt-contrib-compress');
  grunt.loadNpmTasks('grunt-mocha-test');
  grunt.loadNpmTasks('grunt-complexity');
  grunt.loadNpmTasks('grunt-documantix');
  grunt.loadNpmTasks('grunt-plato');
  grunt.loadNpmTasks('grunt-include-replace');

  // define runner tasks
  grunt.registerTask('lint', 'jshint');
  grunt.registerTask('test', ['clean:coverage', 'prepareCoverage', 'lint', 'mochaTest', 'generateCoverageBadge', 'complexity']);
  grunt.registerTask('docs', ['clean:reportZip', 'clean:report', 'preparePlato', 'plato', 'documantix', 'includereplace', 'yuidoc', 'compress']);
  grunt.registerTask('all', ['clean', 'test', 'docs']);

};
<commit_msg>Removed complexity measurement of test<commit_after>/* jshint camelcase: false */
module.exports = function (grunt) {
  'use strict';

  grunt.initConfig({

    // load module meta data
    pkg: grunt.file.readJSON('package.json'),

    // define a src set of files for other tasks
    src: {
      lint: ['Gruntfile.js', 'index.js', 'lib/**/*.js', 'test/*.js'],
      complexity: ['index.js', 'lib/**/*.js'],
      test: ['test/*.js'],
      src: ['index.js', 'lib/**/*.js']
    },

    // clean automatically generated helper files & docs
    clean: {
      coverage: ['coverage', 'report/coverage'],
      report: ['report/complexity', 'report/api', 'report/docs'],
      reportZip: ['report.zip']
    },

    // linting
    jshint: {
      options: {
        jshintrc: '.jshintrc'
      },
      all: '<%= src.lint %>'
    },

    // testing
    mochaTest: {
      test: {
        options: {
          reporter: 'spec',
          require: 'coverage/blanket'
        },
        src: '<%= src.test %>'
      },
      coverage: {
        options: {
          reporter: 'html-cov',
          quiet: true,
          captureFile: 'report/coverage/index.html'
        },
        src: '<%= src.test %>'
      },
      jsoncoverage: {
        options: {
          reporter: 'json-cov',
          quiet: true,
          captureFile: 'report/coverage/coverage.json'
        },
        src: '<%= src.test %>'
      }
    },

    // code metrics
    complexity: {
      generic: {
        src: '<%= src.complexity %>',
        options: {
          cyclomatic: 4,
          halstead: 20,
          maintainability: 100
        }
      }
    },
    plato: {
      generic: {
        options : {
          jshint : grunt.file.readJSON('.jshintrc')
        },
        files: {
          'report/complexity': '<%= src.complexity %>',
        }
      }
    },

    // api docs
    yuidoc: {
      compile: {
        name: '<%= pkg.name %>',
        description: '<%= pkg.description %>',
        version: '<%= pkg.version %>',
        url: '<%= pkg.homepage %>',
        options: {
          paths: '.',
          outdir: 'report/api'
        }
      }
    },

    // user docs
    documantix: {
      options: {
        header: 'dalekjs/dalekjs.com/master/assets/header.html',
        footer: 'dalekjs/dalekjs.com/master/assets/footer.html',
        target: 'report/docs'
      },
      src: ['index.js']
    },

    // add current timestamp to the html document
    includereplace: {
      dist: {
        options: {
          globals: {
            timestamp: '<%= grunt.template.today("dddd, mmmm dS, yyyy, h:MM:ss TT") %>'
          },
        },
        src: 'report/docs/*.html',
        dest: '.'
      }
    },

    // compress artifacts
    compress: {
      main: {
        options: {
          archive: 'report.zip'
        },
        files: [
          {src: ['report/**'], dest: '/'}
        ]
      }
    }

  });

  // prepare files & folders for grunt:plato
  grunt.registerTask('preparePlato', function () {
    var fs = require('fs');

    var platoDummyFolders = [
      'report', 'report/complexity',
      'report/complexity/files', 'report/complexity/files/test',
      'report/complexity/files/index_js',
      'report/complexity/files/lib_commands_cookie_js',
      'report/complexity/files/lib_commands_element_js',
      'report/complexity/files/lib_commands_frame_js',
      'report/complexity/files/lib_commands_page_js',
      'report/complexity/files/lib_commands_screenshot_js',
      'report/complexity/files/lib_commands_window_js',
      'report/complexity/files/lib_commands_url_js'
    ];
    var platoDummyFiles = ['/report/complexity/report.history.json', '/report/complexity/files/report.history.json',
      '/report/complexity/files/index_js/report.history.json',
      '/report/complexity/files/lib_commands_cookie_js/report.history.json',
      '/report/complexity/files/lib_commands_element_js/report.history.json',
      '/report/complexity/files/lib_commands_frame_js/report.history.json',
      '/report/complexity/files/lib_commands_page_js/report.history.json',
      '/report/complexity/files/lib_commands_screenshot_js/report.history.json',
      '/report/complexity/files/lib_commands_url_js/report.history.json',
      '/report/complexity/files/lib_commands_window_js/report.history.json'
    ];

    // generate dirs for docs & reports
    platoDummyFolders.forEach(function (path) {
      if (!fs.existsSync(__dirname + '/' + path)) {
        fs.mkdirSync(__dirname + '/' + path);
      }
    });

    // store some dummy reports, so that grunt plato doesnt complain
    platoDummyFiles.forEach(function (file) {
      if (!fs.existsSync(__dirname + file)) {
        fs.writeFileSync(__dirname + file, '{}');
      }
    });
  });

  // prepare files & folders for coverage
  grunt.registerTask('prepareCoverage', function () {
    var fs = require('fs');

    // generate folders
    ['coverage', 'report', 'report/coverage'].forEach(function (folder) {
      if (!fs.existsSync(__dirname + '/' + folder)) {
        fs.mkdirSync(__dirname + '/' + folder);
      }
    });

    // generate code coverage helper file
    var coverageHelper = 'require("blanket")({pattern: [require("fs").realpathSync(__dirname + "/../index.js"), require("fs").realpathSync(__dirname + "/../lib/")]});';
    if (!fs.existsSync(__dirname + '/coverage/blanket.js')) {
      fs.writeFileSync(__dirname + '/coverage/blanket.js', coverageHelper);
    }
  });

  // generates a coverage badge
  grunt.registerTask('generateCoverageBadge', function () {
    var fs = require('fs');
    if (fs.existsSync(__dirname + '/node_modules/coverage-badge')) {
      if (fs.existsSync(__dirname + '/report/coverage/coverage.json')) {
        var green = [147,188,59];
        var yellow = [166,157,0];
        var red = [189,0,2];

        var getColor = function (coverage) {
          if (coverage > 90) {
            return mixColors(yellow, green, (coverage-90)/10);
          }

          if (coverage > 80) {
            return mixColors(red, yellow, (coverage-80)/10);
          }

          return createColor(red);
        };

        var mixColors = function (from, to, ratio) {
          var result = [], i;
          for (i=0; i<3; i++) {
            result[i] = Math.round(from[i] + (ratio * (to[i]-from[i])));
          }
          return createColor(result);
        };

        var createColor = function (values) {
          return 'rgba('+values[0]+','+values[1]+','+values[2]+',1)';
        };

        var Badge = require(__dirname + '/node_modules/coverage-badge/lib/Badge.js');
        var badgeFn = function(coverage) {
          coverage = Math.floor(Number(coverage));
          var badge = new Badge({
            box_color: getColor(coverage),
            box_text: coverage+'%',
            label_text: 'cov',
            height: 18,
            width: 49,
            box_width: 25,
            rounding: 0,
            padding: 0,
            label_font: '7pt DejaVu Sans',
            box_font: 'bold 7pt DejaVu Sans'
          });
          return badge.stream();
        };

        var coverage = JSON.parse(fs.readFileSync(__dirname + '/report/coverage/coverage.json')).coverage;
        var file = fs.createWriteStream(__dirname + '/report/coverage/coverage.png');
        badgeFn(coverage).pipe(file);
      }
    }
  });

  // load 3rd party tasks
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-yuidoc');
  grunt.loadNpmTasks('grunt-contrib-compress');
  grunt.loadNpmTasks('grunt-mocha-test');
  grunt.loadNpmTasks('grunt-complexity');
  grunt.loadNpmTasks('grunt-documantix');
  grunt.loadNpmTasks('grunt-plato');
  grunt.loadNpmTasks('grunt-include-replace');

  // define runner tasks
  grunt.registerTask('lint', 'jshint');
  grunt.registerTask('test', ['clean:coverage', 'prepareCoverage', 'lint', 'mochaTest', 'generateCoverageBadge', 'complexity']);
  grunt.registerTask('docs', ['clean:reportZip', 'clean:report', 'preparePlato', 'plato', 'documantix', 'includereplace', 'yuidoc', 'compress']);
  grunt.registerTask('all', ['clean', 'test', 'docs']);

};
<|endoftext|>


<commit_before>/*
  backgrid-paginator
  http://github.com/wyuenho/backgrid-paginator

  Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
  Licensed under the MIT license.
*/

// jshint globalstrict:true, node:true

"use strict";

module.exports = function (grunt) {

  grunt.initConfig({

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

    clean: {
      options: {
        force: true
      },
      api: [
        "api/**/*"
      ],
      "default": [
        "*.min.*",
        "test/coverage/**/*"
      ]
    },

    karma: {
      unit: {
        configFile: 'karma.conf.js',
        singleRun: true
      }
    },

    jsduck: {
      main: {
        src: ["backgrid-paginator.js"],
        dest: "api",
        options: {
          "external": ["Backbone.Model,Backbone.Collection,Backbone.View,Backgrid.Grid,Backgrid.Column"],
          "title": "backgrid-paginator",
          "no-source": true,
          "categories": "categories.json",
          "warnings": "-no_doc",
          "pretty-json": true
        }
      }
    },

    recess: {
      csslint: {
        options: {
          compile: true
        },
        files: {
          "backgrid-paginator.css": ["backgrid-paginator.css"]
        }
      },
      "default": {
        options: {
          compress: true
        },
        files: {
          "backgrid-paginator.min.css": ["backgrid-paginator.css"]
        }
      }
    },

    uglify: {
      options: {
        mangle: true,
        compress: true,
        preserveComments: "some"
      },
      "default": {
        files: {
          "backgrid-paginator.min.js": ["backgrid-paginator.js"]
        }
      }
    }
  });

  grunt.loadNpmTasks("grunt-contrib-clean");
  grunt.loadNpmTasks("grunt-contrib-uglify");
  grunt.loadNpmTasks("grunt-recess");
  grunt.loadNpmTasks("grunt-jsduck");
  grunt.loadNpmTasks("grunt-karma");

  grunt.registerTask("dist", ["uglify", "recess"]);
  grunt.registerTask("default", ["clean", "jsduck", "dist", "karma"]);
};
<commit_msg>Remove deprecated option<commit_after>/*
  backgrid-paginator
  http://github.com/wyuenho/backgrid-paginator

  Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
  Licensed under the MIT license.
*/

// jshint globalstrict:true, node:true

"use strict";

module.exports = function (grunt) {

  grunt.initConfig({

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

    clean: {
      options: {
        force: true
      },
      api: [
        "api/**/*"
      ],
      "default": [
        "*.min.*",
        "test/coverage/**/*"
      ]
    },

    karma: {
      unit: {
        configFile: 'karma.conf.js',
        singleRun: true
      }
    },

    jsduck: {
      main: {
        src: ["backgrid-paginator.js"],
        dest: "api",
        options: {
          "external": ["Backbone.Model,Backbone.Collection,Backbone.View,Backgrid.Grid,Backgrid.Column"],
          "title": "backgrid-paginator",
          "no-source": true,
          "categories": "categories.json",
          "pretty-json": true
        }
      }
    },

    recess: {
      csslint: {
        options: {
          compile: true
        },
        files: {
          "backgrid-paginator.css": ["backgrid-paginator.css"]
        }
      },
      "default": {
        options: {
          compress: true
        },
        files: {
          "backgrid-paginator.min.css": ["backgrid-paginator.css"]
        }
      }
    },

    uglify: {
      options: {
        mangle: true,
        compress: true,
        preserveComments: "some"
      },
      "default": {
        files: {
          "backgrid-paginator.min.js": ["backgrid-paginator.js"]
        }
      }
    }
  });

  grunt.loadNpmTasks("grunt-contrib-clean");
  grunt.loadNpmTasks("grunt-contrib-uglify");
  grunt.loadNpmTasks("grunt-recess");
  grunt.loadNpmTasks("grunt-jsduck");
  grunt.loadNpmTasks("grunt-karma");

  grunt.registerTask("dist", ["uglify", "recess"]);
  grunt.registerTask("default", ["clean", "jsduck", "dist", "karma"]);
};
<|endoftext|>