/** * Copyright (c) 2016 Kam Low * * @license MIT **/ var fs = require('fs'), path = require('path'), Promise = require('bluebird'), tmp = require('tmp'), grunt = require('grunt'), package = require('./package'), _ = require('lodash'); // Ensures temporary files are cleaned up on program close, even if errors are encountered. tmp.setGracefulCleanup(); var defaults = { silent: false, port: 4400, targetDir: path.resolve(process.cwd(), 'public'), targetFile: 'index.html', appDir: path.resolve(__dirname, 'app'), configFile: path.resolve(__dirname, 'app/lib/config.js'), cacheDir: tmp.dirSync({ unsafeCleanup: true, prefix: 'spectacle-' }).name }; function resolveOptions(options) { var opts = _.extend({}, defaults, options); // Replace some absolute paths if (opts.specFile && opts.specFile.indexOf('test/fixtures') === 0) opts.specFile = path.resolve(__dirname, opts.specFile); if (opts.logoFile && opts.logoFile.indexOf('test/fixtures') === 0) opts.logoFile = path.resolve(__dirname, opts.logoFile); return opts; } /** * Run Spectacle and configured tasks **/ module.exports = function (options) { var opts = resolveOptions(options); // //= Load the specification and init configuration function loadData() { var specPath = path.resolve(opts.specFile); delete require.cache[specPath]; return require(path.resolve(opts.appDir + '/lib/preprocessor'))( options, require(specPath)); } var config = require(path.resolve(opts.configFile))(grunt, opts, loadData()); // //= Setup Grunt to do the heavy lifting grunt.initConfig(_.merge({ pkg: package }, config)); if(opts.silent) { grunt.log.writeln = function() {} grunt.log.write = function() {} grunt.log.header = function() {} grunt.log.ok = function() {} } var cwd = process.cwd(); // change CWD for loadNpmTasks global install var exists = grunt.file.exists(path.join(path.resolve('node_modules'), 'grunt-contrib-concat', 'package.json')); if (!exists) process.chdir(__dirname); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-compile-handlebars'); grunt.loadNpmTasks('grunt-prettify'); grunt.loadNpmTasks('grunt-sass'); process.chdir(cwd); grunt.registerTask('predentation', 'Remove indentation from generated
tags.', function() { var html = fs.readFileSync(opts.cacheDir + '/' + opts.targetFile, 'utf8'); html = html.replace(/([\s\S]*?)<\/code><\/pre>/gmi, function(x, y) { var lines = x.split('\n'), level = null; if (lines) { // Determine the level of indentation lines.forEach(function(line) { if (line[0] === '<') return; var wsp = line.search(/\S/); level = (level === null || (wsp < line.length && wsp < level)) ? wsp : level; }); // Remove indentation var regex = new RegExp('^\\s{' + level + '}'); lines.forEach(function(line, index, lines) { lines[index] = line.replace(regex, ''); }); } return lines.join('\n'); }); fs.writeFileSync(opts.cacheDir + '/' + opts.targetFile, html); }); grunt.registerTask('stylesheets', ['sass:scss', 'concat:css', 'cssmin']); grunt.registerTask('javascripts', ['concat:js', 'uglify']); grunt.registerTask('templates', ['clean:html', 'compile-handlebars', 'predentation', 'prettify']); grunt.registerTask('foundation', ['sass:foundation_scss', 'concat:foundation_css']); // 'concat:foundation_js' grunt.registerTask('default', ['stylesheets', 'javascripts', 'foundation', 'templates']); grunt.registerTask('server', ['connect']); grunt.registerTask('develop', ['server', 'watch']); // Reload template data when watch files change grunt.event.on('watch', function(action, filepath) { // if (filepath == config.specFile) grunt.config.set('compile-handlebars.compile.templateData', loadData()); }); // Report, etc when all tasks have completed. var donePromise = new Promise(function(resolve, reject) { grunt.task.options({ error: function(e) { if(!opts.silent) { console.warn('Task error:', e); } // TODO: fail here or push on? reject(e); }, done: function() { if(!opts.silent) { console.log('All tasks complete'); } resolve(); } }); }); // //= Run the shiz if (opts.startServer) { grunt.task.run('server'); } else { if (!opts.disableCss) { grunt.task.run(['foundation', 'stylesheets']); } if (!opts.disableJs) { grunt.task.run('javascripts'); } if (opts.logoFile) { grunt.task.run('copy:logo'); } grunt.task.run('templates'); if (opts.developmentMode) { grunt.task.run('develop'); } } grunt.task.start(); return donePromise; };