Skip to content

Commit

Permalink
Build: add combined file with selected widgets & parsers. See Mottie#855
Browse files Browse the repository at this point in the history


NOTE: the core js/jquery.tablesorter.js file is no longer UMD wrapped!; this is done by the build process now

Updated various parser & widget comments
  • Loading branch information
Mottie committed Mar 28, 2015
1 parent bde0a33 commit 263aa97
Show file tree
Hide file tree
Showing 82 changed files with 9,188 additions and 348 deletions.
223 changes: 148 additions & 75 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,47 +24,95 @@ module.exports = function( grunt ) {
'resizable',
'saveSort'
// 'addResizeEvent', // included with stickyHeaders widget
// 'zeba' // included in core
]
// 'zebra' // included in core
],
standardWidgetFileName: 'jquery.tablesorter.widgets.js',
wrappers : {
widgetPrefix: 'js/widgets/widget-',
widgetSuffix: '.js',
parserPrefix: 'js/parsers/parser-',
parserSuffix: '.js'
},
wrapperUMD: {
// tablesorter core
coreBanner: '(function(factory) {\n' +
" if (typeof define === 'function' && define.amd) {\n" +
" define(['jquery'], factory);\n" +
" } else if (typeof module === 'object' && typeof module.exports === 'object') {\n" +
" module.exports = factory(require('jquery'));\n" +
' } else {\n' +
' factory(jQuery);\n' +
' }\n' +
'}(function($) {\n\n',
// widgets wrapper & combined wrapper - may need a separate entry when this wrapper is redefined to make
// widgets a dependency of the core (see https://github.com/Mottie/tablesorter/issues/855)
banner: '<%= pkg.banner %>/* Includes widgets ( <%= pkg.selectedWidgets %> <%= pkg.selectedParsers %>) */\n' +
'(function(factory) {\n' +
" if (typeof define === 'function' && define.amd) {\n" +
" define(['jquery'], factory);\n" +
" } else if (typeof module === 'object' && typeof module.exports === 'object') {\n" +
" module.exports = factory(require('jquery'));\n" +
' } else {\n' +
' factory(jQuery);\n' +
' }\n' +
'}(function($) {\n\n',
footer: '\nreturn $.tablesorter;\n}));\n'
},
noModBanner: '/*** This file is dynamically generated ***\n' +
'█████▄ ▄████▄ █████▄ ▄████▄ ██████ ███████▄ ▄████▄ █████▄ ██ ██████ ██ ██\n' +
'██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██\n' +
'██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██▀▀ ▀▀▀▀██\n' +
'█████▀ ▀████▀ ██ ██ ▀████▀ ██ ██ ██ ██ ▀████▀ █████▀ ██ ██ █████▀\n*/\n'
},

