123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493 |
- /* jshint node: true */
- var markdown = require('node-markdown').Markdown;
- var fs = require('fs');
- module.exports = function(grunt) {
- grunt.loadNpmTasks('grunt-contrib-watch');
- grunt.loadNpmTasks('grunt-contrib-concat');
- grunt.loadNpmTasks('grunt-contrib-copy');
- grunt.loadNpmTasks('grunt-contrib-jshint');
- grunt.loadNpmTasks('grunt-contrib-uglify');
- grunt.loadNpmTasks('grunt-html2js');
- grunt.loadNpmTasks('grunt-karma');
- grunt.loadNpmTasks('grunt-conventional-changelog');
- grunt.loadNpmTasks('grunt-ddescribe-iit');
- // Project configuration.
- grunt.util.linefeed = '\n';
- grunt.initConfig({
- ngversion: '1.4.7',
- bsversion: '3.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 %>',
- ' */\n'].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'],
- //we don't need to jshint here, it slows down everything else
- 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/'
- }]
- }
- },
- 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: '.'
- },
- files: [{
- expand: true,
- src: ['template/**/*.html'],
- ext: '.html.js'
- }]
- }
- },
- jshint: {
- files: ['Gruntfile.js','src/**/*.js'],
- options: {
- jshintrc: '.jshintrc'
- }
- },
- 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 evluate it at run-time, because <%= pkg.version %>
- //is only evaluated once
- 'release-prepare': [
- 'grunt before-test after-test',
- 'grunt version', //remove "-SNAPSHOT"
- 'grunt conventionalChangelog'
- ],
- 'release-complete': [
- 'git commit CHANGELOG.md package.json -m "chore(release): v%version%"',
- 'git tag %version%'
- ],
- 'release-start': [
- 'grunt version:minor:"SNAPSHOT"',
- 'git commit package.json -m "chore(release): Starting v%version%"'
- ]
- },
- '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', ['enforce', 'ddescribe-iit', 'jshint', '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']);
- grunt.registerTask('enforce', 'Install commit message enforce script if it doesn\'t exist', function() {
- if (!grunt.file.exists('.git/hooks/commit-msg')) {
- grunt.file.copy('misc/validate-commit-msg.js', '.git/hooks/commit-msg');
- require('fs').chmodSync('.git/hooks/commit-msg', '0755');
- }
- });
- //Common ui.bootstrap module containing all modules for src and templates
- //findModule: Adds a given module to config
- var 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 + '"';
- }
- var module = {
- name: name,
- moduleName: enquote('ui.bootstrap.' + name),
- displayName: ucwords(breakup(name, ' ')),
- srcFiles: grunt.file.expand('src/'+name+'/*.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(enquote),
- dependencies: dependenciesForModule(name),
- docs: {
- md: grunt.file.expand('src/'+name+'/docs/*.md')
- .map(grunt.file.read).map(markdown).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')
- }
- };
- var styles = {
- css: [],
- js: []
- };
- module.cssFiles.forEach(processCSS.bind(null, 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) {
- var deps = [];
- grunt.file.expand('src/' + name + '/*.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
- var moduleDeclIndex = contents.indexOf('angular.module(');
- var depArrayStart = contents.indexOf('[', moduleDeclIndex);
- var depArrayEnd = contents.indexOf(']', depArrayStart);
- var dependencies = contents.substring(depArrayStart + 1, depArrayEnd);
- dependencies.split(',').forEach(function(dep) {
- if (dep.indexOf('ui.bootstrap.') > -1) {
- var 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() {
- var dir = this.args[0];
- if (dir) { grunt.config('dist', dir); }
- });
- grunt.registerTask('build', 'Create bootstrap build files', function() {
- var _ = 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(function(dir) {
- findModule(dir.split('/')[1]);
- });
- }
- var modules = grunt.config('modules');
- grunt.config('srcModules', _.pluck(modules, 'moduleName'));
- grunt.config('tplModules', _.pluck(modules, 'tplModules').filter(function(tpls) { return tpls.length > 0;} ));
- grunt.config('demoModules', modules
- .filter(function(module) {
- return module.docs.md && module.docs.js && module.docs.html;
- })
- .sort(function(a, b) {
- if (a.name < b.name) { return -1; }
- if (a.name > b.name) { return 1; }
- return 0;
- })
- );
- var cssStrings = _.flatten(_.compact(_.pluck(modules, 'css')));
- var 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');
- }
- var moduleFileMapping = _.clone(modules, true);
- moduleFileMapping.forEach(function (module) {
- delete module.docs;
- });
- grunt.config('moduleFileMapping', moduleFileMapping);
- var srcFiles = _.pluck(modules, 'srcFiles');
- var 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 {
- var isToRunJenkinsTask = !!this.args.length;
- if(grunt.option('coverage')) {
- var 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 () {
- var _ = grunt.util._;
- var moduleMappingJs = 'dist/assets/module-mapping.json';
- var moduleMappings = grunt.config('moduleFileMapping');
- var moduleMappingsMap = _.object(_.pluck(moduleMappings, 'name'), moduleMappings);
- var jsContent = JSON.stringify(moduleMappingsMap);
- grunt.file.write(moduleMappingJs, jsContent);
- grunt.log.writeln('File ' + moduleMappingJs.cyan + ' created.');
- });
- grunt.registerTask('makeRawFilesJs', function () {
- var _ = grunt.util._;
- var jsFilename = 'dist/assets/raw-files.json';
- var 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 () {
- var done = this.async();
- var exec = require('child_process').exec;
- var versionsMappingFile = 'dist/versions-mapping.json';
- exec('git tag --sort -version:refname', function(error, stdout, stderr) {
- // Let's remove the oldest 14 versions.
- var versions = stdout.split('\n').slice(0, -14);
- var jsContent = versions.map(function(version) {
- return {
- version: version,
- url: '/bootstrap/versioned-docs/' + version
- };
- });
- jsContent[0] = {
- version: 'Current',
- url: '/bootstrap'
- };
- 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(state, minify, file) {
- /* jshint quotmark: false */
- var 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.$$csp() && angular.element(document).find('head').prepend('<style type=\"text/css\">" + css + "</style>');";
- state.js.push(js);
- return state;
- }
- function setVersion(type, suffix) {
- var file = 'package.json';
- var VERSION_REGEX = /([\'|\"]version[\'|\"][ ]*:[ ]*[\'|\"])([\d|.]*)(-\w+)*([\'|\"])/;
- var contents = grunt.file.read(file);
- var 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() {
- var self = this;
- var sh = require('shelljs');
- self.data.forEach(function(cmd) {
- cmd = cmd.replace('%version%', grunt.file.readJSON('package.json').version);
- grunt.log.ok(cmd);
- var result = sh.exec(cmd,{silent:true});
- if (result.code !== 0) {
- grunt.fatal(result.output);
- }
- });
- });
- return grunt;
- };
|