09177883a6
Cleaned up eslint issue.
560 lines
20 KiB
JavaScript
560 lines
20 KiB
JavaScript
const marked = require('marked');
|
|
const fs = require('fs');
|
|
const _ = require('lodash');
|
|
|
|
module.exports = function(grunt) {
|
|
require('load-grunt-tasks')(grunt);
|
|
|
|
// Project configuration.
|
|
grunt.util.linefeed = '\n';
|
|
|
|
grunt.initConfig({
|
|
ngversion: '1.6.1',
|
|
bsversion: '4.1.1',
|
|
modules: [],//to be filled in by build task
|
|
pkg: grunt.file.readJSON('package.json'),
|
|
dist: 'dist',
|
|
filename: 'ui-bootstrap',
|
|
filenamecustom: '<%= filename %>-custom',
|
|
meta: {
|
|
modules: 'angular.module("ui.bootstrap", [<%= srcModules %>]);',
|
|
tplmodules: 'angular.module("ui.bootstrap.tpls", [<%= tplModules %>]);',
|
|
all: 'angular.module("ui.bootstrap", ["ui.bootstrap.tpls", <%= srcModules %>]);',
|
|
cssInclude: '',
|
|
cssFileBanner: '/* Include this file in your html if you are using the CSP mode. */\n\n',
|
|
cssFileDest: '<%= dist %>/<%= filename %>-<%= pkg.version %>-csp.css',
|
|
banner: [
|
|
'/*',
|
|
' * <%= pkg.name %>',
|
|
' * <%= pkg.homepage %>\n',
|
|
' * Version: <%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>',
|
|
' * License: <%= pkg.license %>',
|
|
' */'
|
|
].join('\n')
|
|
},
|
|
delta: {
|
|
docs: {
|
|
files: ['misc/demo/index.html'],
|
|
tasks: ['after-test']
|
|
},
|
|
html: {
|
|
files: ['template/**/*.html'],
|
|
tasks: ['html2js', 'karma:watch:run']
|
|
},
|
|
js: {
|
|
files: ['src/**/*.js', '!src/**/index.js'],
|
|
tasks: ['karma:watch:run']
|
|
}
|
|
},
|
|
concat: {
|
|
dist: {
|
|
options: {
|
|
banner: '<%= meta.banner %><%= meta.modules %>\n',
|
|
footer: '<%= meta.cssInclude %>'
|
|
},
|
|
src: [], //src filled in by build task
|
|
dest: '<%= dist %>/<%= filename %>-<%= pkg.version %>.js'
|
|
},
|
|
dist_tpls: {
|
|
options: {
|
|
banner: '<%= meta.banner %><%= meta.all %>\n<%= meta.tplmodules %>\n',
|
|
footer: '<%= meta.cssInclude %>'
|
|
},
|
|
src: [], //src filled in by build task
|
|
dest: '<%= dist %>/<%= filename %>-tpls-<%= pkg.version %>.js'
|
|
}
|
|
},
|
|
copy: {
|
|
demohtml: {
|
|
options: {
|
|
//process html files with gruntfile config
|
|
processContent: grunt.template.process
|
|
},
|
|
files: [
|
|
{
|
|
expand: true,
|
|
src: ['**/*.html'],
|
|
cwd: 'misc/demo/',
|
|
dest: 'dist/'
|
|
}
|
|
]
|
|
},
|
|
demoassets: {
|
|
files: [
|
|
{
|
|
expand: true,
|
|
//Don't re-copy html files, we process those
|
|
src: ['**/**/*', '!**/*.html'],
|
|
cwd: 'misc/demo',
|
|
dest: 'dist/'
|
|
}
|
|
]
|
|
},
|
|
docs: {
|
|
files: [
|
|
{
|
|
expand: true,
|
|
src: ['**/*', '*/*'],
|
|
cwd: 'dist/',
|
|
dest: 'docs/'
|
|
}
|
|
]
|
|
}
|
|
},
|
|
uglify: {
|
|
options: {
|
|
banner: '<%= meta.banner %>'
|
|
},
|
|
dist: {
|
|
src: ['<%= concat.dist.dest %>'],
|
|
dest: '<%= dist %>/<%= filename %>-<%= pkg.version %>.min.js'
|
|
},
|
|
dist_tpls: {
|
|
src: ['<%= concat.dist_tpls.dest %>'],
|
|
dest: '<%= dist %>/<%= filename %>-tpls-<%= pkg.version %>.min.js'
|
|
}
|
|
},
|
|
html2js: {
|
|
dist: {
|
|
options: {
|
|
module: null, // no bundle module for all the html2js templates
|
|
base: '.',
|
|
rename: function(moduleName) {
|
|
return `uib/${moduleName}`;
|
|
}
|
|
},
|
|
files: [
|
|
{
|
|
expand: true,
|
|
src: ['template/**/*.html'],
|
|
ext: '.html.js'
|
|
}
|
|
]
|
|
}
|
|
},
|
|
eslint: {
|
|
files: ['Gruntfile.js', 'src/**/*.js']
|
|
},
|
|
karma: {
|
|
options: {
|
|
configFile: 'karma.conf.js'
|
|
},
|
|
watch: {
|
|
background: true
|
|
},
|
|
continuous: {
|
|
singleRun: true
|
|
},
|
|
jenkins: {
|
|
singleRun: true,
|
|
autoWatch: false,
|
|
colors: false,
|
|
reporters: ['dots', 'junit'],
|
|
browsers: ['Chrome', 'ChromeCanary', 'Firefox', 'Opera', '/Users/jenkins/bin/safari.sh']
|
|
},
|
|
travis: {
|
|
singleRun: true,
|
|
autoWatch: false,
|
|
reporters: ['dots'],
|
|
browsers: ['Firefox']
|
|
},
|
|
coverage: {
|
|
preprocessors: {
|
|
'src/*/*.js': 'coverage'
|
|
},
|
|
reporters: ['progress', 'coverage']
|
|
}
|
|
},
|
|
conventionalChangelog: {
|
|
options: {
|
|
changelogOpts: {
|
|
preset: 'angular'
|
|
},
|
|
templateFile: 'misc/changelog.tpl.md'
|
|
},
|
|
release: {
|
|
src: 'CHANGELOG.md'
|
|
}
|
|
},
|
|
shell: {
|
|
//We use %version% and evaluate it at run-time, because <%= pkg.version %>
|
|
//is only evaluated once
|
|
'release-prepare': [
|
|
'git add docs'
|
|
],
|
|
'release-complete': [
|
|
'git commit -a -m "chore(release): v%version%"',
|
|
'git tag v%version%',
|
|
'git push --follow-tags'
|
|
],
|
|
'publish': [
|
|
'rm -rf dist/*',
|
|
'cp ./docs/ui-bootstrap-%version%.js ./dist/ui-bootstrap.js',
|
|
'cp ./docs/ui-bootstrap-%version%-csp.css ./dist/ui-bootstrap-csp.css',
|
|
'cp ./docs/ui-bootstrap-tpls-%version%.js ./dist/ui-bootstrap-tpls.js',
|
|
'npm publish'
|
|
]
|
|
},
|
|
'ddescribe-iit': {
|
|
files: [
|
|
'src/**/*.spec.js'
|
|
]
|
|
}
|
|
});
|
|
|
|
//register before and after test tasks so we've don't have to change cli
|
|
//options on the google's CI server
|
|
grunt.registerTask('before-test', [/*'ddescribe-iit',*/ 'eslint', 'html2js']);
|
|
grunt.registerTask('after-test', ['build', 'copy']);
|
|
|
|
//Rename our watch task to 'delta', then make actual 'watch'
|
|
//task build things, then start test server
|
|
grunt.renameTask('watch', 'delta');
|
|
grunt.registerTask('watch', ['before-test', 'after-test', 'karma:watch', 'delta']);
|
|
|
|
// Default task.
|
|
grunt.registerTask('default', ['before-test', 'test', 'after-test']);
|
|
|
|
// Build docs
|
|
grunt.registerTask('docs', ['before-test', 'after-test', 'copy:docs']);
|
|
|
|
//Common ui.bootstrap module containing all modules for src and templates
|
|
//findModule: Adds a given module to config
|
|
const foundModules = {};
|
|
|
|
function findModule(name)
|
|
{
|
|
if(foundModules[name])
|
|
{ return; }
|
|
foundModules[name] = true;
|
|
|
|
function breakup(text, separator)
|
|
{
|
|
return text.replace(/[A-Z]/g, function(match) {
|
|
return separator + match;
|
|
});
|
|
}
|
|
|
|
function ucwords(text)
|
|
{
|
|
return text.replace(/^([a-z])|\s+([a-z])/g, function($1) {
|
|
return $1.toUpperCase();
|
|
});
|
|
}
|
|
|
|
function enquote(str)
|
|
{
|
|
return `"${str}"`;
|
|
}
|
|
|
|
function enquoteUibDir(str)
|
|
{
|
|
return enquote(`uib/${str}`);
|
|
}
|
|
|
|
const module = {
|
|
name: name,
|
|
moduleName: enquote(`ui.bootstrap.${name}`),
|
|
displayName: ucwords(breakup(name, ' ')),
|
|
srcFiles: grunt.file.expand([`src/${name}/*.js`, `!src/${name}/index.js`, `!src/${name}/index-nocss.js`]),
|
|
cssFiles: grunt.file.expand(`src/${name}/*.css`),
|
|
tplFiles: grunt.file.expand(`template/${name}/*.html`),
|
|
tpljsFiles: grunt.file.expand(`template/${name}/*.html.js`),
|
|
tplModules: grunt.file.expand(`template/${name}/*.html`).map(enquoteUibDir),
|
|
dependencies: dependenciesForModule(name),
|
|
docs: {
|
|
md: grunt.file.expand(`src/${name}/docs/*.md`)
|
|
.map(grunt.file.read).map((str) => marked(str)).join('\n'),
|
|
js: grunt.file.expand(`src/${name}/docs/*.js`)
|
|
.map(grunt.file.read).join('\n'),
|
|
html: grunt.file.expand(`src/${name}/docs/*.html`)
|
|
.map(grunt.file.read).join('\n')
|
|
}
|
|
};
|
|
|
|
const styles = {
|
|
css: [],
|
|
js: []
|
|
};
|
|
module.cssFiles.forEach(processCSS.bind(null, module.name, styles, true));
|
|
if(styles.css.length)
|
|
{
|
|
module.css = styles.css.join('\n');
|
|
module.cssJs = styles.js.join('\n');
|
|
}
|
|
|
|
module.dependencies.forEach(findModule);
|
|
grunt.config('modules', grunt.config('modules').concat(module));
|
|
}
|
|
|
|
function dependenciesForModule(name)
|
|
{
|
|
let deps = [];
|
|
grunt.file.expand([`src/${name}/*.js`, `!src/${name}/index.js`, `!src/${name}/index-nocss.js`])
|
|
.map(grunt.file.read)
|
|
.forEach(function(contents) {
|
|
//Strategy: find where module is declared,
|
|
//and from there get everything inside the [] and split them by comma
|
|
const moduleDeclIndex = contents.indexOf('angular.module(');
|
|
const depArrayStart = contents.indexOf('[', moduleDeclIndex);
|
|
const depArrayEnd = contents.indexOf(']', depArrayStart);
|
|
const dependencies = contents.substring(depArrayStart + 1, depArrayEnd);
|
|
dependencies.split(',').forEach(function(dep) {
|
|
if(dep.indexOf('ui.bootstrap.') > -1)
|
|
{
|
|
const depName = dep.trim().replace('ui.bootstrap.', '').replace(/['"]/g, '');
|
|
if(deps.indexOf(depName) < 0)
|
|
{
|
|
deps.push(depName);
|
|
//Get dependencies for this new dependency
|
|
deps = deps.concat(dependenciesForModule(depName));
|
|
}
|
|
}
|
|
});
|
|
});
|
|
return deps;
|
|
}
|
|
|
|
grunt.registerTask('dist', 'Override dist directory', function() {
|
|
const dir = this.args[0];
|
|
if(dir)
|
|
{ grunt.config('dist', dir); }
|
|
});
|
|
|
|
grunt.registerTask('build', 'Create bootstrap build files', function() {
|
|
const _ = grunt.util._;
|
|
|
|
//If arguments define what modules to build, build those. Else, everything
|
|
if(this.args.length)
|
|
{
|
|
this.args.forEach(findModule);
|
|
grunt.config('filename', grunt.config('filenamecustom'));
|
|
}
|
|
else
|
|
{
|
|
grunt.file.expand({
|
|
filter: 'isDirectory', cwd: '.'
|
|
}, 'src/*').forEach((dir) => {
|
|
findModule(dir.split('/')[1]);
|
|
});
|
|
}
|
|
|
|
const modules = grunt.config('modules');
|
|
grunt.config('srcModules', _.pluck(modules, 'moduleName'));
|
|
grunt.config('tplModules', _.pluck(modules, 'tplModules').filter((tpls) => tpls.length > 0));
|
|
grunt.config('demoModules', modules
|
|
.filter((module) => module.docs.md && module.docs.js && module.docs.html)
|
|
.sort((a, b) => {
|
|
if(a.name < b.name)
|
|
{ return -1; }
|
|
if(a.name > b.name)
|
|
{ return 1; }
|
|
return 0;
|
|
})
|
|
);
|
|
|
|
const cssStrings = _.flatten(_.compact(_.pluck(modules, 'css')));
|
|
const cssJsStrings = _.flatten(_.compact(_.pluck(modules, 'cssJs')));
|
|
if(cssStrings.length)
|
|
{
|
|
grunt.config('meta.cssInclude', cssJsStrings.join('\n'));
|
|
|
|
grunt.file.write(grunt.config('meta.cssFileDest'), grunt.config('meta.cssFileBanner') +
|
|
cssStrings.join('\n'));
|
|
|
|
grunt.log.writeln('File ' + grunt.config('meta.cssFileDest') + ' created');
|
|
}
|
|
|
|
const moduleFileMapping = _.clone(modules, true);
|
|
moduleFileMapping.forEach((module) => delete module.docs);
|
|
|
|
grunt.config('moduleFileMapping', moduleFileMapping);
|
|
|
|
const srcFiles = _.pluck(modules, 'srcFiles');
|
|
const tpljsFiles = _.pluck(modules, 'tpljsFiles');
|
|
//Set the concat task to concatenate the given src modules
|
|
grunt.config('concat.dist.src', grunt.config('concat.dist.src')
|
|
.concat(srcFiles));
|
|
//Set the concat-with-templates task to concat the given src & tpl modules
|
|
grunt.config('concat.dist_tpls.src', grunt.config('concat.dist_tpls.src')
|
|
.concat(srcFiles).concat(tpljsFiles));
|
|
|
|
grunt.task.run(['concat', 'uglify', 'makeModuleMappingFile', 'makeRawFilesJs', 'makeVersionsMappingFile']);
|
|
});
|
|
|
|
grunt.registerTask('test', 'Run tests on singleRun karma server', function() {
|
|
//this task can be executed in 3 different environments: local, Travis-CI and Jenkins-CI
|
|
//we need to take settings for each one into account
|
|
if(process.env.TRAVIS)
|
|
{
|
|
grunt.task.run('karma:travis');
|
|
}
|
|
else
|
|
{
|
|
const isToRunJenkinsTask = !!this.args.length;
|
|
if(grunt.option('coverage'))
|
|
{
|
|
const karmaOptions = grunt.config.get('karma.options'),
|
|
coverageOpts = grunt.config.get('karma.coverage');
|
|
grunt.util._.extend(karmaOptions, coverageOpts);
|
|
grunt.config.set('karma.options', karmaOptions);
|
|
}
|
|
grunt.task.run(this.args.length ? 'karma:jenkins' : 'karma:continuous');
|
|
}
|
|
});
|
|
|
|
grunt.registerTask('makeModuleMappingFile', function() {
|
|
const _ = grunt.util._;
|
|
const moduleMappingJs = 'dist/assets/module-mapping.json';
|
|
const moduleMappings = grunt.config('moduleFileMapping');
|
|
const moduleMappingsMap = _.object(_.pluck(moduleMappings, 'name'), moduleMappings);
|
|
const jsContent = JSON.stringify(moduleMappingsMap);
|
|
grunt.file.write(moduleMappingJs, jsContent);
|
|
grunt.log.writeln('File ' + moduleMappingJs.cyan + ' created.');
|
|
});
|
|
|
|
grunt.registerTask('makeRawFilesJs', function() {
|
|
const _ = grunt.util._;
|
|
const jsFilename = 'dist/assets/raw-files.json';
|
|
const genRawFilesJs = require('./misc/raw-files-generator');
|
|
|
|
genRawFilesJs(grunt, jsFilename, _.flatten(grunt.config('concat.dist_tpls.src')),
|
|
grunt.config('meta.banner'), grunt.config('meta.cssFileBanner')
|
|
);
|
|
});
|
|
|
|
grunt.registerTask('makeVersionsMappingFile', function() {
|
|
const done = this.async();
|
|
|
|
const exec = require('child_process').exec;
|
|
|
|
grunt.log.writeln(`Mapping file skipped till someone wants to fix.`);
|
|
|
|
return;
|
|
|
|
// const versionsMappingFile = 'dist/versions-mapping.json';
|
|
|
|
// exec('git tag --sort -version:refname', function(error, stdout, stderr) {
|
|
// // Let's remove the oldest 56 versions.
|
|
// const versions = stdout.split('\n').slice(0, -56);
|
|
// let jsContent = versions.map(function(version) {
|
|
// version = version.replace(/^v/, '');
|
|
// return {
|
|
// version: version,
|
|
// url: `/ui-bootstrap4/versioned-docs/${version}/index.html`
|
|
// };
|
|
// });
|
|
// jsContent = _.sortBy(jsContent, 'version').reverse();
|
|
// jsContent.unshift({
|
|
// version: 'Current',
|
|
// url: '/ui-bootstrap4/index.html'
|
|
// });
|
|
// grunt.file.write(versionsMappingFile, JSON.stringify(jsContent));
|
|
// grunt.log.writeln(`File ${versionsMappingFile.cyan} created.`);
|
|
// done();
|
|
// });
|
|
|
|
});
|
|
|
|
/**
|
|
* Logic from AngularJS
|
|
* https://github.com/angular/angular.js/blob/36831eccd1da37c089f2141a2c073a6db69f3e1d/lib/grunt/utils.js#L121-L145
|
|
*/
|
|
function processCSS(moduleName, state, minify, file)
|
|
{
|
|
let css = fs.readFileSync(file).toString(),
|
|
js;
|
|
state.css.push(css);
|
|
|
|
if(minify)
|
|
{
|
|
css = css
|
|
.replace(/\r?\n/g, '')
|
|
.replace(/\/\*.*?\*\//g, '')
|
|
.replace(/:\s+/g, ':')
|
|
.replace(/\s*\{\s*/g, '{')
|
|
.replace(/\s*\}\s*/g, '}')
|
|
.replace(/\s*\,\s*/g, ',')
|
|
.replace(/\s*\;\s*/g, ';');
|
|
}
|
|
//escape for js
|
|
css = css
|
|
.replace(/\\/g, '\\\\')
|
|
.replace(/'/g, "\\'")
|
|
.replace(/\r?\n/g, '\\n');
|
|
js = `angular.module('ui.bootstrap.${moduleName}').run(function() {!angular.$$csp().noInlineStyle && !angular.$$uib${_.capitalize(
|
|
moduleName)}Css && angular.element(document).find('head').prepend('<style type="text/css">${css}</style>'); angular.$$uib${_.capitalize(
|
|
moduleName)}Css = true; });`;
|
|
state.js.push(js);
|
|
|
|
return state;
|
|
}
|
|
|
|
function setVersion(type, suffix)
|
|
{
|
|
const file = 'package.json';
|
|
const VERSION_REGEX = /([\'|\"]version[\'|\"][ ]*:[ ]*[\'|\"])([\d|.]*)(-\w+)*([\'|\"])/;
|
|
let contents = grunt.file.read(file);
|
|
let version;
|
|
contents = contents.replace(VERSION_REGEX, function(match, left, center) {
|
|
version = center;
|
|
if(type)
|
|
{
|
|
version = require('semver').inc(version, type);
|
|
}
|
|
//semver.inc strips our suffix if it existed
|
|
if(suffix)
|
|
{
|
|
version += '-' + suffix;
|
|
}
|
|
return left + version + '"';
|
|
});
|
|
grunt.log.ok('Version set to ' + version.cyan);
|
|
grunt.file.write(file, contents);
|
|
return version;
|
|
}
|
|
|
|
grunt.registerTask('version', 'Set version. If no arguments, it just takes off suffix', function() {
|
|
setVersion(this.args[0], this.args[1]);
|
|
});
|
|
|
|
grunt.registerMultiTask('shell', 'run shell commands', function() {
|
|
const self = this;
|
|
const sh = require('shelljs');
|
|
self.data.forEach(function(cmd) {
|
|
cmd = cmd.replace('%version%', grunt.file.readJSON('package.json').version);
|
|
grunt.log.ok(cmd);
|
|
const result = sh.exec(cmd, { silent: true });
|
|
if(result.code !== 0)
|
|
{
|
|
grunt.fatal(result.output);
|
|
}
|
|
});
|
|
});
|
|
|
|
//------------------------------------------------------------------------------------------------------------------
|
|
// New Release System
|
|
//------------------------------------------------------------------------------------------------------------------
|
|
|
|
grunt.registerTask('release', function(version) {
|
|
// Step 1, we change package.json
|
|
grunt.config.set('pkg.version', version);
|
|
grunt.file.write('./package.json', JSON.stringify(grunt.config('pkg'), null, 2));
|
|
|
|
// Step 2, we queue up additional tasks
|
|
grunt.task.run([
|
|
'conventionalChangelog',
|
|
'html2js',
|
|
'build',
|
|
'copy',
|
|
'shell:release-prepare',
|
|
'shell:release-complete',
|
|
'shell:publish'
|
|
]);
|
|
});
|
|
|
|
//------------------------------------------------------------------------------------------------------------------
|
|
|
|
return grunt;
|
|
};
|