// example widgets = [ 'pager','column', 'filter', 'stickyHeaders' ];
addWidgetDependencies = function(widgets) {
// example widgets = [ 'pager', 'column', 'filter', 'stickyHeaders' ];
addWidgetDependencies = function( widgets ) {
var indx, dep,
maxDeps = 40, // just in case (there are currently 27 widgets)
len = widgets.length,
deps = defaults.dependencies.widgets;
for ( dep in deps ) {
if ( typeof dep === 'string' ) {
for ( indx = 0; indx < len; indx++ ) {
// make sure indexOf is not matching "column" instead of "columnSelector" with surrounding spaces
if ( (' ' + dep + ' ').indexOf(' ' + widgets[indx] + ' ') >= 0 && widgets.indexOf( deps[dep] ) < 0 ) {
widgets.push( deps[dep] );
// keep checking newly added widgets, in case "filter" is added and "storage" hasn't been
if (len < maxDeps) { len++; }
// make sure indexOf is not matching 'column' instead of 'columnSelector' with surrounding spaces
if ( ( ' ' + dep + ' ' ).indexOf( ' ' + widgets[indx] + ' ' ) >= 0 && widgets.indexOf( deps[ dep ] ) < 0 ) {
widgets.push( deps[ dep ] );
// keep checking newly added widgets, in case 'filter' is added and 'storage' hasn't been
if ( len < maxDeps ) { len++; }
continue;
}
}
}
}
return widgets;
},
formFileNames = function(){
formFileNames = function() {
var wrap = defaults.wrappers;
// add widget path & file extension
pkg.processedWidgets = ( widgetFilePrefix +
pkg.selectedWidgets.join( widgetFileSuffix + ',' + widgetFilePrefix ) +
widgetFileSuffix ).split( ',' );
pkg.processedWidgets = ( wrap.widgetPrefix +
pkg.selectedWidgets.join( wrap.widgetSuffix + ',' + wrap.widgetPrefix ) +
wrap.widgetSuffix ).split( ',' );
console.info( 'Creating a widgets file with: ' + pkg.selectedWidgets.join(', ') );

if ( pkg.selectedParsers ) {
// parser path & file extension
pkg.processedParsers = ( wrap.parserPrefix +
pkg.selectedParsers.join( wrap.parserSuffix + ',' + wrap.parserPrefix ) +
wrap.parserSuffix ).split( ',' );
console.info( 'Creating a combined file with selected widgets & these parsers: ' + pkg.selectedParsers.join(', ') );
// make this look nice for the banner
pkg.selectedParsers = ') & parsers ( ' + pkg.selectedParsers + ' ';
}
console.info( pkg.processedParsers );
};

// minified banner template - updated ##/##/20## (v2.##.##)
pkg.banner = '/*! <%= pkg.name %> (FORK) widgets - updated ' +
pkg.banner = '/*! <%= pkg.name %> (FORK) - updated ' +
'<%= grunt.template.today("mm-dd-yyyy") %> (v<%= pkg.version %>)*/\n';

widgetFilePrefix = 'js/widgets/widget-';
widgetFileSuffix = '.js';

pkg.buildWidget = 'jquery.tablesorter.widgets.js';
pkg.buildWidget = defaults.standardWidgetFileName;
pkg.buildCombined = 'jquery.tablesorter.combined.js';
pkg.processedParsers = '!js/parsers/*.js';

// Project configuration.
grunt.initConfig({
Expand All @@ -80,26 +128,16 @@ module.exports = function( grunt ) {
},

copy: {
main: {
expand: true,
src: [
'js/jquery.*.js',
'!js/_test-*.js',
'!js/*.min.js',
],
dest: 'dist/',
filter: 'isFile'
},
css: {
files : [{
expand: true,
dot: true,
flatten: true,
src: ['css/*.css', 'addons/pager/*.css'],
src: [ 'css/*.css', 'addons/pager/*.css' ],
dest: 'dist/css/',
rename: function(dest, src) {
if (/black-ice/.test(src)) {
src = src.replace(/-/, '');
rename: function( dest, src ) {
if ( /black-ice/.test( src ) ) {
src = src.replace( /-/, '' );
}
return dest + src;
}
Expand All @@ -120,19 +158,18 @@ module.exports = function( grunt ) {
},

concat: {
main: {
options: {
banner: defaults.wrapperUMD.coreBanner,
footer: defaults.wrapperUMD.footer
},
src: [ 'js/jquery.tablesorter.js' ],
dest: 'dist/js/jquery.tablesorter.js'
},
widgets: {
options: {
banner: '<%= pkg.banner %>/* Includes: <%= pkg.selectedWidgets %> */\n' +
"(function(factory) {\n" +
" if (typeof define === 'function' && define.amd) {\n" +
" define(['jquery'], factory);\n" +
" } else if (typeof module === 'object' && typeof module.exports === 'object') {\n" +
" module.exports = factory(require('jquery'));\n" +
" } else {\n" +
" factory(jQuery);\n" +
" }\n" +
"}(function($) {\n\n",
footer: "\n\n return $.tablesorter;\n}));\n"
banner: defaults.wrapperUMD.banner,
footer: defaults.wrapperUMD.footer
},
src: [
'<%= pkg.processedWidgets %>',
Expand All @@ -141,43 +178,60 @@ module.exports = function( grunt ) {
],
dest: 'dist/js/<%= pkg.buildWidget %>'
},
everything: {
options: {
banner: defaults.wrapperUMD.banner,
footer: defaults.wrapperUMD.footer
},
src: [
'js/jquery.tablesorter.js',
'<%= pkg.processedWidgets %>',
'<%= pkg.processedParsers %>',
'!js/widgets/_test-*.js',
'!js/widgets/*.min.js'
],
dest: 'dist/js/<%= pkg.buildCombined %>'
},
// keep all the existing jsFiddle demos from breaking
copyback: {
copybackWidgets: {
options: {
banner: '/*** This file is dynamically generated ***\n' +
'█████▄ ▄████▄ █████▄ ▄████▄ ██████ ███████▄ ▄████▄ █████▄ ██ ██████ ██ ██\n' +
'██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██\n' +
'██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██▀▀ ▀▀▀▀██\n' +
'█████▀ ▀████▀ ██ ██ ▀████▀ ██ ██ ██ ██ ▀████▀ █████▀ ██ ██ █████▀\n*/\n'
banner: defaults.noModBanner
},
src : ['dist/js/<%= pkg.buildWidget %>'],
dest: 'js/<%= pkg.buildWidget %>'
},
copybackCombined: {
options: {
banner: defaults.noModBanner
},
src : ['dist/js/<%= pkg.buildCombined %>'],
dest: 'js/<%= pkg.buildCombined %>'
}
},

jshint: {
files: {
src: [
'addons/pager/*.js',
'!addons/pager/*.min.js',
'js/jquery.*.js',
'js/**/*.js',
'!js/_test-*.js',
'!js/**/_test-*.js',
'!js/*.min.js',
'!js/**/semver*.js'
'addons/pager/*.js',
'!addons/pager/*.min.js',
'js/jquery.*.js',
'js/**/*.js',
'!js/_test-*.js',
'!js/**/_test-*.js',
'!js/*.min.js',
'!js/**/semver*.js'
]
},
options: {
globals: {
"localStorage": false,
"navigator": false,
"console": false,
"alert": false
'localStorage': false,
'navigator': false,
'console': false,
'alert': false
},
"loopfunc": true,
"jquery": true,
"browser": true
'loopfunc': true,
'jquery': true,
'browser': true
}
},

Expand All @@ -191,16 +245,28 @@ module.exports = function( grunt ) {
expand: true,
cwd: './js/', // Src matches are relative to this path.
src: [
'*.js',
'**/*.js',
'!jquery.tablesorter.js',
'!_test-*.js',
'!**/_test-*.js',
'!*.min.js',
'!**/semver.js'
],
dest: 'dist/js/',
ext: '.min.js', // Dist files will have this extension.
extDot: 'last' // Extensions in filenames begin after the first dot
extDot: 'last' // Extensions in filenames begin after this dot
}]
},
// jquery.tablesorter.min.js is being minified from js/jquery.tablesorter.js
// so it doesn't include the UMD wrapper! Point to the dist/js/ version
main: {
files : [{
expand: true,
cwd: './dist/js/',
src: [ 'jquery.tablesorter.js' ],
dest: 'dist/js/',
ext: '.min.js', // Dist files will have this extension.
extDot: 'last' // Extensions in filenames begin after this dot
}]
},
pageraddon: {
Expand All @@ -216,7 +282,7 @@ module.exports = function( grunt ) {
expand: true,
flatten: true,
cwd: 'dist/css',
src: ['*.css'],
src: ['*.css', '!_test-*.css'],
dest: 'dist/css',
ext: '.min.css',
extDot: 'last'
Expand Down Expand Up @@ -264,31 +330,37 @@ module.exports = function( grunt ) {
];

// basic = same as before: core, widgets, filterformatter all separate
grunt.registerTask( 'default', 'Default build', function(){
grunt.registerTask( 'default', 'Default build', function() {
pkg.selectedWidgets = addWidgetDependencies( defaults.standardWidgets );
formFileNames();
grunt.task.run(tasks);
});

// enter "grunt custom:{filename}" (not including the ".json")
// enter 'grunt custom:{filename}' (not including the '.json')
// to load in a custom json file
// the expected JSON format is (with custom widgets in a string):
// { "widgets" : "columnHighlight filter resizable saveSort stickyHeaders uitheme" }
grunt.registerTask( 'custom', 'Custom build', function(file){
var temp, widgets, deps = true;
grunt.registerTask( 'custom', 'Custom build', function(file) {
var temp, widgets,
parsers = '',
deps = true;

/* Allow developer to set up a custom widget build (json file will have settings)*/
try {
temp = grunt.file.readJSON( file );
if (temp) {
if ( temp ) {
parsers = temp.parsers;
// include dependencies?
deps = ('includeDependencies' in temp) ? temp.includeDependencies : true;
// custom file name?
pkg.buildWidget = ('destFileName' in temp) ? temp.destFileName : "jquery.tablesorter.custom-widgets.js";
pkg.buildWidget = ('destFileName' in temp) ? temp.destFileName : 'jquery.tablesorter.custom-widgets.js';
// widgets to include
widgets = (temp.widgets || '');
if (widgets.replace(/\s+/g,'') === '') {
grunt.fail.warn('Aborting... No widgets found in custom build file.');
grunt.log.error('No widgets found in custom build file.');
console.info('Continuing build with default widgets...');
temp = defaults.standardWidgets;
pkg.buildWidget = defaults.standardWidgetFileName;
} else {
temp = widgets.split(/\s+/);
}
Expand All @@ -300,6 +372,7 @@ module.exports = function( grunt ) {
}
// add dependencies
pkg.selectedWidgets = deps ? addWidgetDependencies( temp ) : temp;
pkg.selectedParsers = parsers.split( /\s+/ );
formFileNames();
grunt.task.run(tasks);
});
Expand All @@ -311,7 +384,7 @@ module.exports = function( grunt ) {
len = projectFile.length;
for ( i = 0; i < len; i++ ) {
if ( !grunt.file.exists( projectFile[ i ] ) ) {
grunt.log.error( "file " + projectFile[ i ] + " not found" );
grunt.log.error( 'file ' + projectFile[ i ] + ' not found' );
return true; // return false to abort the execution
}
project = grunt.file.readJSON( projectFile[ i ] ); // get file as json object
Expand Down
3 changes: 1 addition & 2 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"jquery": ">=1.2.6"
},
"main": [
"js/jquery.tablesorter.js",
"js/jquery.tablesorter.widgets.js"
"dist/js/jquery.tablesorter.combined.js"
]
}
Loading

0 comments on commit 263aa97

Please sign in to comment.