diff --git a/.gitignore b/.gitignore index fadcc5fce..ca249a988 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -src/selector-sizzle.js -src/selector.js dist .project .settings diff --git a/Gruntfile.js b/Gruntfile.js index 27ad0f919..8338a015a 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -2,6 +2,9 @@ module.exports = function( grunt ) { "use strict"; + // Integrate build task + require( "./build/build" )( grunt ); + var distpaths = [ "dist/jquery.js", "dist/jquery.min.map", @@ -36,41 +39,19 @@ module.exports = function( grunt ) { cache: "dist/.sizecache.json" } }, - selector: { - destFile: "src/selector-sizzle.js", - apiFile: "src/sizzle-jquery.js", - srcFile: "bower_components/sizzle/dist/sizzle.js" - }, build: { all: { dest: "dist/jquery.js", - src: [ - "src/intro.js", - "src/core.js", - { flag: "sizzle", src: "src/selector-sizzle.js", alt: "src/selector-native.js" }, - "src/callbacks.js", - "src/deferred.js", - "src/support.js", - "src/data.js", - "src/queue.js", - "src/attributes.js", - "src/event.js", - "src/traversing.js", - "src/manipulation.js", - { flag: "wrap", src: "src/wrap.js" }, - { flag: "css", src: "src/css.js" }, - "src/serialize.js", - { flag: "event-alias", src: "src/event-alias.js" }, - { flag: "ajax", src: "src/ajax.js" }, - { flag: "ajax/script", src: "src/ajax/script.js", needs: ["ajax"] }, - { flag: "ajax/jsonp", src: "src/ajax/jsonp.js", needs: [ "ajax", "ajax/script" ] }, - { flag: "ajax/xhr", src: "src/ajax/xhr.js", needs: ["ajax"] }, - { flag: "effects", src: "src/effects.js", needs: ["css"] }, - { flag: "offset", src: "src/offset.js", needs: ["css"] }, - { flag: "dimensions", src: "src/dimensions.js", needs: ["css"] }, - { flag: "deprecated", src: "src/deprecated.js" }, - "src/outro.js" - ] + minimum: [ + "core", + "selector" + ], + // Exclude specified modules if the module matching the key is removed + removeWith: { + callbacks: [ "deferred" ], + css: [ "effects", "dimensions", "offset" ], + sizzle: [ "css/hidden-visible-selectors", "effects/animated-selector" ] + } } }, jsonlint: { @@ -87,7 +68,7 @@ module.exports = function( grunt ) { options: srcHintOptions }, grunt: { - src: [ "Gruntfile.js" ], + src: [ "Gruntfile.js", "build/build.js" ], options: { jshintrc: ".jshintrc" } @@ -140,10 +121,6 @@ module.exports = function( grunt ) { join_vars: false, loops: false, unused: false - }, - mangle: { - // saves some bytes when gzipped - except: [ "undefined" ] } } } @@ -208,252 +185,6 @@ module.exports = function( grunt ) { ); }); - grunt.registerTask( "selector", "Build Sizzle-based selector module", function() { - - var cfg = grunt.config("selector"), - name = cfg.destFile, - sizzle = { - api: grunt.file.read( cfg.apiFile ), - src: grunt.file.read( cfg.srcFile ) - }, - compiled, parts; - - /** - - sizzle-jquery.js -> sizzle between "EXPOSE" blocks, - replace define & window.Sizzle assignment - - - // EXPOSE - if ( typeof define === "function" && define.amd ) { - define(function() { return Sizzle; }); - } else { - window.Sizzle = Sizzle; - } - // EXPOSE - - Becomes... - - Sizzle.attr = jQuery.attr; - jQuery.find = Sizzle; - jQuery.expr = Sizzle.selectors; - jQuery.expr[":"] = jQuery.expr.pseudos; - jQuery.unique = Sizzle.uniqueSort; - jQuery.text = Sizzle.getText; - jQuery.isXMLDoc = Sizzle.isXML; - jQuery.contains = Sizzle.contains; - - */ - - // Break into 3 pieces - parts = sizzle.src.split("// EXPOSE"); - // Replace the if/else block with api - parts[1] = sizzle.api; - // Rejoin the pieces - compiled = parts.join(""); - - grunt.verbose.writeln("Injected " + cfg.apiFile + " into " + cfg.srcFile); - - // Write concatenated source to file, and ensure newline-only termination - grunt.file.write( name, compiled.replace( /\x0d\x0a/g, "\x0a" ) ); - - // Fail task if errors were logged. - if ( this.errorCount ) { - return false; - } - - // Otherwise, print a success message. - grunt.log.writeln( "File '" + name + "' created." ); - }); - - // Special "alias" task to make custom build creation less grawlix-y - grunt.registerTask( "custom", function() { - var done = this.async(), - args = [].slice.call(arguments), - modules = args.length ? args[0].replace(/,/g, ":") : ""; - - - // Translation example - // - // grunt custom:+ajax,-dimensions,-effects,-offset - // - // Becomes: - // - // grunt build:*:*:+ajax:-dimensions:-effects:-offset - - grunt.log.writeln( "Creating custom build...\n" ); - - grunt.util.spawn({ - grunt: true, - args: [ "build:*:*:" + modules, "pre-uglify", "uglify", "dist" ] - }, function( err, result ) { - if ( err ) { - grunt.verbose.error(); - done( err ); - return; - } - - grunt.log.writeln( result.stdout.replace("Done, without errors.", "") ); - - done(); - }); - }); - - // Special concat/build task to handle various jQuery build requirements - grunt.registerMultiTask( - "build", - "Concatenate source (include/exclude modules with +/- flags), embed date/version", - function() { - - // Concat specified files. - var compiled = "", - modules = this.flags, - optIn = !modules["*"], - explicit = optIn || Object.keys(modules).length > 1, - name = this.data.dest, - src = this.data.src, - deps = {}, - excluded = {}, - version = grunt.config( "pkg.version" ), - excluder = function( flag, needsFlag ) { - // optIn defaults implicit behavior to weak exclusion - if ( optIn && !modules[ flag ] && !modules[ "+" + flag ] ) { - excluded[ flag ] = false; - } - - // explicit or inherited strong exclusion - if ( excluded[ needsFlag ] || modules[ "-" + flag ] ) { - excluded[ flag ] = true; - - // explicit inclusion overrides weak exclusion - } else if ( excluded[ needsFlag ] === false && - ( modules[ flag ] || modules[ "+" + flag ] ) ) { - - delete excluded[ needsFlag ]; - - // ...all the way down - if ( deps[ needsFlag ] ) { - deps[ needsFlag ].forEach(function( subDep ) { - modules[ needsFlag ] = true; - excluder( needsFlag, subDep ); - }); - } - } - }; - - // append commit id to version - if ( process.env.COMMIT ) { - version += " " + process.env.COMMIT; - } - - // figure out which files to exclude based on these rules in this order: - // dependency explicit exclude - // > explicit exclude - // > explicit include - // > dependency implicit exclude - // > implicit exclude - // examples: - // * none (implicit exclude) - // *:* all (implicit include) - // *:*:-css all except css and dependents (explicit > implicit) - // *:*:-css:+effects same (excludes effects because explicit include is trumped by explicit exclude of dependency) - // *:+effects none except effects and its dependencies (explicit include trumps implicit exclude of dependency) - src.forEach(function( filepath ) { - var flag = filepath.flag; - - if ( flag ) { - - excluder(flag); - - // check for dependencies - if ( filepath.needs ) { - deps[ flag ] = filepath.needs; - filepath.needs.forEach(function( needsFlag ) { - excluder( flag, needsFlag ); - }); - } - } - }); - - // append excluded modules to version - if ( Object.keys( excluded ).length ) { - version += " -" + Object.keys( excluded ).join( ",-" ); - // set pkg.version to version with excludes, so minified file picks it up - grunt.config.set( "pkg.version", version ); - } - - - // conditionally concatenate source - src.forEach(function( filepath ) { - var flag = filepath.flag, - specified = false, - omit = false, - messages = []; - - if ( flag ) { - if ( excluded[ flag ] !== undefined ) { - messages.push([ - ( "Excluding " + flag ).red, - ( "(" + filepath.src + ")" ).grey - ]); - specified = true; - omit = !filepath.alt; - if ( !omit ) { - flag += " alternate"; - filepath.src = filepath.alt; - } - } - if ( excluded[ flag ] === undefined ) { - messages.push([ - ( "Including " + flag ).green, - ( "(" + filepath.src + ")" ).grey - ]); - - // If this module was actually specified by the - // builder, then set the flag to include it in the - // output list - if ( modules[ "+" + flag ] ) { - specified = true; - } - } - - filepath = filepath.src; - - // Only display the inclusion/exclusion list when handling - // an explicit list. - // - // Additionally, only display modules that have been specified - // by the user - if ( explicit && specified ) { - messages.forEach(function( message ) { - grunt.log.writetableln( [ 27, 30 ], message ); - }); - } - } - - if ( !omit ) { - compiled += grunt.file.read( filepath ); - } - }); - - // Embed Version - // Embed Date - compiled = compiled.replace( /@VERSION/g, version ) - // yyyy-mm-ddThh:mmZ - .replace( /@DATE/g, ( new Date() ).toISOString().replace( /:\d+\.\d+Z$/, "Z" ) ); - - // Write concatenated source to file - grunt.file.write( name, compiled ); - - // Fail task if errors were logged. - if ( this.errorCount ) { - return false; - } - - // Otherwise, print a success message. - grunt.log.writeln( "File '" + name + "' created." ); - }); - // Process files for distribution grunt.registerTask( "dist", function() { var stored, flags, paths, nonascii; @@ -545,7 +276,7 @@ module.exports = function( grunt ) { // Strip banners return contents // Remove the main jQuery banner, it'll be replaced by the new banner anyway. - .replace( /^\/\*!(?:.|\n)*?\*\/\n?/g, "" ) + .replace( /^\/\*![\W\w]*?\*\/\n?/g, "" ) // Strip other banners preserving line count. .replace( /^\/\*!(?:.|\n)*?\*\/\n?/gm, function ( match ) { return match.replace( /[^\n]/gm, "" ); @@ -590,7 +321,7 @@ module.exports = function( grunt ) { grunt.loadNpmTasks("grunt-jsonlint"); // Short list as a high frequency watch task - grunt.registerTask( "dev", [ "selector", "build:*:*", "jshint" ] ); + grunt.registerTask( "dev", [ "build:*:*", "jshint" ] ); // Default grunt grunt.registerTask( "default", [ "jsonlint", "dev", "pre-uglify", "uglify", "post-uglify", "dist:*", "compare_size" ] ); diff --git a/README.md b/README.md index 092db1954..382853366 100644 --- a/README.md +++ b/README.md @@ -67,22 +67,36 @@ The built version of jQuery will be put in the `dist/` subdirectory, along with Special builds can be created that exclude subsets of jQuery functionality. This allows for smaller custom builds when the builder is certain that those parts of jQuery are not being used. -For example, an app that only used JSONP for `$.ajax()` and did not need to calculate offsets or positions of elements could exclude the offset and ajax/xhr modules. The current modules that can be excluded are: +For example, an app that only used JSONP for `$.ajax()` and did not need to calculate offsets or positions of elements could exclude the offset and ajax/xhr modules. + +Any module may be excluded except for `core`, and `selector`. To exclude a module, pass its path relative to the `src` folder (without the `.js` extension). + +Some example modules that can be excluded are: - **ajax**: All AJAX functionality: `$.ajax()`, `$.get()`, `$.post()`, `$.ajaxSetup()`, `.load()`, transports, and ajax event shorthands such as `.ajaxStart()`. - **ajax/xhr**: The XMLHTTPRequest AJAX transport only. - **ajax/script**: The ` - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + +