Files
shiny/tools/Gruntfile.js
2016-10-26 21:01:36 -05:00

252 lines
7.8 KiB
JavaScript

module.exports = function(grunt) {
var instdir = '../inst/';
var js_srcdir = '../srcjs/'
gruntConfig = {
pkg: pkgInfo(),
clean: {
options: { force: true },
src: [
instdir + "www/shared/shiny.js",
instdir + "www/shared/shiny.js.map",
instdir + "www/shared/shiny.min.js",
instdir + "www/shared/shiny.min.js.map",
"./temp_concat/shiny.js",
"./temp_concat/shiny.js.map",
instdir + 'www/shared/datepicker/js/bootstrap-datepicker.min.js',
instdir + 'www/shared/ionrangeslider/js/ion.rangeSlider.min.js'
]
},
concat: {
options: {
process: function(src, filepath) {
return '//---------------------------------------------------------------------\n' +
'// Source file: ' + filepath + '\n\n' + src;
},
sourceMap: true
},
shiny: {
src: [
js_srcdir + '_start.js',
js_srcdir + 'utils.js',
js_srcdir + 'browser.js',
js_srcdir + 'input_rate.js',
js_srcdir + 'shinyapp.js',
js_srcdir + 'notifications.js',
js_srcdir + 'modal.js',
js_srcdir + 'file_processor.js',
js_srcdir + 'binding_registry.js',
js_srcdir + 'output_binding.js',
js_srcdir + 'output_binding_text.js',
js_srcdir + 'output_binding_image.js',
js_srcdir + 'output_binding_html.js',
js_srcdir + 'output_binding_downloadlink.js',
js_srcdir + 'output_binding_datatable.js',
js_srcdir + 'output_binding_adapter.js',
js_srcdir + 'input_binding.js',
js_srcdir + 'input_binding_text.js',
js_srcdir + 'input_binding_textarea.js',
js_srcdir + 'input_binding_password.js',
js_srcdir + 'input_binding_number.js',
js_srcdir + 'input_binding_checkbox.js',
js_srcdir + 'input_binding_slider.js',
js_srcdir + 'input_binding_date.js',
js_srcdir + 'input_binding_daterange.js',
js_srcdir + 'input_binding_select.js',
js_srcdir + 'input_binding_radio.js',
js_srcdir + 'input_binding_checkboxgroup.js',
js_srcdir + 'input_binding_actionbutton.js',
js_srcdir + 'input_binding_tabinput.js',
js_srcdir + 'input_binding_fileinput.js',
js_srcdir + 'init_shiny.js',
js_srcdir + 'reactlog.js',
js_srcdir + '_end.js'
],
// The temp_concat/ directory would have gone under /srcjs/, but the
// Babel Grunt plugin has trouble finding presets if it operates on a
// file that's not under the current directory. So we'll put it under
// ./
dest: './temp_concat/shiny.js',
nonull: true
},
},
babel: {
options: {
sourceMap: true,
compact: false,
presets: ['es2015']
},
shiny: {
src: './temp_concat/shiny.js',
dest: instdir + '/www/shared/shiny.js'
}
},
eslint: {
options: {
parser: 'babel-eslint',
format: require('eslint-stylish-mapped'),
extends: 'eslint:recommended',
rules: {
"consistent-return": 1,
"dot-location": [1, "property"],
"eqeqeq": 1,
// "no-shadow": 1,
"no-undef": 1,
"no-unused-vars": [1, {"args": "none"}],
// "no-use-before-define": [1, {"functions": false}],
"semi": [1, "always"]
},
envs: [
"es6",
"browser",
"jquery"
],
globals: ["strftime"]
},
shiny: ['./temp_concat/shiny.js']
},
uglify: {
shiny: {
options: {
banner: '/*! <%= pkg.name %> <%= pkg.version %> | ' +
'(c) 2012-<%= grunt.template.today("yyyy") %> RStudio, Inc. | ' +
'License: <%= pkg.license %> */\n',
sourceMap: true,
// Base the .min.js sourcemap off of the .js sourcemap created by concat
sourceMapIn: instdir + 'www/shared/shiny.js.map',
sourceMapIncludeSources: true
},
src: instdir + 'www/shared/shiny.js',
dest: instdir + 'www/shared/shiny.min.js'
},
datepicker: {
src: [
instdir + 'www/shared/datepicker/js/bootstrap-datepicker.js',
instdir + 'www/shared/datepicker/js/locales/bootstrap-datepicker.*.js'
],
dest: instdir + 'www/shared/datepicker/js/bootstrap-datepicker.min.js'
},
ionrangeslider: {
src: instdir + 'www/shared/ionrangeslider/js/ion.rangeSlider.js',
dest: instdir + 'www/shared/ionrangeslider/js/ion.rangeSlider.min.js'
}
},
copy: {
babelPolyfill: {
src: "node_modules/babel-polyfill/dist/polyfill.min.js",
dest: "../inst/www/shared/babel-polyfill.min.js"
}
},
watch: {
shiny: {
files: ['<%= concat.shiny.src %>', '../DESCRIPTION'],
tasks: [
'newer:concat',
'newer:eslint',
'configureBabel',
'newer:babel',
'newer:uglify'
]
},
babelPolyfill: {
files: '<%= copy.babelPolyfill.src %>',
tasks: ['newer:copy:babelPolyfill']
},
datepicker: {
files: '<%= uglify.datepicker.src %>',
tasks: ['newer:uglify:datepicker']
}
},
newer: {
options: {
override: function(detail, include) {
// If DESCRIPTION is updated, we'll also need to re-minify shiny.js
// because the min.js file embeds the version number.
if (detail.task === 'uglify' && detail.target === 'shiny') {
include(isNewer('../DESCRIPTION', detail.time));
} else {
include(false);
}
}
}
}
};
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-babel');
grunt.loadNpmTasks('grunt-eslint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-newer');
// Need this here so that babel reads in the source map file after it's
// generated. Without this task, it would read in the source map when Grunt
// runs, which is wrong, if the source map doesn't exist, or is change later.
grunt.task.registerTask("configureBabel", "configures babel options", function() {
gruntConfig.babel.options.inputSourceMap = grunt.file.readJSON('./temp_concat/shiny.js.map');
});
grunt.initConfig(gruntConfig);
grunt.registerTask('default', [
'newer:concat',
'newer:eslint',
'configureBabel',
'newer:babel',
'newer:uglify',
'newer:copy'
]);
// ---------------------------------------------------------------------------
// Utility functions
// ---------------------------------------------------------------------------
// Return an object which merges information from package.json and the
// DESCRIPTION file.
function pkgInfo() {
var pkg = grunt.file.readJSON('package.json');
pkg.name = descKeyValue('Package');
pkg.version = descKeyValue('Version');
pkg.license = descKeyValue('License');
return pkg;
}
// From the DESCRIPTION file, get the value of a key. This presently only
// works if the value is on one line, the same line as the key.
function descKeyValue(key) {
var lines = require('fs').readFileSync('../DESCRIPTION', 'utf8').split('\n');
var pattern = new RegExp('^' + key + ':');
var txt = lines.filter(function(line) {
return pattern.test(line);
});
txt = txt[0];
pattern = new RegExp(key + ': *');
txt = txt.replace(pattern, '');
return txt;
}
// Return true if file's mtime is newer than mtime; false otherwise.
function isNewer(file, mtime) {
return require('fs').statSync(file).mtime > mtime;
}
};