Files
portal-webapp/portal_client/Gruntfile.js
T
2018-07-07 20:43:51 -05:00

454 lines
14 KiB
JavaScript

/*jslint node: true */
'use strict';
var pkg = require('./package.json');
var serveStatic = require('serve-static');
var serveIndex = require('serve-index');
//Using exclusion patterns slows down Grunt significantly
//instead of creating a set of patterns like '**/*.js' and '!**/node_modules/**'
//This method assumes the website root is in the app folder.
//
//omitDirPrefix: If true, refrains from adding 'app/' to each of the patterns.
var createFolderGlobs = function (fileTypePatterns, omitDirPrefix) {
var ignore = ['yarn_components', 'tzdata'];
//FOR DEBUGGING
//console.log('\ncreateFolderGlobs()...');
//Convert fileTypePatterns to array
fileTypePatterns = Array.isArray(fileTypePatterns) ? fileTypePatterns : [fileTypePatterns];
var fs = require('fs');
//FOR DEBUGGING
//console.log('File Type Patterns (Computed): ' + fileTypePatterns);
//Change from the grunt dir to the app dir
var gruntDir = process.cwd();
process.chdir('app');
//FOR DEBUGGING
//console.log('CWD: ' + process.cwd());
//Modify
var returnPatterns = fs.readdirSync(process.cwd())
.map(function (file) {
//console.log('Examining: ' + file);
//If this is a file, or a folder in the ignore list
if (ignore.indexOf(file) !== -1 ||
file.indexOf('.') === 0 ||
!fs.lstatSync(file).isDirectory()) {
//FOR DEBUGGING
//console.log('Ignoring: ' + file);
return null;
} else {
//FOR DEBUGGING
//console.log('--> Accepting: ' + file);
return fileTypePatterns.map(function (pattern) {
return file + '/**/' + pattern;
});
}
})
.filter(function (patterns) {
return patterns;
})
.concat(fileTypePatterns);
//Change back from app dir to grunt dir
process.chdir(gruntDir);
if (!omitDirPrefix) {
//Prepend 'app/' to each filter item
var patternsString = returnPatterns.toString();
var csvArray = patternsString.split(',');
returnPatterns = csvArray.map(function (pattern) {
return 'app/' + pattern;
});
}
//FOR DEBUGGING
//console.log('RESULT: ' + returnPatterns);
return returnPatterns;
}; //end function createFolderGlobs()
module.exports = function (grunt) {
require('time-grunt')(grunt);
// load all grunt tasks with jit loading
require('jit-grunt')(grunt, {
protractor: 'grunt-protractor-runner',
configureProxies: 'grunt-connect-proxy2',
dom_munger: 'grunt-dom-munger2',
ngtemplates: 'grunt-angular-templates'
});
// Project configuration.
grunt.initConfig({
connect: {
//Default options for all connect targets
options: {
port: 9000,
hostname: '127.0.0.1',
base: 'app/',
livereload: 35729,
open: 'http://127.0.0.1:9000',
middleware: function (connect, options) {
if (!Array.isArray(options.base)) {
options.base = [options.base];
}
// Setup the proxy
var middlewares = [require('grunt-connect-proxy2/lib/utils').proxyRequest];
// Serve static files.
options.base.forEach(function (base) {
middlewares.push(serveStatic(base));
});
// Make directory browse-able.
var directory = options.directory || options.base[options.base.length - 1];
middlewares.push(serveIndex(directory));
return middlewares;
}
},
main: {
//See https://github.com/drewzboto/grunt-connect-proxy
proxies: [
{
context: ['/rest', '/portal'],
host: 'localhost',
port: 8080,
ws: true,
}
]
},
dist: {
options: {
base: 'dist/'
},
proxies: [
{
context: ['/rest', '/portal'],
host: 'localhost',
port: 8080
}
]
}
},
watch: {
main: {
options: {
livereload: true,
spawn: false,
debounceDelay: 250
},
files: [createFolderGlobs(['*.js', '*.less', '*.html', '*.css']), '!_SpecRunner.html', '!.grunt', '!*-spec.js'],
tasks: []
},
dist: {
options: {
livereload: true,
spawn: false
},
files: ['app.full.min.css', 'app.full.min.js', 'index.html'],
tasks: [] //all the tasks are run dynamically during the watch event handler
}
},
jshint: {
main: {
options: {
jshintrc: '.jshintrc'
},
src: [createFolderGlobs('*.js'), '*.js', '!app/common/generated_code/**', '!Gruntfile.js', '!assets.js', '!webpack.config.js', '!yarn_file_copy.js']
}
},
csslint: {
main: {
options: {
csslintrc: '.csslintrc'
},
src: ['<%= dom_munger.data.applintcss %>', '!app/compiled-less/**', '!app/yarn_components/**']
}
},
lesslint: {
main: {
options: {
csslint: {
csslintrc: '.csslintrc'
}
},
src: ['app/*.less', '!app/compiled-less/**', '!app/yarn_components/**']
}
},
clean: {
before: {
src: ['dist', 'temp', 'test_results']
},
after: {
src: ['temp']
},
cleanDistTest: {
src: ['distTestFolder']
}
},
less: {
production: {
files: [{
cwd: 'app',
src: ['**/*.less', '!yarn_components/**'],
dest: 'app/compiled-less/',
filter: 'isFile',
expand: true,
ext: '.less.css'
}]
}
},
ngtemplates: {
main: {
options: {
module: pkg.name,
htmlmin: '<%= htmlmin.main.options %>'
},
src: [createFolderGlobs('*.html', true), '!index.html', '!_SpecRunner.html'],
dest: 'temp/templates.js',
cwd: 'app/'
}
},
copy: {
main: {
files: [
{cwd: 'app', src: ['<%= dom_munger.data.appjsCopyList %>','<%= dom_munger.data.appcssCopyList %>'], dest: 'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['yarn_components/**/*.woff'], dest: 'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['yarn_components/**/*.woff2'], dest: 'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['yarn_components/**/*.eot'], dest: 'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['yarn_components/**/*.svg'], dest: 'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['yarn_components/**/*.ttf'], dest: 'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['yarn_components/**/*.png'], dest: 'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['yarn_components/**/*.jpg'], dest: 'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['yarn_components/**/*.gif'], dest: 'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['images/**/*.svg'], dest: 'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['images/**/*.png'], dest: 'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['images/**/*.jpg'], dest: 'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['images/**/*.gif'], dest: 'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['fonts/google-md-icons/**'], dest:'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['favicon.ico'], dest: 'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['robots.txt'], dest: 'dist/', filter: 'isFile', expand: true},
{cwd: 'app', src: ['404.html'], dest: 'dist/', filter: 'isFile', expand: true}
]
},
//Prepares a copy of the dist folder and inserts unit tests for running
//unit tests on the distribution build.
prepareDistTestFolder: {
files: [
//Copy the dist folder's contents to the war.
//Path is relative to src/main/webapp/grunt
{cwd: 'dist', src: ['**'], dest: 'distTestFolder', filter: 'isFile', expand: true},
{cwd: 'app', src: ['**/*-spec.js'], dest: 'distTestFolder', filter: 'isFile', expand: true}
]
}
},
dom_munger: { //jshint ignore: line
read: {
options: {
read: [
{selector: 'script[data-build!="exclude"]', attribute: 'src', writeto: 'appjs', isPath: true},
{selector: 'link[type="text/css"][data-build!="exclude"]', attribute: 'href', writeto: 'appcss', isPath: true},
{selector: 'script[data-remove="exclude"]', attribute: 'src', writeto: 'appjsCopyList'},
{selector: 'link[type="text/css"][data-remove="exclude"]', attribute: 'href', writeto: 'appcssCopyList'},
{selector: 'script[data-karma-tests!="exclude"]', attribute: 'src', writeto: 'applintjs', isPath: true},
{selector: 'link[type="text/css"]', attribute: 'href', writeto: 'applintcss', isPath: true}
]
},
src: 'app/index.html'
},
update: {
options: {
remove: ['script[data-remove!="exclude"]', 'link[data-remove!="exclude"]'],
append: [
{selector: 'body', html: '<script src="app.full.min.js"></script>'},
{selector: 'head', html: '<link rel="stylesheet" href="app.full.min.css">'}
]
},
src: 'app/index.html',
dest: 'dist/index.html'
}
},
cssmin: {
options: {
target: 'dist/'//Eg. Changes '../relative/url/path/in/bower/components' to 'app/yarn_components/...'
//root: 'app' //Eg. changes '../relative/url/path/in/bower/components' to '/yarn_components...', but the starting slash causes problems
},
main: {
files: {
'dist/app.full.min.css': [
'temp/**/*.less.css',
'<%= dom_munger.data.appcss %>'
]
}
}
},
concat: {
main: {
src: ['<%= dom_munger.data.appjs %>', '<%= ngtemplates.main.dest %>'],
dest: 'temp/app.full.js'
}
},
ngAnnotate: {
main: {
src: 'temp/app.full.js',
dest: 'temp/app.full.js'
}
},
uglify: {
main: {
files: {
'dist/app.full.min.js': ['temp/app.full.js']
}
},
pretty: {
options: {
beautify: true,
preserveComments: 'all',
sourceMap: true,
sourceMapName: 'dist/app.full.min.js.map'
},
files: {
'dist/app.full.min.js': ['temp/app.full.js']
}
}
},
html2js: {
options: {
base: '.',
module: 'ui-templates',
rename: function (modulePath) {
var moduleName = modulePath.replace('app/common/partials/ui-bootstrap-tpls/', '').replace('.html', '');
return 'template' + '/' + moduleName + '.html';
}
},
main: {
src: ['app/common/partials/ui-bootstrap-tpls/**/*.html'],
dest: 'app/common/generated_code/ui-templates.js'
}
},
htmlmin: {
main: {
options: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true,
removeEmptyAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true
},
files: {
'dist/index.html': 'dist/index.html'
}
}
},
concurrent: {
build: [
'onlyBuild'
],
/**
* Note: The multiCapabilities feature of protractor does not seem compatible
* with grunt concurrent, unless everything passes perfectly
*/
test: {
tasks: [
'unitTests',
]
},
serve: {
tasks: [
'unitTests',
'onlyServe'
],
options: {
logConcurrentOutput: true
}
}
} //end concurrent
}); //end grunt.initConfig
//Runs the linters through our code
grunt.registerTask('lintAll', [
'dom_munger:read',
'jshint',
'lesslint',
'csslint']);
grunt.registerTask('unitTests', [
'lintAll',
'dom_munger:read',
]);
/**
* Used by the concurrent task to split up build task.
*/
grunt.registerTask('onlyBuild', [
'clean:before',
'dom_munger',
'less', //Compiles less files to css. Creates one css file for each less file in a respective folder in temp/path/name.css
'ngtemplates', //creates temp/templates.js that maps templates safely for minification
'cssmin', //minifies css into dist/app.full.min.css
'concat',
'ngAnnotate', //Makes AngularJS files minification safe. Reads temp/app.full.js. Writes results to temp/app.full.js
'uglify:main', //Minifies and uglifies
'copy:main',
'htmlmin',
'clean:after'
]);
/**
* Used by the concurrent task to split up serve task.
*/
grunt.registerTask('onlyServe', [
'configureProxies:main',
'connect:main',
'watch:main'
]);
//Builds and runs a live watch server using the distribution build.
grunt.registerTask('serveDist', ['build', 'connect:dist', 'watch:dist']);
//Runs a test on the distribution build.
//NOTE: this currently fails with an undefined tinyMCE variable
//
grunt.registerTask('testDist', [
'build',
'copy:prepareDistTestFolder',
'clean:cleanDistTest'
]);
//############################################################################
//############################################################################
// The tasks below are intended for public command line use
//############################################################################
//############################################################################
/** Makes the distribution build */
grunt.registerTask('build', ['concurrent:build']);
/** Runs a live watch server proxied between port 9000 and 8080 */
grunt.registerTask('serve', ['concurrent:serve']);
/** Re converts the html/js templates. */
grunt.registerTask('runHTML2js', ['html2js']);
/** Runs the test task, including lint, unit tests, and e2e tests */
grunt.registerTask('test', ['concurrent:test']);
/** By default, we run the serve task */
grunt.registerTask('default', ['serve']);
/** Compiles project's less files into css. */
grunt.registerTask('makeLess', ['dom_munger', 'less']);
};