454 lines
14 KiB
JavaScript
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']);
|
|
};
|