Permalink
Browse files

quick port of grunt for qunit and phantom build

  • Loading branch information...
1 parent 6e8cf9c commit ec4c3a828a93b2ffc43a7794e7df02e0d0fceb33 @johnbender johnbender committed May 23, 2012
Showing with 685 additions and 0 deletions.
  1. +6 −0 .gitignore
  2. +124 −0 build/config.js
  3. +10 −0 build/tasks/clean.js
  4. +116 −0 build/tasks/css.js
  5. +11 −0 build/tasks/custom_init.js
  6. +63 −0 build/tasks/js.js
  7. +59 −0 build/tasks/legacy.js
  8. +119 −0 build/tasks/qunit/phantom.js
  9. +96 −0 build/tasks/qunit/qunit.js
  10. +59 −0 grunt.js
  11. +22 −0 package.json
View
@@ -13,3 +13,9 @@ tmp/
# branch preview
branches
+
+# node build dependencies
+node_modules
+
+# phantom junit output
+build/test-results/
View
@@ -0,0 +1,124 @@
+var fs = require( 'fs' ),
+ path = require( 'path' ),
+ child_process = require( 'child_process' ),
+ glob = require( 'glob-whatev' );
+
+module.exports = function( grunt ) {
+ var global = {
+ dirs : {
+ output: 'compiled',
+ temp: 'tmp'
+ },
+
+ files: {
+ license: 'LICENSE-INFO.txt'
+ },
+
+ names: {
+ base: 'jquery.mobile',
+ // this will change for the deploy target to include version information
+ root: 'jquery.mobile',
+ structure: 'jquery.mobile.structure',
+ theme: 'jquery.mobile.theme'
+ },
+
+ // other version information is added via the asyncConfig helper that
+ // depends on git commands (eg ver.min, ver.header)
+ ver: {
+ official: grunt.file.read( 'version.txt' ).replace(/\n/, ''),
+ min: "/*! jQuery Mobile v<%= build_sha %> jquerymobile.com | jquery.org/license !*/"
+ },
+
+ shas: {},
+
+ helpers: {
+ appendFrom: function( output, input, filter ) {
+ var inputString = fs.readFileSync(input).toString();
+
+ this.append( output, inputString, filter );
+ },
+
+ append: function( output, input, filter ) {
+ var id = fs.openSync(output, 'a+');
+
+ input = filter ? filter(input) : input;
+
+ fs.writeSync( id, input );
+ fs.closeSync( id );
+ },
+
+ minify: function( opts ) {
+ var max = grunt.file.read( opts.input ),
+ min = opts.minCallback(max);
+
+ // add the min header into the minified file, and then the min css
+ grunt.file.write( opts.output, opts.header );
+ this.append( opts.output, min );
+
+ grunt.helper( "min_max_info", min, max );
+ },
+
+ // NOTE cargo culting my way to the top :(
+ rmdirRecursive: function(dir) {
+ if( !path.existsSync(dir) ) {
+ return;
+ }
+
+ var list = fs.readdirSync(dir);
+ for(var i = 0; i < list.length; i++) {
+ var filename = path.join(dir, list[i]);
+ var stat = fs.statSync(filename);
+
+ if(filename == "." || filename == "..") {
+ // pass these files
+ } else if(stat.isDirectory()) {
+ // rmdir recursively
+ this.rmdirRecursive(filename);
+ } else {
+ // rm fiilename
+ fs.unlinkSync(filename);
+ }
+ }
+ fs.rmdirSync(dir);
+ },
+
+ asyncConfig: function( callback ) {
+ child_process.exec( 'git log -1 --format=format:"Git Build: SHA1: %H <> Date: %cd"', function( err, stdout, stderr ){
+ global.shas.build_sha = stdout;
+ global.ver.min = grunt.template.process( global.ver.min, global.shas );
+
+ child_process.exec( 'git log -1 --format=format:"%H"', function( err, stdout, stderr ) {
+ global.shas.head_sha = stdout;
+
+ // NOTE not using a template here because the Makefile depends on the v@VERSION
+ global.ver.header = grunt.file.read( global.files.license )
+ .replace(/v@VERSION/, global.shas.build_sha );
+ callback( global );
+ });
+ });
+ }
+ }
+ };
+
+ grunt.registerTask( 'test_config', 'glob all the test files', function() {
+ var done = this.async(), test_paths, server_paths = [];
+
+ test_paths = glob.glob( 'tests/unit/*/' );
+ test_paths = test_paths.concat( glob.glob('tests/unit/**/*-tests.html') );
+ test_paths.forEach( function( file_path ) {
+ var final_path = process.env.ROOT_DOMAIN + file_path;
+
+ // if no test path is defined or if the path matches that specified in the env
+ // add it to the config
+ if( !process.env.TEST_PATH || file_path.indexOf(process.env.TEST_PATH) >= 0 ) {
+ server_paths.push( final_path );
+ }
+ });
+
+ grunt.config.set( 'qunit', { all: server_paths });
+
+ done();
+ });
+
+ grunt.config.set( 'global', global );
+};
View
@@ -0,0 +1,10 @@
+var fs = require( 'fs' );
+
+module.exports = function( grunt ) {
+ var config = grunt.config.get( 'global' );
+
+ grunt.registerTask( 'clean', 'ensure the output directory is present', function() {
+ config.helpers.rmdirRecursive( config.dirs.output );
+ config.helpers.rmdirRecursive( config.dirs.temp );
+ });
+};
View
@@ -0,0 +1,116 @@
+var requirejs = require( 'requirejs' ),
+ path = require( 'path' ),
+ fs = require( 'fs' ),
+ sqwish = require ( 'sqwish' ),
+ util = require( 'util' );
+
+module.exports = function( grunt ) {
+ var config = grunt.config.get( 'global' ),
+ regularFile = path.join( config.dirs.output, config.names.root ),
+ structureFile = path.join( config.dirs.output, config.names.structure ),
+ themeFile = path.join( config.dirs.output, config.names.theme ),
+ helpers = config.helpers;
+
+ grunt.config.set( 'css', {
+ theme: process.env.THEME || 'default',
+
+ require: {
+ all: {
+ cssIn: 'css/themes/default/jquery.mobile.css',
+ optimizeCss: 'standard.keepComments.keepLines',
+ baseUrl: '.',
+ out: regularFile + '.compiled.css'
+ },
+
+ structure: {
+ cssIn: 'css/structure/jquery.mobile.structure.css',
+ out: structureFile + '.compiled.css'
+ }
+ }
+ });
+
+ grunt.registerTask( 'css_without_deps', 'compile and minify the css', function() {
+ var done = this.async(),
+ theme = grunt.config.get( 'css' ).theme,
+ require = grunt.config.get( 'css' ).require;
+
+ helpers.asyncConfig(function( config ) {
+ // pull the includes together using require js
+ requirejs.optimize( require.all );
+
+ // dump the versioned header into the normal css file
+ grunt.file.write( regularFile + '.css', config.ver.header );
+
+ // add the compiled css to the normal css file
+ helpers.appendFrom( regularFile + '.css', require.all.out );
+
+ helpers.minify({
+ output: regularFile + '.min.css',
+ input: regularFile + '.css',
+ header: config.ver.min,
+ minCallback: function( unminified ) {
+ return sqwish.minify( unminified, false );
+ }
+ });
+
+ // pull the includes together using require js
+ requirejs.optimize( require.structure );
+
+ // dump the versioned header into the structure css file
+ grunt.file.write( structureFile + '.css', config.ver.header );
+
+ // add the compiled css to the normal css file
+ helpers.appendFrom( structureFile + '.css', require.all.out );
+
+ // add the min header into the minified file
+ grunt.file.write( structureFile + '.min.css', config.ver.min );
+
+ // minify the structure css
+ helpers.minify({
+ output: structureFile + '.min.css',
+ input: structureFile + '.css',
+ header: config.ver.min,
+ minCallback: function( unminified ) {
+ return sqwish.minify( unminified, false );
+ }
+ });
+
+ // dump the versioned header into the theme css file
+ grunt.file.write( themeFile + '.css', config.ver.header );
+
+ // dump the theme css into the theme css file
+ helpers.appendFrom( themeFile + '.css', 'css/themes/default/jquery.mobile.theme.css' );
+
+ // minify the theme css
+ helpers.minify({
+ output: themeFile + '.min.css',
+ input: themeFile + '.css',
+ header: config.ver.min,
+ minCallback: function( unminified ) {
+ return sqwish.minify( unminified, false );
+ }
+ });
+
+ // remove the requirejs compile output
+ fs.unlink( require.all.out );
+ fs.unlink( require.structure.out );
+
+ // copy images directory
+ var imagesPath = path.join( config.dirs.output, 'images' ), fileCount = 0;
+
+ grunt.file.mkdir( imagesPath );
+ grunt.file.recurse( path.join('css', 'themes', theme, 'images'), function( full, root, sub, filename ) {
+
+ fileCount++;
+ var is = fs.createReadStream( full );
+ var os = fs.createWriteStream( path.join(imagesPath, filename) );
+ util.pump(is, os, function() {
+ fileCount--;
+ if( fileCount == 0 ) { done(); }
+ });
+ });
+ });
+ });
+
+ grunt.registerTask( 'css', 'custom_init css_without_deps' );
+};
View
@@ -0,0 +1,11 @@
+var fs = require( 'fs' ), path = require( 'path' );
+
+module.exports = function( grunt ) {
+ var config = grunt.config.get( 'global' );
+ // TODO having issues overriding default init task
+ grunt.registerTask( 'custom_init', 'ensure the output directory is present', function() {
+ if( !path.existsSync(config.dirs.output) ) {
+ fs.mkdirSync( config.dirs.output );
+ }
+ });
+};
View
@@ -0,0 +1,63 @@
+var requirejs = require( 'requirejs' ),
+ path = require( 'path' ),
+ fs = require( 'fs' );
+
+module.exports = function( grunt ) {
+ var config = grunt.config.get( 'global' ),
+ outputFile = path.join( config.dirs.output, config.names.root ),
+ helpers = config.helpers;
+
+ grunt.config.set( 'js', {
+ require: {
+ baseUrl: 'js',
+ name: 'jquery.mobile',
+ exclude:[
+ 'jquery',
+ '../external/requirejs/order',
+ '../external/requirejs/depend',
+ '../external/requirejs/text',
+ '../external/requirejs/text!../version.txt'
+ ],
+ out: outputFile + '.compiled.js',
+ pragmasOnSave: { jqmBuildExclude: true },
+ wrap: { startFile: 'build/wrap.start', endFile: 'build/wrap.end' },
+ findNestedDependencies: true,
+ skipModuleInsertion: true,
+ optimize: 'none'
+ }
+ });
+
+ grunt.registerTask( 'js_without_deps', 'compile and minify the js', function() {
+ var done = this.async(), require = grunt.config.get( 'js' ).require;
+
+ helpers.asyncConfig(function( config ) {
+ // pull the includes together using require js
+ requirejs.optimize( require );
+
+ // dump the versioned header into the normal js file
+ grunt.file.write( outputFile + '.js', config.ver.header );
+
+ // add the compiled js to the normal js file, replace the version tag
+ // with the contents from version.txt
+ helpers.appendFrom( outputFile + '.js', require.out, function( fileContents ) {
+ return fileContents.replace( /__version__/, '"' + config.ver.official + '"' );
+ });
+
+ helpers.minify({
+ output: outputFile + '.min.js',
+ input: outputFile + '.js',
+ header: config.ver.min,
+ minCallback: function( unminified ) {
+ return grunt.helper( 'uglify', unminified, {});
+ }
+ });
+
+ // remove the requirejs compile output
+ fs.unlink( require.out );
+ done();
+ });
+ });
+
+ // NOTE custom dasks don't accept dependencies so we alias
+ grunt.registerTask( 'js', 'custom_init js_without_deps' );
+};
Oops, something went wrong.

0 comments on commit ec4c3a8

Please sign in to comment.