diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..aa2f745 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: monthly + + # Group all dependabot version update PRs into one + groups: + github-actions: + applies-to: version-updates + patterns: + - "*" diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index a97a874..b2107fb 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -15,19 +15,19 @@ jobs: NODE_VERSION: [18.x, 20.x, 22.x] steps: - name: Checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Install xsltproc + - name: Install xsltproc & ImageMagick run: | - sudo apt-get install xsltproc + sudo apt-get install xsltproc imagemagick - name: Use Node.js ${{ matrix.NODE_VERSION }} - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.NODE_VERSION }} - name: Cache - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 with: path: ~/.npm key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-npm-lock-${{ hashFiles('**/package-lock.json') }} diff --git a/Gruntfile.js b/Gruntfile.js index d49e922..e664603 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -11,7 +11,6 @@ grunt.loadNpmTasks( "grunt-check-modules" ); grunt.loadNpmTasks( "grunt-contrib-clean" ); grunt.loadNpmTasks( "grunt-contrib-copy" ); grunt.loadNpmTasks( "grunt-contrib-handlebars" ); -grunt.loadNpmTasks( "grunt-contrib-uglify" ); grunt.loadNpmTasks( "grunt-eslint" ); grunt.initConfig( { @@ -61,10 +60,7 @@ grunt.initConfig( { dest: "app/dist" } }, - uglify: { - options: { - preserveComments: "some" - }, + minify: { // DownloadBuilder minified frontend bundle download: { @@ -87,6 +83,9 @@ grunt.initConfig( { } } ); +// local tasks +grunt.loadTasks( "grunt-tasks" ); + function log( callback, successMsg, errorMsg ) { return function( error, result, code ) { if ( error && errorMsg ) { @@ -279,7 +278,7 @@ function buildPackages( folder, callback ) { grunt.registerTask( "default", [ "check-modules", "eslint", "test" ] ); -grunt.registerTask( "build-app", [ "clean", "handlebars", "copy", "uglify" ] ); +grunt.registerTask( "build-app", [ "clean", "handlebars", "copy", "minify" ] ); grunt.registerTask( "build-packages", "Builds zip package of each jQuery UI release specified in config file with all components and lightness theme, inside the given folder", function( folder ) { var done = this.async(); diff --git a/grunt-tasks/minify.js b/grunt-tasks/minify.js new file mode 100644 index 0000000..dfe37f5 --- /dev/null +++ b/grunt-tasks/minify.js @@ -0,0 +1,26 @@ +"use strict"; + +const swc = require( "@swc/core" ); +const swcOptions = require( "../lib/swc-options" ); + +module.exports = function( grunt ) { + +grunt.registerMultiTask( "minify", async function() { + const done = this.async(); + + for ( const file of this.files ) { + const contents = file.src + .map( singleFile => grunt.file.read( singleFile ) ) + .join( "\n" ); + + const { code } = await swc.minify( contents, swcOptions ); + + grunt.file.write( file.dest, code ); + + grunt.log.writeln( `File ${ file.dest } created.` ); + } + + done(); +} ); + +}; diff --git a/lib/jquery-ui-files.js b/lib/jquery-ui-files.js index 0d762b2..12a6450 100644 --- a/lib/jquery-ui-files.js +++ b/lib/jquery-ui-files.js @@ -5,7 +5,8 @@ var stripBanner, glob, noDirectory, fs = require( "node:fs" ), path = require( "node:path" ), sqwish = require( "sqwish" ), - UglifyJS = require( "uglify-js" ), + swc = require( "@swc/core" ), + swcOptions = require( "./swc-options" ), util = require( "./util" ), Files = require( "./files" ), filesCache = {}; @@ -91,7 +92,10 @@ JqueryUiFiles.prototype = { path: file.path.replace( /\.([^.]*)$/, ".min.$1" ) }; if ( ( /\.js$/i ).test( file.path ) ) { - minified[ file.path ].data = UglifyJS.minify( file.data.toString( "utf8" ) ).code; + minified[ file.path ].data = swc.minifySync( + file.data.toString( "utf8" ), + swcOptions + ).code; } else if ( ( /\.css$/i ).test( file.path ) ) { minified[ file.path ].data = sqwish.minify( file.data.toString( "utf8" ) ); } diff --git a/lib/package.js b/lib/package.js index ff35e2c..0cf03dc 100644 --- a/lib/package.js +++ b/lib/package.js @@ -11,7 +11,8 @@ var indexTemplate, sqwish = require( "sqwish" ), ThemeRoller = require( "./themeroller" ), semver = require( "semver" ), - UglifyJS = require( "uglify-js" ); + swc = require( "@swc/core" ), + swcOptions = require( "./swc-options" ); indexTemplate = handlebars.compile( fs.readFileSync( __dirname + "/../template/zip/index.html", "utf8" ) ); @@ -340,13 +341,8 @@ extend( Package.prototype, { } this.jsBundle.promise.then( function( js ) { - var minJs; var _banner = banner( pkgJson, jsFileNames, { minify: true } ); - var uglifyResult = UglifyJS.minify( js ); - if ( uglifyResult.error ) { - throw uglifyResult.error; - } - minJs = uglifyResult.code; + var minJs = swc.minifySync( js, swcOptions ).code; callback( null, _banner + minJs ); } ).catch( callback ); }, diff --git a/lib/swc-options.js b/lib/swc-options.js new file mode 100644 index 0000000..b48807f --- /dev/null +++ b/lib/swc-options.js @@ -0,0 +1,21 @@ +"use strict"; + +module.exports = { + compress: { + ecma: 5, + hoist_funs: false, + loops: false + }, + format: { + ecma: 5, + asciiOnly: true, + + // That only preserves license comments. + // See https://swc.rs/docs/configuration/minification#note-about-comments + comments: true + }, + inlineSourcesContent: false, + mangle: true, + module: false, + sourceMap: false +}; diff --git a/package-lock.json b/package-lock.json index 428011b..97226e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,11 @@ "version": "2.3.13", "license": "MIT", "dependencies": { + "@swc/core": "1.11.5", "async": "3.2.6", "builder-amd": "0.0.3", "builder-jquery-css": "0.0.4", + "eslint": "9.21.0", "eslint-config-jquery": "3.0.2", "express": "^4.21.2", "fast-glob": "^3.3.3", @@ -23,7 +25,6 @@ "grunt-contrib-clean": "2.0.1", "grunt-contrib-copy": "1.0.0", "grunt-contrib-handlebars": "3.0.0", - "grunt-contrib-uglify": "5.2.2", "grunt-eslint": "25.0.0", "handlebars": "4.7.8", "lzma": "2.3.2", @@ -31,7 +32,6 @@ "qunit": "^2.24.1", "semver": "^7.7.1", "sqwish": "0.2.2", - "uglify-js": "3.19.3", "winston": "^3.17.0", "wolfy87-eventemitter": "5.2.9" }, @@ -431,6 +431,219 @@ "node": ">=14" } }, + "node_modules/@swc/core": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.11.5.tgz", + "integrity": "sha512-EVY7zfpehxhTZXOfy508gb3D78ihoGGmvyiTWtlBPjgIaidP1Xw0naHMD78CWiFlZmeDjKXJufGtsEGOnZdmNA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.19" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.11.5", + "@swc/core-darwin-x64": "1.11.5", + "@swc/core-linux-arm-gnueabihf": "1.11.5", + "@swc/core-linux-arm64-gnu": "1.11.5", + "@swc/core-linux-arm64-musl": "1.11.5", + "@swc/core-linux-x64-gnu": "1.11.5", + "@swc/core-linux-x64-musl": "1.11.5", + "@swc/core-win32-arm64-msvc": "1.11.5", + "@swc/core-win32-ia32-msvc": "1.11.5", + "@swc/core-win32-x64-msvc": "1.11.5" + }, + "peerDependencies": { + "@swc/helpers": "*" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.5.tgz", + "integrity": "sha512-GEd1hzEx0mSGkJYMFMGLnrGgjL2rOsOsuYWyjyiA3WLmhD7o+n/EWBDo6mzD/9aeF8dzSPC0TnW216gJbvrNzA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.11.5.tgz", + "integrity": "sha512-toz04z9wAClVvQSEY3xzrgyyeWBAfMWcKG4K0ugNvO56h/wczi2ZHRlnAXZW1tghKBk3z6MXqa/srfXgNhffKw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.5.tgz", + "integrity": "sha512-5SjmKxXdwbBpsYGTpgeXOXMIjS563/ntRGn8Zc12H/c4VfPrRLGhgbJ/48z2XVFyBLcw7BCHZyFuVX1+ZI3W0Q==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.5.tgz", + "integrity": "sha512-pydIlInHRzRIwB0NHblz3Dx58H/bsi0I5F2deLf9iOmwPNuOGcEEZF1Qatc7YIjP5DFbXK+Dcz+pMUZb2cc2MQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.5.tgz", + "integrity": "sha512-LhBHKjkZq5tJF1Lh0NJFpx7ROnCWLckrlIAIdSt9XfOV+zuEXJQOj+NFcM1eNk17GFfFyUMOZyGZxzYq5dveEQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.5.tgz", + "integrity": "sha512-dCi4xkxXlsk5sQYb3i413Cfh7+wMJeBYTvBZTD5xh+/DgRtIcIJLYJ2tNjWC4/C2i5fj+Ze9bKNSdd8weRWZ3A==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.11.5.tgz", + "integrity": "sha512-K0AC4TreM5Oo/tXNXnE/Gf5+5y/HwUdd7xvUjOpZddcX/RlsbYOKWLgOtA3fdFIuta7XC+vrGKmIhm5l70DSVQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.5.tgz", + "integrity": "sha512-wzum8sYUsvPY7kgUfuqVYTgIPYmBC8KPksoNM1fz5UfhudU0ciQuYvUBD47GIGOevaoxhLkjPH4CB95vh1mJ9w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.5.tgz", + "integrity": "sha512-lco7mw0TPRTpVPR6NwggJpjdUkAboGRkLrDHjIsUaR+Y5+0m5FMMkHOMxWXAbrBS5c4ph7QErp4Lma4r9Mn5og==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.5.tgz", + "integrity": "sha512-E+DApLSC6JRK8VkDa4bNsBdD7Qoomx1HvKVZpOXl9v94hUZI5GMExl4vU5isvb+hPWL7rZ0NeI7ITnVLgLJRbA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" + }, + "node_modules/@swc/types": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.19.tgz", + "integrity": "sha512-WkAZaAfj44kh/UFdAQcrMP1I0nwRqpt27u+08LMBYMqmQfwwMofYoMh/48NGkMMRfC4ynpfwRbJuu8ErfNloeA==", + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -1120,12 +1333,6 @@ "node": ">= 0.4" } }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "license": "MIT" - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -1649,21 +1856,6 @@ "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", "license": "MIT" }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -2239,82 +2431,6 @@ "node": ">=8" } }, - "node_modules/grunt-contrib-uglify": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-5.2.2.tgz", - "integrity": "sha512-ITxiWxrjjP+RZu/aJ5GLvdele+sxlznh+6fK9Qckio5ma8f7Iv8woZjRkGfafvpuygxNefOJNc+hfjjBayRn2Q==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "maxmin": "^3.0.0", - "uglify-js": "^3.16.1", - "uri-path": "^1.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/grunt-contrib-uglify/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/grunt-contrib-uglify/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/grunt-contrib-uglify/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/grunt-contrib-uglify/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/grunt-contrib-uglify/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/grunt-eslint": { "version": "25.0.0", "resolved": "https://registry.npmjs.org/grunt-eslint/-/grunt-eslint-25.0.0.tgz", @@ -2556,19 +2672,6 @@ "node": "*" } }, - "node_modules/gzip-size": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", - "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==", - "license": "MIT", - "dependencies": { - "duplexer": "^0.1.1", - "pify": "^4.0.1" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -3189,85 +3292,6 @@ "node": ">= 0.4" } }, - "node_modules/maxmin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-3.0.0.tgz", - "integrity": "sha512-wcahMInmGtg/7c6a75fr21Ch/Ks1Tb+Jtoan5Ft4bAI0ZvJqyOw8kkM7e7p8hDSzY805vmxwHT50KcjGwKyJ0g==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "figures": "^3.2.0", - "gzip-size": "^5.1.1", - "pretty-bytes": "^5.3.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/maxmin/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/maxmin/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/maxmin/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/maxmin/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/maxmin/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -3770,15 +3794,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3788,18 +3803,6 @@ "node": ">= 0.8.0" } }, - "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -4647,6 +4650,7 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "license": "BSD-2-Clause", + "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" }, @@ -4700,15 +4704,6 @@ "punycode": "^2.1.0" } }, - "node_modules/uri-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz", - "integrity": "sha512-8pMuAn4KacYdGMkFaoQARicp4HSw24/DHOVKWqVRJ8LhhAwPPFpdGvdL9184JVmUwe7vz7Z9n6IqI6t5n2ELdg==", - "license": "WTFPL OR MIT", - "engines": { - "node": ">= 0.10" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index 7d5ed74..af8403a 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,11 @@ }, "license": "MIT", "dependencies": { + "@swc/core": "1.11.5", "async": "3.2.6", "builder-amd": "0.0.3", "builder-jquery-css": "0.0.4", + "eslint": "9.21.0", "eslint-config-jquery": "3.0.2", "express": "^4.21.2", "fast-glob": "^3.3.3", @@ -22,7 +24,6 @@ "grunt-contrib-clean": "2.0.1", "grunt-contrib-copy": "1.0.0", "grunt-contrib-handlebars": "3.0.0", - "grunt-contrib-uglify": "5.2.2", "grunt-eslint": "25.0.0", "handlebars": "4.7.8", "lzma": "2.3.2", @@ -30,7 +31,6 @@ "qunit": "^2.24.1", "semver": "^7.7.1", "sqwish": "0.2.2", - "uglify-js": "3.19.3", "winston": "^3.17.0", "wolfy87-eventemitter": "5.2.9" }, diff --git a/test/package.js b/test/package.js index f913663..5e4c81d 100644 --- a/test/package.js +++ b/test/package.js @@ -2,19 +2,67 @@ QUnit.module( "package" ); -let commonFiles, COMMON_FILES_TESTCASES, defaultTheme, someWidgets1, someWidgets2, themeFiles, THEME_FILES_TESTCASES; +let defaultTheme, someWidgets1, someWidgets2, + commonFiles, COMMON_FILES_TESTCASES, + themeFiles, THEME_FILES_TESTCASES, + es5Files, ES5_FILES_TESTCASES; const JqueryUi = require( "../lib/jquery-ui" ); const Package = require( "../lib/package" ); const Packager = require( "node-packager" ); const themeGallery = require( "../lib/themeroller-themegallery" )(); - -function filePresent( files, filepath ) { - const filepathRe = filepath instanceof RegExp ? filepath : new RegExp( filepath.replace( /\*/g, "[^\/]*" ).replace( /\./g, "\\." ).replace( /(.*)/, "^$1$" ) ); - return Object.keys( files ).some( function( filepath ) { +const { ESLint } = require( "eslint" ); + +function findFilepath( files, filepath ) { + const filepathRe = filepath instanceof RegExp ? + filepath : + new RegExp( + filepath + .replace( /\*/g, "[^\/]*" ) + .replace( /\./g, "\\." ) + .replace( /(.*)/, "^$1$" ) + ); + return Object.keys( files ).find( function( filepath ) { return filepathRe.test( filepath ); } ); } +// An ESLint instance meant just to test if provided files are in ES5. +// Use via the `ensureEs5` function. +const eslintEs5 = new ESLint( { + + // Disable searching for config files + overrideConfigFile: true, + + overrideConfig: { + + // Match all files. We will run it only on code we want anyway. + files: [ "*" ], + + languageOptions: { + ecmaVersion: 5, + sourceType: "script" + }, + + linterOptions: { + noInlineConfig: true, + reportUnusedDisableDirectives: "off", + reportUnusedInlineConfigs: "off" + } + } +} ); + +async function ensureEs5( contents ) { + const results = await eslintEs5.lintText( contents ); + if ( results[ 0 ].errorCount === 0 ) { + return { success: true }; + } + + return { + success: false, + message: results[ 0 ].messages.map( msgData => msgData.message ).join( "\n" ) + }; +} + defaultTheme = themeGallery[ 0 ].vars; someWidgets1 = "widget position widgets/autocomplete widgets/button widgets/menu widgets/progressbar widgets/spinner widgets/tabs".split( " " ); someWidgets2 = "widget widgets/mouse position widgets/draggable widgets/resizable widgets/button widgets/datepicker widgets/dialog widgets/slider widgets/tooltip".split( " " ); @@ -32,10 +80,26 @@ commonFiles = [ COMMON_FILES_TESTCASES = commonFiles.length; function commonFilesCheck( assert, files ) { commonFiles.forEach( function( filepath ) { - assert.ok( filePresent( files, filepath ), "A common file \"" + filepath + "\" present." ); + assert.ok( !!findFilepath( files, filepath ), "A common file \"" + filepath + "\" present." ); } ); } +es5Files = [ + "jquery-ui.js", + "jquery-ui.min.js" +]; +ES5_FILES_TESTCASES = es5Files.length * 2; +async function es5FilesCheck( assert, files ) { + for ( const filepathPattern of es5Files ) { + const filepath = findFilepath( files, filepathPattern ); + assert.ok( !!filepath, "A JS file \"" + filepath + "\" present." ); + const lintResult = await ensureEs5( files[ filepath ] ); + assert.ok( lintResult.success, `JS file "${ filepath }" needs to be in ES5 format.${ + lintResult.success ? "" : `Messages from ESLint:\n${ lintResult.message }` + }` ); + } +} + themeFiles = [ "jquery-ui.theme.css", "jquery-ui.theme.min.css", @@ -45,9 +109,9 @@ THEME_FILES_TESTCASES = themeFiles.length; function themeFilesCheck( assert, files, theme ) { themeFiles.forEach( function( filepath ) { if ( theme ) { - assert.ok( filePresent( files, filepath ), "A theme file \"" + filepath + "\" present." ); + assert.ok( !!findFilepath( files, filepath ), "A theme file \"" + filepath + "\" present." ); } else { - assert.ok( !filePresent( files, filepath ), "The theme file \"" + filepath + "\" not included." ); + assert.ok( !findFilepath( files, filepath ), "The theme file \"" + filepath + "\" not included." ); } } ); } @@ -55,18 +119,20 @@ function themeFilesCheck( assert, files, theme ) { function runTests( context, jQueryUiVersion ) { QUnit.test( `[${ jQueryUiVersion }]: select all components with the default theme`, function( assert ) { - assert.expect( COMMON_FILES_TESTCASES + THEME_FILES_TESTCASES ); + assert.expect( COMMON_FILES_TESTCASES + ES5_FILES_TESTCASES + THEME_FILES_TESTCASES ); return new Promise( ( resolve, reject ) => { const pkg = new Packager( context.files, Package, { components: context.allComponents, themeVars: defaultTheme } ); - pkg.toJson( function( error, files ) { + pkg.toJson( async function( error, files ) { + debugger; if ( error ) { return reject( error ); } commonFilesCheck( assert, files ); + await es5FilesCheck( assert, files ); themeFilesCheck( assert, files, true ); resolve(); } ); @@ -74,18 +140,19 @@ function runTests( context, jQueryUiVersion ) { } ); QUnit.test( `[${ jQueryUiVersion }]: select all components with a different theme`, function( assert ) { - assert.expect( COMMON_FILES_TESTCASES + THEME_FILES_TESTCASES ); + assert.expect( COMMON_FILES_TESTCASES + ES5_FILES_TESTCASES + THEME_FILES_TESTCASES ); return new Promise( ( resolve, reject ) => { const pkg = new Packager( context.files, Package, { components: context.allComponents, themeVars: themeGallery[ 1 ].vars } ); - pkg.toJson( function( error, files ) { + pkg.toJson( async function( error, files ) { if ( error ) { return reject( error ); } commonFilesCheck( assert, files ); + await es5FilesCheck( assert, files ); themeFilesCheck( assert, files, true ); resolve(); } ); @@ -93,7 +160,7 @@ function runTests( context, jQueryUiVersion ) { } ); QUnit.test( `[${ jQueryUiVersion }]: test: select all widgets`, function( assert ) { - assert.expect( COMMON_FILES_TESTCASES + THEME_FILES_TESTCASES + 2 ); + assert.expect( COMMON_FILES_TESTCASES + ES5_FILES_TESTCASES + THEME_FILES_TESTCASES + 2 ); return new Promise( ( resolve, reject ) => { const allWidgets = context.allWidgets; @@ -102,11 +169,12 @@ function runTests( context, jQueryUiVersion ) { themeVars: defaultTheme } ); assert.strictEqual( allWidgets.length, 15, "All widgets count" ); - pkg.toJson( function( error, files ) { + pkg.toJson( async function( error, files ) { if ( error ) { return reject( error ); } commonFilesCheck( assert, files ); + await es5FilesCheck( assert, files ); themeFilesCheck( assert, files, true ); // 15 widgets, 14 have CSS, plus core, theme, draggable, resizable @@ -119,7 +187,7 @@ function runTests( context, jQueryUiVersion ) { } ); QUnit.test( `[${ jQueryUiVersion }]: test: select all effects`, function( assert ) { - assert.expect( COMMON_FILES_TESTCASES + THEME_FILES_TESTCASES + 1 ); + assert.expect( COMMON_FILES_TESTCASES + ES5_FILES_TESTCASES + THEME_FILES_TESTCASES + 1 ); return new Promise( ( resolve, reject ) => { const pkg = new Packager( context.files, Package, { @@ -127,11 +195,12 @@ function runTests( context, jQueryUiVersion ) { themeVars: null } ); assert.strictEqual( context.allEffects.length, 16, "All effects count" ); - pkg.toJson( function( error, files ) { + pkg.toJson( async function( error, files ) { if ( error ) { return reject( error ); } commonFilesCheck( assert, files ); + await es5FilesCheck( assert, files ); themeFilesCheck( assert, files, false ); resolve(); } ); @@ -139,7 +208,7 @@ function runTests( context, jQueryUiVersion ) { } ); QUnit.test( `[${ jQueryUiVersion }]: select some widgets (1)`, function( assert ) { - assert.expect( COMMON_FILES_TESTCASES + THEME_FILES_TESTCASES + 2 ); + assert.expect( COMMON_FILES_TESTCASES + ES5_FILES_TESTCASES + THEME_FILES_TESTCASES + 2 ); return new Promise( ( resolve, reject ) => { const pkg = new Packager( context.files, Package, { @@ -147,11 +216,12 @@ function runTests( context, jQueryUiVersion ) { themeVars: defaultTheme } ); assert.strictEqual( someWidgets1.length, 8, "Some widgets count" ); - pkg.toJson( function( error, files ) { + pkg.toJson( async function( error, files ) { if ( error ) { return reject( error ); } commonFilesCheck( assert, files ); + await es5FilesCheck( assert, files ); themeFilesCheck( assert, files, true ); // 8 components selected, 6 have CSS, plus core, theme, @@ -165,7 +235,7 @@ function runTests( context, jQueryUiVersion ) { } ); QUnit.test( `[${ jQueryUiVersion }]: select some widgets (2)`, function( assert ) { - assert.expect( COMMON_FILES_TESTCASES + THEME_FILES_TESTCASES + 2 ); + assert.expect( COMMON_FILES_TESTCASES + ES5_FILES_TESTCASES + THEME_FILES_TESTCASES + 2 ); return new Promise( ( resolve, reject ) => { const pkg = new Packager( context.files, Package, { @@ -173,11 +243,12 @@ function runTests( context, jQueryUiVersion ) { themeVars: defaultTheme } ); assert.strictEqual( someWidgets2.length, 10, "Some widgets count" ); - pkg.toJson( function( error, files ) { + pkg.toJson( async function( error, files ) { if ( error ) { return reject( error ); } commonFilesCheck( assert, files ); + await es5FilesCheck( assert, files ); themeFilesCheck( assert, files, true ); // 10 components selected, 7 have CSS, plus core, theme,