storyboard-webclient/Gruntfile.js

654 lines
18 KiB
JavaScript

/*
* Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the 'License'); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
/**
* This file serves as task declaration/configuration for steps executed
* during the grunt build. It loads grunt modules declared in package.json,
* configures them, and makes them available via 'grunt PLUGIN' on the
* commandline. It also groups these tasks into individual steps helpful during
* development, such as build, package, test, and release.
*
* @author Michael Krotscheck
*/
var config = {
livereload: {
port: 35729
}
};
var lrSnippet = require('connect-livereload')(config.livereload);
var mountFolder = function (connect, dir) {
'use strict';
return connect.static(require('path').resolve(dir));
};
var proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest;
module.exports = function (grunt) {
'use strict';
var dir = {
source: './src',
theme: './src/theme',
test: './test',
output: './build',
report: './reports',
node_modules: './node_modules',
fontawesome: './node_modules/@fortawesome/fontawesome-free-webfonts'
};
var proxies = {
localhost: {
context: '/api/v1',
host: 'localhost',
port: 8080,
https: false,
rewrite: {
'^/api/v1': '/v1'
}
}
};
// load all grunt tasks
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
grunt.initConfig({
/**
* grunt clean
*
* Cleans our output directories.
*/
clean: {
dist: {
files: [
{
dot: true,
src: [
dir.report,
'./cover',
dir.output
]
}
]
},
postbuild: [dir.output + '/js/storyboard-es6.js']
},
/**
* grunt gitinfo
*
* Gets information about the current state of the source repository.
*/
gitinfo: {
options: {
cwd: '.'
}
},
/**
* grunt template
*
* Interpolate variables into any templates we have defined.
*/
template: {
'process-html-template': {
options: {
data: {
sha: '<%= gitinfo.local.branch.current.SHA %>'
}
},
files: {
'src/app/pages/template/about.html': [
'src/app/pages/template/about.html.tpl'
]
}
}
},
/**
* grunt concat
*
* Creates a single file out of our javascript source in accordance
* with the concatenation priority. First the application module, then
* any dependent module declarations, and finally everything else.
*/
concat: {
dist: {
src: [
dir.source + '/app/**/module.js',
dir.source + '/app/**/*.js'
],
dest: dir.output + '/js/storyboard-es6.js'
}
},
/**
* grunt sass
*
* Compiles our .scss files into real CSS, and produces a source map
* to aid debugging.
*/
sass: {
options: {
includePaths: [
dir.theme + '/custom/',
dir.theme + '/storyboard/',
dir.node_modules + '/bootstrap-sass/assets/stylesheets/',
dir.node_modules + '/highlightjs/styles',
dir.node_modules + '/ng-sortable/dist/',
dir.fontawesome + '/scss/'
],
sourceMap: true
},
theme: {
files: {
'build/styles/main.css': dir.theme + '/main.scss'
}
}
},
/**
* Compile our SVG's into fonts. This is a utility method only which
* needs to be executed manually.
*/
webfont: {
custom_icons: {
src: dir.source + '/fonts/src/*.svg',
dest: dir.source + '/fonts',
destCss: dir.source + '/theme/base',
options: {
font: 'custom_icons',
syntax: 'bem',
htmlDemo: false,
stylesheet: 'css',
relativeFontPath: '../../fonts',
hashes: false
}
}
},
/**
* grunt html2js
*
* A convenience method that converts all of the templates found in our
* project into a single javascript file (mostly by converting them
* into strings). This presents a tradeoff: All of the HTML layout
* is loaded up front, which could take a while, but it prevents load
* lag during application runtime.
*/
html2js: {
options: {
module: 'sb.templates',
base: dir.source
},
main: {
src: [dir.source + '/app/*/template/**/**.html'],
dest: dir.output + '/js/templates.js'
}
},
/**
* grunt copy
*
* Copies any as-yet-unprocessed files into the dist directory, as well
* as pulling any assets from imported libraries to their appropriate
* locations.
*/
copy: {
dist: {
files: [
{
expand: true,
dot: true,
cwd: dir.source,
dest: dir.output,
src: [
'**/*.{txt,eot,ttf,woff}',
'*.html',
'robots.txt',
'config.json'
]
},
{
expand: true,
dot: true,
cwd: dir.fontawesome + '/webfonts/',
dest: dir.output + '/fonts',
src: [
'*.*'
]
},
{
src: dir.theme + '/storyboard/favicon.ico',
dest: dir.output + '/favicon.ico'
},
{
src: dir.theme + '/custom/favicon.ico',
dest: dir.output + '/favicon.ico'
}
]
},
draft: {
files: [
{
expand: true,
dot: true,
cwd: dir.test + '/draft',
dest: dir.output,
src: [
'*.json'
]
}
]
}
},
/**
* @private
*
* grunt useminPrepare
*
* This task is a configuration builder, used to parse minification
* annotations in index.html. It's used in our compile step as an
* dependency concatenator, so that we can easily declare what we
* need in the index.html file and get all the pieces wrapped up
* nice and pretty by the script.
*
* It will generate configurations for the concat task (the others
* are explicitly disabled).
*/
useminPrepare: {
html: [dir.source + '/index.html'],
options: {
flow: {
steps: {
'js': ['concat'],
'css': ['concat']
},
post: []
},
dest: dir.output
}
},
/**
* grunt useminPrepare cssmin
*
* Parses all of the css references in our index.html and minifies them.
* The configuration for this task is generated by useminPrepare.
*/
cssmin: {
minify: {
expand: true,
cwd: dir.output + '/styles/',
src: ['*.css'],
dest: dir.output + '/styles/'
}
},
/**
* grunt useminPrepare usemin
*
* Completes the packaging task by renaming all modified asset
* references from the previous steps in referencing documents.
*/
usemin: {
html: [
dir.output + '/index.html'
],
css: [
dir.output + '/styles/**/*.css'
],
options: {
dirs: [dir.output]
}
},
/**
* grunt htmlmin
*
* The final optimization step, which cleans up our html file and
* removes extraneous comments, tags, and more.
*/
htmlmin: {
dist: {
options: {
removeComments: true,
removeCommentsFromCDATA: true,
collapseWhitespace: false,
collapseBooleanAttributes: false,
removeAttributeQuotes: false,
removeRedundantAttributes: false,
useShortDoctype: false,
removeEmptyAttributes: true,
removeOptionalTags: true
},
files: [
{
expand: true,
cwd: dir.output,
src: ['index.html'],
dest: dir.output
}
]
}
},
/**
* grunt compress
*
* Create a tarball containing the build output.
*/
compress: {
main: {
options: {
archive: 'storyboard-output.tgz',
mode: 'tgz'
},
files: [
{expand: true, cwd: dir.output, src: ['**/*'], dest: ''}
]
}
},
/**
* grunt babel
*
* Transpiles all JS to ES5 and minifies the output.
*/
babel: {
options: {
sourceMap: true,
presets: ['@babel/preset-env'],
compact: true,
comments: false
},
dist: {
files: [
{
src: dir.output + '/js/storyboard-es6.js',
dest: dir.output + '/js/storyboard.js'
}
]
}
},
/**
* grunt watch
*
* This task is run with grunt server, in order to automatically update
* the hosted files that are served via the devserver. The livereload
* directive will then communicate with the browser and refresh the page
* when necessary.
*/
watch: {
template: {
files: [
dir.source + '/**/*.tpl'
],
tasks: ['compile']
},
concat: {
files: [
dir.source + '/app/**/module.js',
dir.source + '/app/**/*.js'
],
tasks: ['concat']
},
babel: {
/**
* Grunt has trouble watching new files if
* the path starts with ./
*/
files: [
dir.output + '/js/storyboard-es6.js'
],
options: {
event: ['added', 'changed']
},
tasks: ['babel']
},
clean_postbuild: {
files: [
dir.output + '/js/storyboard.js'
],
tasks: ['clean:postbuild']
},
sass: {
files: [
dir.theme + '/**/*.scss'
],
tasks: ['sass:theme']
},
copy: {
files: [
dir.source + '/**/*.{ico,txt,eot,ttf,woff}'
],
tasks: ['copy:dist']
},
index: {
files: [
dir.source + '/index.html'
],
tasks: ['compile']
},
templates: {
files: [
dir.source + '/app/*/template/**/**.html'
],
tasks: ['html2js']
},
livereload: {
options: {
livereload: config.livereload.port
},
files: [
dir.output + '/**/*.*'
]
}
},
/**
* grunt connect
*
* The connect plugin hosts a simple web server with our application,
* either under development or under test.
*/
connect: {
options: {
hostname: grunt.option('hostname') || 'localhost'
},
livereload: {
options: {
port: 9000,
middleware: function (connect) {
return [
lrSnippet,
mountFolder(connect, dir.output),
proxySnippet
];
}
},
proxies: [proxies.localhost]
},
dist: {
options: {
port: 9000,
keepalive: true,
middleware: function (connect) {
return [
mountFolder(connect, dir.output),
proxySnippet
];
}
},
proxies: [proxies.localhost]
},
test: {
options: {
port: 9005,
middleware: function (connect) {
return [
mountFolder(connect, dir.output),
proxySnippet
];
}
},
proxies: [proxies.localhost]
}
},
/**
* grunt shell:xvfbStart / grunt shell:xvfbStop
*
* Starts and stops a virtual frame buffer.
*/
shell: {
xvfbStart: {
command: 'source ./bin/xvfb.sh start'
},
xvfbStop: {
command: 'source ./bin/xvfb.sh stop'
}
},
/**
* grunt protractor
*
* Protractor is an angular-provided method by which jasmine tests are
* executed via the selenium web driver. Its goal is to handle browser
* drive testing, rather than unit or integration testing.
*/
protractor: {
options: {
configFile: './protractor.conf.js',
keepAlive: true,
noColor: false,
args: {
}
},
dist: {},
integration: {
options: {
configFile: './protractor-integration.conf.js'
}
}
}
});
/**
* Compiles all of our sources.
*/
grunt.registerTask('compile', [
'gitinfo',
'template',
'useminPrepare',
'concat',
'babel',
'sass',
'html2js',
'copy:dist',
'usemin'
]);
/**
* Package built code into a release package.
*/
grunt.registerTask('package', [
'cssmin',
'htmlmin',
'compress'
]);
/**
* Compile and packages our code.
*/
grunt.registerTask('build', [
'compile',
'package',
'clean:postbuild'
]);
/**
* Compile and packages our code.
*/
grunt.registerTask('build:draft', [
'compile',
'package',
'copy:draft'
]);
/**
* This task performs a full build of our application, and then runs that
* source in a local web server. It does no watching, it simply hosts the
* files.
*/
grunt.registerTask('serve:dist', [
'clean:dist',
'compile',
'package',
'configureProxies:dist',
'connect:dist'
]);
/**
* Development server - runs a build and sets up concurrent watchers that
* will automatically lint, test, and refresh
* the code when a change is detected.
*/
grunt.registerTask('serve', [
'clean:dist',
'compile',
'configureProxies:livereload',
'connect:livereload',
'watch'
]);
/**
* grunt test:integration
*
* This command will create a clean build against which our integration
* tests will be run.
*/
grunt.registerTask('test:integration', [
'clean:dist',
'compile',
'configureProxies:test',
'connect:test',
'protractor:integration'
]);
/**
* grunt test:functional
*
* This command will create a clean build against which our functional
* tests will be run. For more information, please see
* protractor.conf.js
*/
grunt.registerTask('test:functional', [
'clean:dist',
'compile',
'connect:test',
'protractor'
]);
};