3 module.exports = function( grunt ) {
4 function readOptionalJSON( filepath ) {
5 const stripJSONComments = require( "strip-json-comments" );
8 data = JSON.parse( stripJSONComments(
9 fs.readFileSync( filepath, { encoding: "utf8" } )
15 const fs = require( "fs" );
16 const { spawn } = require( "child_process" );
17 const gzip = require( "gzip-js" );
18 const nodeV16OrNewer = !/^v1[0-5]\./.test( process.version );
19 const nodeV17OrNewer = !/^v1[0-6]\./.test( process.version );
20 const customBrowsers = process.env.BROWSERS && process.env.BROWSERS.split( "," );
22 // Support: Node.js <16
23 // Skip running tasks that dropped support for old Node.js in these Node versions.
24 function runIfNewNode( task ) {
25 return nodeV16OrNewer ? task : "print_old_node_message:" + task;
28 if ( nodeV16OrNewer ) {
29 const playwright = require( "playwright-webkit" );
30 process.env.WEBKIT_HEADLESS_BIN = playwright.webkit.executablePath();
33 if ( !grunt.option( "filename" ) ) {
34 grunt.option( "filename", "jquery.js" );
37 grunt.option( "dist-folder", grunt.option( "esm" ) ? "dist-module" : "dist" );
39 const builtJsFiles = [
42 "dist/jquery.slim.js",
43 "dist/jquery.slim.min.js",
44 "dist-module/jquery.module.js",
45 "dist-module/jquery.module.min.js",
46 "dist-module/jquery.slim.module.js",
47 "dist-module/jquery.slim.module.min.js"
50 const builtJsMinFiles = builtJsFiles
51 .filter( filepath => filepath.endsWith( ".min.js" ) );
54 pkg: grunt.file.readJSON( "package.json" ),
55 dst: readOptionalJSON( "dist/.destination.json" ),
57 files: builtJsMinFiles,
60 gz: function( contents ) {
61 return gzip.zip( contents, {} ).length;
64 cache: "build/.sizecache.json"
71 plugins: [ "@babel/transform-for-of" ]
75 "test/data/core/jquery-iterability-transpiled.js":
76 "test/data/core/jquery-iterability-transpiled-es6.js"
82 dest: "dist/jquery.js",
87 // Exclude specified modules if the module matching the key is removed
89 ajax: [ "manipulation/_evalUrl", "deprecated/ajax-event-alias" ],
90 callbacks: [ "deferred" ],
91 css: [ "effects", "dimensions", "offset" ],
92 "css/showHide": [ "effects" ],
94 remove: [ "ajax", "effects", "queue", "core/ready" ],
95 include: [ "core/ready-no-deferred" ]
97 event: [ "deprecated/ajax-event-alias", "deprecated/event" ],
98 selector: [ "css/hiddenVisibleSelectors", "effects/animatedSelector" ]
105 destPrefix: "external"
108 "bootstrap/bootstrap.css": "bootstrap/dist/css/bootstrap.css",
109 "bootstrap/bootstrap.min.css": "bootstrap/dist/css/bootstrap.min.css",
110 "bootstrap/bootstrap.min.css.map": "bootstrap/dist/css/bootstrap.min.css.map",
112 "core-js-bundle/core-js-bundle.js": "core-js-bundle/minified.js",
113 "core-js-bundle/LICENSE": "core-js-bundle/LICENSE",
115 "npo/npo.js": "native-promise-only/lib/npo.src.js",
117 "qunit/qunit.js": "qunit/qunit/qunit.js",
118 "qunit/qunit.css": "qunit/qunit/qunit.css",
119 "qunit/LICENSE.txt": "qunit/LICENSE.txt",
121 "requirejs/require.js": "requirejs/require.js",
123 "sinon/sinon.js": "sinon/pkg/sinon.js",
124 "sinon/LICENSE.txt": "sinon/LICENSE"
130 src: [ "package.json" ]
138 // We have to explicitly declare "src" property otherwise "newer"
139 // task wouldn't work properly :/
150 // Ignore files from .eslintignore
151 // See https://github.com/sindresorhus/grunt-eslint/issues/119
153 .readFileSync( `${ __dirname }/.eslintignore`, "utf-8" )
155 .filter( filePath => filePath )
156 .map( filePath => filePath[ 0 ] === "!" ?
157 filePath.slice( 1 ) :
161 // Explicitly ignore `dist/` & `dist-module/` as it could be unignored
162 // by the above `.eslintignore` parsing.
164 "!dist-module/**/*.js"
171 // A special module with basic tests, meant for not fully
172 // supported environments like jsdom. We run it everywhere,
173 // though, to make sure tests are not broken.
200 customContextFile: "test/karma.context.html",
201 customDebugFile: "test/karma.debug.html",
203 ChromeHeadlessNoSandbox: {
204 base: "ChromeHeadless",
205 flags: [ "--no-sandbox" ]
208 frameworks: [ "qunit" ],
209 middleware: [ "mockserver" ],
213 "middleware:mockserver": [
215 require( "./test/middleware-mockserver.cjs" )
222 // We're running `QUnit.start()` ourselves via `loadTests()`
228 "test/data/jquery-1.9.1.js",
229 "external/sinon/sinon.js",
230 "external/npo/npo.js",
231 "external/requirejs/require.js",
232 "test/data/testinit.js",
237 pattern: "dist/jquery.*",
249 { pattern: "external/**", included: false, served: true },
251 pattern: "test/**/*.@(js|css|jpg|html|xml|svg)",
257 reporters: [ "dots" ],
260 // 2 minutes; has to be longer than QUnit.config.testTimeout
261 browserNoActivityTimeout: 120e3,
264 captureTimeout: 20 * 1000,
268 browsers: customBrowsers ||
269 [ "ChromeHeadless", "FirefoxHeadless", "WebkitHeadless" ]
272 browsers: customBrowsers || [ "ChromeHeadless" ],
277 // We're running `QUnit.start()` ourselves via `loadTests()`
290 "test/data/jquery-1.9.1.js",
291 "test/data/testinit-jsdom.js",
293 // We don't support various loading methods like esmodules,
294 // choosing a version etc. for jsdom.
297 // A partial replacement for testinit.js#loadTests()
298 "test/data/testrunner.js",
300 // jsdom only runs basic tests
301 "test/unit/basic.js",
304 pattern: "test/**/*.@(js|css|jpg|html|xml|svg)",
310 browsers: [ "jsdom" ]
313 // To debug tests with Karma:
314 // 1. Run 'grunt karma:chrome-debug' or 'grunt karma:firefox-debug'
315 // (any karma subtask that has singleRun=false)
316 // 2. Press "Debug" in the opened browser window to start
317 // the tests. Unlike the other karma tasks, the debug task will
318 // keep the browser window open.
320 browsers: [ "Chrome" ],
324 browsers: [ "Firefox" ],
333 files: [ "<%= eslint.dev.src %>" ],
339 [ "<%= grunt.option('dist-folder') %>/" +
340 "<%= grunt.option('filename').replace(/\\.js$/, '.min.js') %>" ]:
341 "<%= grunt.option('dist-folder') %>/<%= grunt.option('filename') %>"
345 filename: "<%= grunt.option('dist-folder') %>/" +
346 "<%= grunt.option('filename')" +
347 ".replace(/\\.js$/, '.min.map') %>",
349 // The map's `files` & `sources` property are set incorrectly, fix
350 // them via overrides from the task config.
351 // See https://github.com/swc-project/swc/issues/7588#issuecomment-1624345254
353 file: "jquery.min.js",
361 ecma: grunt.option( "esm" ) ? 2015 : 5,
364 preamble: "/*! jQuery v4.0.0-pre | " +
365 "(c) OpenJS Foundation and other contributors | " +
366 "jquery.org/license */\n"
369 ecma: grunt.option( "esm" ) ? 2015 : 5,
380 // Load grunt tasks from NPM packages
381 require( "load-grunt-tasks" )( grunt, {
382 pattern: nodeV16OrNewer ? [ "grunt-*" ] : [ "grunt-*", "!grunt-eslint" ]
385 // Integrate jQuery specific tasks
386 grunt.loadTasks( "build/tasks" );
388 grunt.registerTask( "print_old_node_message", ( ...args ) => {
389 var task = args.join( ":" );
390 grunt.log.writeln( "Old Node.js detected, running the task \"" + task + "\" skipped..." );
393 grunt.registerTask( "build-all-variants",
394 "Build all variants of the full/slim build & a script/ESM one",
396 const done = this.async();
398 spawn( "npm run build-all-variants", {
402 .on( "close", code => {
407 grunt.registerTask( "print_jsdom_message", () => {
408 grunt.log.writeln( "Node.js 17 or newer detected, skipping jsdom tests..." );
411 grunt.registerTask( "lint", [
414 // Running the full eslint task without breaking it down to targets
415 // would run the dist target first which would point to errors in the built
416 // file, making it harder to fix them. We want to check the built file only
417 // if we already know the source files pass the linter.
418 runIfNewNode( "eslint:dev" ),
419 runIfNewNode( "eslint:dist" )
422 grunt.registerTask( "lint:newer", [
425 // Don't replace it with just the task; see the above comment.
426 runIfNewNode( "newer:eslint:dev" ),
427 runIfNewNode( "newer:eslint:dist" )
430 grunt.registerTask( "test:fast", [ "node_smoke_tests:commonjs:jquery" ] );
431 grunt.registerTask( "test:slow", [
432 runIfNewNode( "promises_aplus_tests" ),
434 // Support: Node.js 17+
435 // jsdom fails to connect to the Karma server in Node 17+.
436 // Until we figure out a fix, skip jsdom tests there.
437 nodeV17OrNewer ? "print_jsdom_message" : runIfNewNode( "karma:jsdom" )
440 grunt.registerTask( "test:prepare", [
446 grunt.registerTask( "test", [
452 grunt.registerTask( "dev", [
454 runIfNewNode( "newer:eslint:dev" ),
461 grunt.registerTask( "default", [
462 runIfNewNode( "eslint:dev" ),
463 "build-all-variants",
465 runIfNewNode( "eslint:dist" ),