/* global -moment */ /* jshint node: true */ /* jscs:disable */ var _ = require('lodash'), fs = require('fs-extra'), path = require('path'), https = require('https'), getTopContribs = require('top-gh-contribs'), moment = require('moment'), chalk = require('chalk'), Promise = require('bluebird'), escapeChar = process.platform.match(/^win/) ? '^' : '\\', cwd = process.cwd().replace(/( |\(|\))/g, escapeChar + '$1'); module.exports = function(grunt) { // Find all of the task which start with `grunt-` and load them, rather than explicitly declaring them all require('matchdep').filterDev(['grunt-*', '!grunt-cli']).forEach(grunt.loadNpmTasks); grunt.initConfig({ jshint: { options: { jshintrc: true, ignores: [ 'node_modules/**', 'bower_components/**', 'tmp/**', 'dist/**', 'vendor/**' ] }, all: ['**/*.js'] }, jscs: { app: { options: { config: '.jscsrc', excludeFiles: [ 'node_modules/**', 'bower_components/**', 'tests/**', 'tmp/**', 'dist/**', 'vendor/**' ] }, files: { src: ['**/*.js'] } }, tests: { options: { config: 'tests/.jscsrc' }, files: { src: [ 'tests/**/*.js' ] } } }, shell: { 'npm-install': { command: 'npm install' }, 'bower-install': { command: path.resolve(cwd + '/node_modules/.bin/bower install') }, csscombfix: { command: path.resolve(cwd + '/node_modules/.bin/csscomb -c app/styles/csscomb.json -v app/styles') }, csscomblint: { command: path.resolve(cwd + '/node_modules/.bin/csscomb -c app/styles/csscomb.json -lv app/styles') } } }); grunt.registerTask('init', 'Install the client dependencies', ['shell:npm-install', 'shell:bower-install', 'buildAboutPage'] ); grunt.registerTask('lint', 'Run the code style checks and linter', ['jshint', 'jscs', 'shell:csscomblint'] ); // ### Build About Page *(Utility Task)* // Builds the github contributors partial template used on the about page, // and downloads the avatar for each of the users. // Run by any task that compiles ember assets or manually via `grunt buildAboutPage`. // Only builds if the template does not exist. // To force a build regardless, supply the --force option. // `grunt buildAboutPage --force` grunt.registerTask('buildAboutPage', 'Compile assets for the About Ghost page', function () { var done = this.async(), templatePath = 'app/templates/-contributors.hbs', imagePath = 'public/assets/img/contributors', timeSpan = moment().subtract(90, 'days').format('YYYY-MM-DD'), oauthKey = process.env.GITHUB_OAUTH_KEY, contribNumber = 18; if (fs.existsSync(templatePath) && !grunt.option('force')) { grunt.log.writeln('Contributors template already exists.'); grunt.log.writeln(chalk.bold('Skipped')); return done(); } grunt.verbose.writeln('Downloading release and contributor information from Github'); function mergeContribs(first, second) { _.each(second, function (contributor) { var contributorInFirst = _.find(first, ['name', contributor.name]); if (contributorInFirst) { contributorInFirst.commitCount += contributor.commitCount; } else { first.push(contributor); } }); return _(first) .filter(function (contributor) { // remove greenkeeper from contributor list return contributor.name !== 'greenkeeperio-bot'; }) .sortBy('commitCount') .reverse() .take(contribNumber) .value(); } return Promise.join( Promise.promisify(fs.mkdirs)(imagePath), getTopContribs({ user: 'tryghost', repo: 'ghost', oauthKey: oauthKey, sinceDate: timeSpan, count: contribNumber, retry: true }), getTopContribs({ user: 'tryghost', repo: 'ghost-admin', oauthKey: oauthKey, sinceDate: timeSpan, count: contribNumber, retry: true }) ).then(function (results) { var contributors = mergeContribs(results[1], results[2]), contributorTemplate = '
\n \n' + ' " alt="<%= name %>" />\n' + ' \n
', downloadImagePromise = function (url, name) { return new Promise(function (resolve, reject) { var file = fs.createWriteStream(path.join(__dirname, imagePath, name)); https.get(url, function (response) { response.pipe(file); file.on('finish', function () { file.close(); resolve(); }); }).on('error', reject); }); }; grunt.verbose.writeln('Creating contributors template'); grunt.file.write( templatePath, _.map(contributors, function (contributor) { var compiled = _.template(contributorTemplate); return compiled(contributor); }).join('\n') ); grunt.verbose.writeln('Downloading images for top contributors'); return Promise.all(_.map(contributors, function (contributor) { return downloadImagePromise(contributor.avatarUrl + '&s=60', contributor.name); })); }).then(done).catch(function (error) { grunt.log.error(error); if (error.http_status) { grunt.log.writeln('GitHub API request returned status: ' + error.http_status); } if (error.ratelimit_limit) { grunt.log.writeln('Rate limit data: limit: %d, remaining: %d, reset: %s', error.ratelimit_limit, error.ratelimit_remaining, moment.unix(error.ratelimit_reset).fromNow()); } done(false); }); }); };