From 30db70abdcde4edf4002240176e65eb2eafcb70d Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Fri, 13 May 2016 21:20:21 +0100 Subject: [PATCH] MDL-52127 grunt: be aware of third party paths 1) Parse thirdpartylibs.xml and generate an array of third party file paths to use in grunt tasks 2) In the lint tasks, we filter third party files from being linted 3) We add a new task to generate ignore files - currently for eslint, but will be potentially useful for other things in the future 4) Remove .eslintignore from source control Why have the ability to generate a .eslintignore file? For tooling integration - by having the eslintignore file people can use other eslint tools without having to just use grunt (e.g. editor integrations). --- .eslintignore | 6 ---- .gitignore | 1 + Gruntfile.js | 77 ++++++++++++++++++++++++++++++++++++++++----- npm-shrinkwrap.json | 10 ++++++ package.json | 4 ++- 5 files changed, 83 insertions(+), 15 deletions(-) delete mode 100644 .eslintignore diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index a6821676629..00000000000 --- a/.eslintignore +++ /dev/null @@ -1,6 +0,0 @@ -theme/bootstrapbase/amd/src/bootstrap.js -lib/amd/src/mustache.js -lib/amd/src/loglevel.js -lib/editor/atto/yui/src/rangy/ -**/yui/src/*/meta/*.js -lib/yui/src/notification/js/shared.js diff --git a/.gitignore b/.gitignore index 1dab0f7a5c1..71a7224e0ab 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ composer.phar /lib/yuilib/*/*/*-coverage.js atlassian-ide-plugin.xml /node_modules/ +.eslintignore diff --git a/Gruntfile.js b/Gruntfile.js index 2ec167eaa64..3cc3bb07530 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -27,7 +27,10 @@ module.exports = function(grunt) { var path = require('path'), tasks = {}, - cwd = process.env.PWD || process.cwd(); + cwd = process.env.PWD || process.cwd(), + async = require('async'), + DOMParser = require('xmldom').DOMParser, + xpath = require('xpath'); // Windows users can't run grunt in a subdirectory, so allow them to set // the root by passing --root=path/to/dir. @@ -63,6 +66,55 @@ module.exports = function(grunt) { return destPath; }; + /** + * Find thirdpartylibs.xml and generate an array of paths contained within + * them (used to generate ignore files and so on). + * + * @return {array} The list of thirdparty paths. + */ + var getThirdPartyPathsFromXML = function() { + var thirdpartyfiles = grunt.file.expand('*/**/thirdpartylibs.xml'); + var libs = ['node_modules/', 'vendor/']; + + thirdpartyfiles.forEach( function(file) { + var dirname = path.dirname(file); + + var doc = new DOMParser().parseFromString(grunt.file.read(file)); + var nodes = xpath.select("/libraries/library/location/text()", doc); + + nodes.forEach(function(node) { + var lib = path.join(dirname, node.toString()); + if (grunt.file.isDir(lib)) { + // Ensure trailing slash on dirs. + lib = lib.replace(/\/?$/, '/'); + } + + // Look for duplicate paths before adding to array. + if (libs.indexOf(lib) === -1) { + libs.push(lib); + } + }); + }); + return libs; + }; + + // An array of paths to third party directories. + var thirdPartyPaths = getThirdPartyPathsFromXML(); + + /** + * Determine if the file is a Moodle file, or its listed in + * the thirdpartylibs.xml file paths as a third party file. + * + * @param {string} file The file path to determine if thirdparty + * @return {bool} false If thid party file. + */ + var isMoodleFile = function(file) { + if (grunt.file.isMatch(thirdPartyPaths, file)) { + return false; + } + return true; + }; + // Project configuration. grunt.initConfig({ jshint: { @@ -70,20 +122,20 @@ module.exports = function(grunt) { amd: { src: amdSrc } }, eslint: { - // Even though warnings dont stop the build we don't display warnings by default because: - // * At this moment we've got too many core warnings - // * It will complain about ignored files (https://github.com/sindresorhus/grunt-eslint/issues/119) - // * It's better experience to use editor integrations or eslint natively + // Even though warnings dont stop the build we don't display warnings by default because + // at this moment we've got too many core warnings. options: { quiet: !grunt.option('show-lint-warnings') }, // Check AMD files. We add some stricter rules which we can't apply to the default configuration due // to YUI rollups. amd: { src: amdSrc, + filter: isMoodleFile, options: { rules: {'no-undef': 'error', 'no-unused-vars': 'error', 'no-empty': 'error', 'no-unused-expressions': 'error'} } }, // Check YUI module source files. yui: { - src: ['**/yui/src/**/*.js'] + src: ['**/yui/src/**/*.js', '!*/**/yui/src/*/meta/*.js'], + filter: isMoodleFile } }, uglify: { @@ -131,6 +183,15 @@ module.exports = function(grunt) { } }); + /** + * Generate ignore files (utilising thirdpartylibs.xml data) + */ + tasks.ignorefiles = function() { + // Generate .eslintignore. + var eslintIgnores = ['# Generated by "grunt ignorefiles"', '*/**/yui/src/*/meta/', '*/**/build/'].concat(thirdPartyPaths); + grunt.file.write('.eslintignore', eslintIgnores.join('\n')); + }; + /** * Shifter task. Is configured with a path to a specific file or a directory, * in the case of a specific file it will work out the right module to be built. @@ -139,8 +200,7 @@ module.exports = function(grunt) { * so be careful to to call done(). */ tasks.shifter = function() { - var async = require('async'), - done = this.async(), + var done = this.async(), options = grunt.config('shifter.options'); // Run the shifter processes one at a time to avoid confusing output. @@ -260,6 +320,7 @@ module.exports = function(grunt) { // Register JS tasks. grunt.registerTask('shifter', 'Run Shifter against the current directory', tasks.shifter); + grunt.registerTask('ignorefiles', 'Generate ignore files for linters', tasks.ignorefiles); grunt.registerTask('yui', ['eslint:yui', 'shifter']); grunt.registerTask('amd', ['eslint:amd', 'jshint', 'uglify']); grunt.registerTask('js', ['amd', 'yui']); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 45c770463de..6411bc5d0b2 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1969,6 +1969,16 @@ "from": "xml2js@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz" }, + "xmldom": { + "version": "0.1.22", + "from": "xmldom@latest", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.22.tgz" + }, + "xpath": { + "version": "0.0.23", + "from": "xpath@latest", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.23.tgz" + }, "xregexp": { "version": "3.1.1", "from": "xregexp@>=3.0.0 <4.0.0", diff --git a/package.json b/package.json index d6d275db0c5..5989a0ea0c3 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,8 @@ "grunt-contrib-uglify": "0.11.0", "grunt-contrib-watch": "0.6.1", "grunt-eslint": "^18.1.0", - "shifter": "0.5.0" + "shifter": "0.5.0", + "xmldom": "^0.1.22", + "xpath": "0.0.23" } }