diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..b5bd7f60 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +# This file is for unifying the coding style for different editors and IDEs +# editorconfig.org + +root = true + +[*] +indent_style = tab +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[package.json] +indent_style = space +indent_size = 2 + diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 00000000..85ed8857 --- /dev/null +++ b/.jscsrc @@ -0,0 +1,5 @@ +"preset": "jquery" +"requireCamelCaseOrUpperCaseIdentifiers": { + "ignoreProperties": true +} +"excludeFiles": [ "external", "src/intro.js", "src/outro.js", "node_modules" ] diff --git a/.travis.yml b/.travis.yml index e34e2f36..df2b62dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,4 +2,4 @@ language: node_js sudo: false node_js: - "5" -before_install: npm install -g grunt-cli +script: "npm run ci" diff --git a/Gruntfile.js b/Gruntfile.js index e4264b2a..1c7b31e4 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,5 +1,5 @@ /*global module:false*/ -module.exports = function(grunt) { +module.exports = function( grunt ) { "use strict"; @@ -8,15 +8,15 @@ module.exports = function(grunt) { var data = {}; try { data = grunt.file.readJSON( filepath ); - } catch(e) {} + } catch ( e ) {} return data; }, - srcHintOptions = readOptionalJSON("src/.jshintrc"); + srcHintOptions = readOptionalJSON( "src/.jshintrc" ); delete srcHintOptions.onevar; // Project configuration. - grunt.initConfig({ - pkg: grunt.file.readJSON("package.json"), + grunt.initConfig( { + pkg: grunt.file.readJSON( "package.json" ), files: [ "src/intro.js", "src/version.js", @@ -63,11 +63,28 @@ module.exports = function(grunt) { instrumentedFiles: "temp/", src: [ "dist/jquery-migrate.js" ], htmlReport: "coverage/", + lcovReport: "coverage/", linesThresholdPct: 85 } }, files: [ "test/**/*.html" ] }, + coveralls: { + src: "coverage/lcov.info", + options: { + + // Should not fail if coveralls is down + force: true + } + }, + jscs: { + src: [ + "test/**/*.js", + "<%= files %>", + "Gruntfile.js", + "build/**/*.js" + ] + }, npmcopy: { all: { options: { @@ -77,7 +94,7 @@ module.exports = function(grunt) { "phantomjs-polyfill/bind-polyfill.js": "phantomjs-polyfill/bind-polyfill.js", "qunit/qunit.js": "qunitjs/qunit/qunit.js", "qunit/qunit.css": "qunitjs/qunit/qunit.css", - "qunit/LICENSE.txt": "qunitjs/LICENSE.txt" } + "qunit/LICENSE.txt": "qunitjs/LICENSE.txt" } } }, jshint: { @@ -105,7 +122,8 @@ module.exports = function(grunt) { } }, options: { - banner: "/*! jQuery Migrate v<%= pkg.version %> | (c) <%= pkg.author.name %> | jquery.org/license */\n", + banner: "/*! jQuery Migrate v<%= pkg.version %>" + + " | (c) <%= pkg.author.name %> | jquery.org/license */\n", beautify: { ascii_only: true } @@ -113,77 +131,32 @@ module.exports = function(grunt) { }, watch: { files: [ "src/*.js", "test/*.js" ], - tasks: [ "buildnounit" ] - }, - }); + tasks: [ "build" ] + } + } ); // Load grunt tasks from NPM packages - grunt.loadNpmTasks("grunt-git-authors"); - grunt.loadNpmTasks("grunt-contrib-concat"); - grunt.loadNpmTasks("grunt-contrib-watch"); - grunt.loadNpmTasks("grunt-contrib-jshint"); - grunt.loadNpmTasks("grunt-contrib-uglify"); - grunt.loadNpmTasks("grunt-qunit-istanbul"); - grunt.loadNpmTasks("grunt-npmcopy"); - - // Default task. - grunt.registerTask( "default", [ "concat", "uglify", "jshint", "qunit" ] ); + grunt.loadNpmTasks( "grunt-git-authors" ); + grunt.loadNpmTasks( "grunt-contrib-concat" ); + grunt.loadNpmTasks( "grunt-contrib-watch" ); + grunt.loadNpmTasks( "grunt-contrib-jshint" ); + grunt.loadNpmTasks( "grunt-jscs" ); + grunt.loadNpmTasks( "grunt-contrib-uglify" ); + grunt.loadNpmTasks( "grunt-qunit-istanbul" ); + grunt.loadNpmTasks( "grunt-coveralls" ); + grunt.loadNpmTasks( "grunt-npmcopy" ); - // Skip unit tests, used by testswarm - grunt.registerTask( "buildnounit", [ "concat", "uglify", "jshint" ] ); + // Integrate jQuery migrate specific tasks + grunt.loadTasks( "build/tasks" ); - // Testswarm - grunt.registerTask( "testswarm", function( commit, configFile, destName ) { - var jobName, - testswarm = require( "testswarm" ), - runs = {}, - done = this.async(), - pull = /PR-(\d+)/.exec( commit ), - config = grunt.file.readJSON( configFile ).jquerymigrate, - tests = grunt.config( "tests" )[ destName ], - browserSets = destName || config.browserSets; + // Just an alias + grunt.registerTask( "test", [ "qunit" ] ); - if ( browserSets[ 0 ] === "[" ) { - // We got an array, parse it - browserSets = JSON.parse( browserSets ); - } + grunt.registerTask( "lint", [ "jshint", "jscs" ] ); + grunt.registerTask( "build", [ "concat", "uglify", "lint" ] ); - if ( pull ) { - jobName = "Pull #" + pull[ 1 ] + ""; - } else { - jobName = "Commit " + commit.substr( 0, 10 ) + ""; - } + grunt.registerTask( "default", [ "build", "test" ] ); - tests.forEach(function( test ) { - var plugin_jquery = test.split("+"); - runs[test] = config.testUrl + commit + "/test/index.html?plugin=" + - plugin_jquery[0] + "&jquery=" + plugin_jquery[1]; - }); - - // TODO: create separate job for git so we can do different browsersets - testswarm.createClient( { - url: config.swarmUrl - } ) - .addReporter( testswarm.reporters.cli ) - .auth( { - id: config.authUsername, - token: config.authToken - }) - .addjob( - { - name: jobName, - runs: runs, - runMax: config.runMax, - browserSets: browserSets, - timeout: 1000 * 60 * 30 - }, function( err, passed ) { - if ( err ) { - grunt.log.error( err ); - } - done( passed ); - } - ); - }); + // For CI + grunt.registerTask( "ci", [ "build", "test", "coveralls" ] ); }; diff --git a/README.md b/README.md index ea1a7ef6..92d6b8d1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ -# jquery-migrate: Migrate older jQuery code to jQuery 1.9+ +[![Build Status](https://travis-ci.org/jquery/jquery-migrate.svg?branch=master)](https://travis-ci.org/jquery/jquery-migrate) +[![Coverage Status](https://img.shields.io/coveralls/jquery/jquery-migrate.svg?style=flat)](https://coveralls.io/r/jquery/jquery-migrate?branch=master) + +# Migrate older jQuery code to jQuery 1.9+ This plugin can be used to detect and restore APIs or features that have been deprecated in jQuery and removed as of version 1.9. See the [warnings page](https://github.com/jquery/jquery-migrate/blob/master/warnings.md) for more information regarding messages the plugin generates. @@ -65,19 +68,35 @@ Bugs in jQuery itself should be reported on the [jQuery Core bug tracker](http:/ For other questions about the plugin that aren't bugs, ask on the [jQuery Forum](http://forum.jquery.com). -How to run the tests: +Build and run tests: ==================================================== -Clone this repo, install `grunt`: + +## Build with `npm` commands +```sh +$ git clone git://github.com/jquery/jquery-migrate.git +$ cd jquery-migrate +$ npm install +$ npm run build +``` + +## Build with [`grunt`](http://gruntjs.com/) + +```sh +$ git clone git://github.com/jquery/jquery-migrate.git +$ cd jquery-migrate +$ npm install +$ npm install -g grunt-cli +$ grunt build +``` + +### Run tests ```sh -git clone git://github.com/jquery/jquery-migrate.git -cd jquery-migrate -npm install -npm install -g grunt-cli +$ npm test ``` -Run `grunt` to `jshint`, `qunit` and `uglify` release. +### Or ```sh -grunt +$ grunt test ``` diff --git a/build/release.js b/build/release.js index 567b6871..f8fbfcb4 100644 --- a/build/release.js +++ b/build/release.js @@ -1,6 +1,6 @@ #!/usr/bin/env node /* - * jQuery Migrate Plugin Release Management + * JQuery Migrate Plugin Release Management */ // Debugging variables @@ -46,7 +46,8 @@ steps( tagReleaseVersion, gruntBuild, makeReleaseCopies, - // uploadToCDN, + + // UploadToCDN, publishToNPM, setNextVersion, pushToRemote, @@ -56,19 +57,19 @@ steps( function initialize( next ) { // -d dryrun mode, no commands are executed at all - if ( process.argv[2] === "-d" ) { + if ( process.argv[ 2 ] === "-d" ) { process.argv.shift(); dryrun = true; - console.warn("=== DRY RUN MODE ===" ); + console.warn( "=== DRY RUN MODE ===" ); } // -r skip remote mode, no remote commands are executed // (git push, npm publish, cdn copy) // Reset with `git reset --hard HEAD~2 && git tag -d (version) && grunt` - if ( process.argv[2] === "-r" ) { + if ( process.argv[ 2 ] === "-r" ) { process.argv.shift(); skipRemote = true; - console.warn("=== SKIPREMOTE MODE ===" ); + console.warn( "=== SKIPREMOTE MODE ===" ); } // First arg should be the version number being released; this is a proper subset @@ -76,14 +77,13 @@ function initialize( next ) { // Examples: 1.0.1, 1.0.1-pre, 1.0.1-rc1, 1.0.1-rc1.1 var newver, oldver, rsemver = /^(\d+)\.(\d+)\.(\d+)(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?$/, - version = rsemver.exec( process.argv[2] || "" ) || [], - major = version[1], - minor = version[2], - patch = version[3], - xbeta = version[4]; - + version = rsemver.exec( process.argv[ 2 ] || "" ) || [], + major = version[ 1 ], + minor = version[ 2 ], + patch = version[ 3 ], + xbeta = version[ 4 ]; - releaseVersion = process.argv[2]; + releaseVersion = process.argv[ 2 ]; isBeta = !!xbeta; if ( !releaseVersion ) { @@ -95,14 +95,14 @@ function initialize( next ) { if ( xbeta === "pre" ) { die( "Cannot release a 'pre' version!" ); } - if ( !(fs.existsSync || path.existsSync)( packageFile ) ) { + if ( !( fs.existsSync || path.existsSync )( packageFile ) ) { die( "No " + packageFile + " in this directory" ); } pkg = JSON.parse( fs.readFileSync( packageFile ) ); status( "Current version is " + pkg.version + "; generating release " + releaseVersion ); version = rsemver.exec( pkg.version ); - oldver = ( +version[1] ) * 10000 + ( +version[2] * 100 ) + ( +version[3] ) + oldver = ( +version[ 1 ] ) * 10000 + ( +version[ 2 ] * 100 ) + ( +version[ 3 ] ); newver = ( +major ) * 10000 + ( +minor * 100 ) + ( +patch ); if ( newver < oldver ) { die( "Next version is older than current version!" ); @@ -119,24 +119,24 @@ function initialize( next ) { function checkGitStatus( next ) { child.execFile( "git", [ "status" ], function( error, stdout, stderr ) { - var onBranch = ((stdout||"").match( /On branch (\S+)/ ) || [])[1]; + var onBranch = ( ( stdout || "" ).match( /On branch (\S+)/ ) || [] )[ 1 ]; if ( onBranch !== branch ) { die( "Branches don't match: Wanted " + branch + ", got " + onBranch ); } if ( /Changes to be committed/i.test( stdout ) ) { - die("Please commit changed files before attemping to push a release."); + die( "Please commit changed files before attemping to push a release." ); } if ( /Changes not staged for commit/i.test( stdout ) ) { - die("Please stash files before attempting to push a release."); + die( "Please stash files before attempting to push a release." ); } next(); - }); + } ); } function tagReleaseVersion( next ) { - git( [ "commit", "-a", "-m", "Tagging the " + releaseVersion + " release." ], function(){ - git( [ "tag", releaseVersion ], next); - }); + git( [ "commit", "-a", "-m", "Tagging the " + releaseVersion + " release." ], function() { + git( [ "tag", releaseVersion ], next ); + } ); } function updateVersions( next ) { @@ -153,18 +153,18 @@ function gruntBuild( next ) { } log( stdout || "(no output)" ); next(); - }); + } ); } function makeReleaseCopies( next ) { finalFiles = {}; - Object.keys( releaseFiles ).forEach(function( key ) { + Object.keys( releaseFiles ).forEach( function( key ) { var builtFile = releaseFiles[ key ], releaseFile = key.replace( /VER/g, releaseVersion ); copy( builtFile, releaseFile ); finalFiles[ releaseFile ] = builtFile; - }); + } ); next(); } @@ -187,18 +187,18 @@ function setNextVersion( next ) { function uploadToCDN( next ) { var cmds = []; - Object.keys( finalFiles ).forEach(function( name ) { + Object.keys( finalFiles ).forEach( function( name ) { cmds.push( - function( nxt ){ + function( nxt ) { exec( "scp", [ name, scpURL ], nxt, skipRemote ); }, - function( nxt ){ + function( nxt ) { exec( "curl", [ cdnURL + name + "?reload" ], nxt, skipRemote ); } ); - }); + } ); cmds.push( next ); - + steps.apply( this, cmds ); } @@ -211,11 +211,11 @@ function pushToRemote( next ) { function steps() { var cur = 0, steps = arguments; - (function next(){ - process.nextTick(function(){ + ( function next() { + process.nextTick( function() { steps[ cur++ ]( next ); - }); - })(); + } ); + } )(); } function updatePackageVersion( ver, blobVer ) { @@ -223,7 +223,7 @@ function updatePackageVersion( ver, blobVer ) { blobVer = blobVer || ver; pkg.version = ver; pkg.author.url = setBlobVersion( pkg.author.url, blobVer ); - pkg.licenses[0].url = setBlobVersion( pkg.licenses[0].url, blobVer ); + pkg.licenses[ 0 ].url = setBlobVersion( pkg.licenses[ 0 ].url, blobVer ); writeJsonSync( packageFile, pkg ); } @@ -278,11 +278,11 @@ function git( args, fn, skip ) { function exec( cmd, args, fn, skip ) { if ( dryrun || skip ) { - log( chalk.black.bgBlue( "# " + cmd + " " + args.join(" ") ) ); + log( chalk.black.bgBlue( "# " + cmd + " " + args.join( " " ) ) ); fn(); } else { - log( chalk.green( cmd + " " + args.join(" ") ) ); - child.execFile( cmd, args, { env: process.env }, + log( chalk.green( cmd + " " + args.join( " " ) ) ); + child.execFile( cmd, args, { env: process.env }, function( err, stdout, stderr ) { if ( err ) { die( stderr || stdout || err ); diff --git a/build/tasks/testswarm.js b/build/tasks/testswarm.js new file mode 100644 index 00000000..8a7380c6 --- /dev/null +++ b/build/tasks/testswarm.js @@ -0,0 +1,58 @@ +"use strict"; + +module.exports = function( grunt ) { + grunt.registerTask( "testswarm", function( commit, configFile, destName ) { + var jobName, + testswarm = require( "testswarm" ), + runs = {}, + done = this.async(), + pull = /PR-(\d+)/.exec( commit ), + config = grunt.file.readJSON( configFile ).jquerymigrate, + tests = grunt.config( "tests" )[ destName ], + browserSets = destName || config.browserSets; + + if ( browserSets[ 0 ] === "[" ) { + + // We got an array, parse it + browserSets = JSON.parse( browserSets ); + } + + if ( pull ) { + jobName = "Pull #" + pull[ 1 ] + ""; + } else { + jobName = "Commit " + commit.substr( 0, 10 ) + ""; + } + + tests.forEach( function( test ) { + var pluginjQuery = test.split( "+" ); + runs[ test ] = config.testUrl + commit + "/test/index.html?plugin=" + + pluginjQuery[ 0 ] + "&jquery=" + pluginjQuery[ 1 ]; + } ); + + // TODO: create separate job for git so we can do different browsersets + testswarm.createClient( { + url: config.swarmUrl + } ) + .addReporter( testswarm.reporters.cli ) + .auth( { + id: config.authUsername, + token: config.authToken + } ) + .addjob( + { + name: jobName, + runs: runs, + runMax: config.runMax, + browserSets: browserSets, + timeout: 1000 * 60 * 30 + }, function( err, passed ) { + if ( err ) { + grunt.log.error( err ); + } + done( passed ); + } + ); + } ); +}; diff --git a/package.json b/package.json index 112b15c5..61697a4b 100644 --- a/package.json +++ b/package.json @@ -18,21 +18,60 @@ }, "license": "MIT", "scripts": { - "test": "grunt" + "build": "grunt build", + "test": "grunt test", + "ci": "grunt ci" }, "devDependencies": { "chalk": "1.1.1", + "commitplease": "^2.3.0", "grunt": "~0.4.5", + "grunt-cli": "^0.1.13", "grunt-contrib-concat": "0.5.1", "grunt-contrib-jshint": "0.11.0", "grunt-contrib-uglify": "0.8.0", "grunt-contrib-watch": "0.6.1", + "grunt-coveralls": "^1.0.0", "grunt-git-authors": "3.0.0", + "grunt-jscs": "^2.7.0", "grunt-npmcopy": "0.1.0", "grunt-qunit-istanbul": "0.6.0", "jquery": "^2.1.3", + "phantomjs-polyfill": "0.0.1", "qunitjs": "1.17.1", "testswarm": "~1.1.0" }, - "keywords": [] + "keywords": [ + "jquery", + "javascript", + "browser", + "plugin", + "migrate" + ], + "commitplease": { + "components": [ + "Docs", + "Tests", + "Build", + "Release", + "Core", + "Ajax", + "Attributes", + "Callbacks", + "CSS", + "Data", + "Deferred", + "Deprecated", + "Dimensions", + "Effects", + "Event", + "Manipulation", + "Offset", + "Queue", + "Selector", + "Serialize", + "Traversing", + "Wrap" + ] + } } diff --git a/src/ajax.js b/src/ajax.js index 11c54ad4..c9ec6b2c 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -1,7 +1,7 @@ // Ensure that $.ajax gets the new parseJSON defined in core.js -jQuery.ajaxSetup({ +jQuery.ajaxSetup( { converters: { "text json": jQuery.parseJSON } -}); +} ); diff --git a/src/attributes.js b/src/attributes.js index d4ba356f..9cb5c10e 100644 --- a/src/attributes.js +++ b/src/attributes.js @@ -1,5 +1,5 @@ -var attrFn = jQuery( "", { size: 1 } ).attr("size") && jQuery.attrFn, +var attrFn = jQuery( "", { size: 1 } ).attr( "size" ) && jQuery.attrFn, oldAttr = jQuery.attr, valueAttrGet = jQuery.attrHooks.value && jQuery.attrHooks.value.get || function() { return null; }, @@ -10,7 +10,7 @@ var attrFn = jQuery( "", { size: 1 } ).attr("size") && jQuery.attrFn, rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, ruseDefault = /^(?:checked|selected)$/i; -// jQuery.attrFn +// JQuery.attrFn migrateWarnProp( jQuery, "attrFn", attrFn || {}, "jQuery.attrFn is deprecated" ); jQuery.attr = function( elem, name, value, pass ) { @@ -18,33 +18,40 @@ jQuery.attr = function( elem, name, value, pass ) { nType = elem && elem.nodeType; if ( pass ) { + // Since pass is used internally, we only warn for new jQuery // versions where there isn't a pass arg in the formal params if ( oldAttr.length < 4 ) { - migrateWarn("jQuery.fn.attr( props, pass ) is deprecated"); + migrateWarn( "jQuery.fn.attr( props, pass ) is deprecated" ); } if ( elem && !rnoAttrNodeType.test( nType ) && - (attrFn ? name in attrFn : jQuery.isFunction(jQuery.fn[name])) ) { + ( attrFn ? name in attrFn : jQuery.isFunction( jQuery.fn[ name ] ) ) ) { return jQuery( elem )[ name ]( value ); } } // Warn if user tries to set `type`, since it breaks on IE 6/7/8; by checking // for disconnected elements we don't warn on $( ""); + var $div = jQuery( "
" ), + $input = jQuery( "" ), + $button = jQuery( "" ); expectNoWarning( "input type change", function() { - $div.appendTo("#qunit-fixture").attr( "type", "fancy" ); - }); + $div.appendTo( "#qunit-fixture" ).attr( "type", "fancy" ); + } ); expectNoWarning( "$(html, props) signature", function() { jQuery( "