Build: Reference GitHub Actions by commit SHAs
[jquery.git] / Gruntfile.js
blob9029be85dca483bdbf696041779751a2cfa1f81d
1 "use strict";
3 module.exports = function( grunt ) {
4         function readOptionalJSON( filepath ) {
5                 const stripJSONComments = require( "strip-json-comments" );
6                 let data = {};
7                 try {
8                         data = JSON.parse( stripJSONComments(
9                                 fs.readFileSync( filepath, { encoding: "utf8" } )
10                         ) );
11                 } catch ( e ) {}
12                 return data;
13         }
15         const fs = require( "fs" );
16         const gzip = require( "gzip-js" );
17         const nodeV14OrNewer = !/^v1[0-3]\./.test( process.version );
18         const nodeV17OrNewer = !/^v1[0-6]\./.test( process.version );
19         const customBrowsers = process.env.BROWSERS && process.env.BROWSERS.split( "," );
21         // Support: Node.js <14
22         // Skip running tasks that dropped support for Node.js 10 or 12
23         // in this Node version.
24         function runIfNewNode( task ) {
25                 return nodeV14OrNewer ? task : "print_old_node_message:" + task;
26         }
28         if ( nodeV14OrNewer ) {
29                 const playwright = require( "playwright-webkit" );
30                 process.env.WEBKIT_HEADLESS_BIN = playwright.webkit.executablePath();
31         }
33         if ( !grunt.option( "filename" ) ) {
34                 grunt.option( "filename", "jquery.js" );
35         }
37         grunt.initConfig( {
38                 pkg: grunt.file.readJSON( "package.json" ),
39                 dst: readOptionalJSON( "dist/.destination.json" ),
40                 compare_size: {
41                         files: [ "dist/jquery.js", "dist/jquery.min.js" ],
42                         options: {
43                                 compress: {
44                                         gz: function( contents ) {
45                                                 return gzip.zip( contents, {} ).length;
46                                         }
47                                 },
48                                 cache: "build/.sizecache.json"
49                         }
50                 },
51                 babel: {
52                         options: {
53                                 sourceMap: "inline",
54                                 retainLines: true,
55                                 plugins: [ "@babel/transform-for-of" ]
56                         },
57                         tests: {
58                                 files: {
59                                         "test/data/core/jquery-iterability-transpiled.js":
60                                                 "test/data/core/jquery-iterability-transpiled-es6.js"
61                                 }
62                         }
63                 },
64                 build: {
65                         all: {
66                                 dest: "dist/jquery.js",
67                                 minimum: [
68                                         "core"
69                                 ],
71                                 // Exclude specified modules if the module matching the key is removed
72                                 removeWith: {
73                                         ajax: [ "manipulation/_evalUrl", "deprecated/ajax-event-alias" ],
74                                         callbacks: [ "deferred" ],
75                                         css: [ "effects", "dimensions", "offset" ],
76                                         "css/showHide": [ "effects" ],
77                                         deferred: {
78                                                 remove: [ "ajax", "effects", "queue", "core/ready" ],
79                                                 include: [ "core/ready-no-deferred" ]
80                                         },
81                                         event: [ "deprecated/ajax-event-alias", "deprecated/event" ],
82                                         selector: [ "css/hiddenVisibleSelectors", "effects/animatedSelector" ]
83                                 }
84                         }
85                 },
86                 npmcopy: {
87                         all: {
88                                 options: {
89                                         destPrefix: "external"
90                                 },
91                                 files: {
92                                         "core-js-bundle/core-js-bundle.js": "core-js-bundle/minified.js",
93                                         "core-js-bundle/LICENSE": "core-js-bundle/LICENSE",
95                                         "npo/npo.js": "native-promise-only/lib/npo.src.js",
97                                         "qunit/qunit.js": "qunit/qunit/qunit.js",
98                                         "qunit/qunit.css": "qunit/qunit/qunit.css",
99                                         "qunit/LICENSE.txt": "qunit/LICENSE.txt",
101                                         "requirejs/require.js": "requirejs/require.js",
103                                         "sinon/sinon.js": "sinon/pkg/sinon.js",
104                                         "sinon/LICENSE.txt": "sinon/LICENSE"
105                                 }
106                         }
107                 },
108                 jsonlint: {
109                         pkg: {
110                                 src: [ "package.json" ]
111                         }
112                 },
113                 eslint: {
114                         options: {
115                                 maxWarnings: 0
116                         },
118                         // We have to explicitly declare "src" property otherwise "newer"
119                         // task wouldn't work properly :/
120                         dist: {
121                                 src: [ "dist/jquery.js", "dist/jquery.min.js" ]
122                         },
123                         dev: {
124                                 src: [
125                                         "src/**/*.js",
126                                         "Gruntfile.js",
127                                         "test/**/*.js",
128                                         "build/**/*.js",
130                                         // Ignore files from .eslintignore
131                                         // See https://github.com/sindresorhus/grunt-eslint/issues/119
132                                         ...fs
133                                                 .readFileSync( `${ __dirname }/.eslintignore`, "utf-8" )
134                                                 .split( "\n" )
135                                                 .filter( filePath => filePath )
136                                                 .map( filePath => filePath[ 0 ] === "!" ?
137                                                         filePath.slice( 1 ) :
138                                                         `!${ filePath }`
139                                                 ),
141                                         // Explicitly ignore `dist/` as it could be unignored by
142                                         // the above `.eslintignore` parsing.
143                                         "!dist/**/*.js"
144                                 ]
145                         }
146                 },
147                 testswarm: {
148                         tests: [
150                                 // A special module with basic tests, meant for not fully
151                                 // supported environments like jsdom. We run it everywhere,
152                                 // though, to make sure tests are not broken.
153                                 "basic",
155                                 "ajax",
156                                 "animation",
157                                 "attributes",
158                                 "callbacks",
159                                 "core",
160                                 "css",
161                                 "data",
162                                 "deferred",
163                                 "deprecated",
164                                 "dimensions",
165                                 "effects",
166                                 "event",
167                                 "manipulation",
168                                 "offset",
169                                 "queue",
170                                 "selector",
171                                 "serialize",
172                                 "support",
173                                 "traversing",
174                                 "tween"
175                         ]
176                 },
177                 karma: {
178                         options: {
179                                 customContextFile: "test/karma.context.html",
180                                 customDebugFile: "test/karma.debug.html",
181                                 customLaunchers: {
182                                         ChromeHeadlessNoSandbox: {
183                                                 base: "ChromeHeadless",
184                                                 flags: [ "--no-sandbox" ]
185                                         }
186                                 },
187                                 frameworks: [ "qunit" ],
188                                 middleware: [ "mockserver" ],
189                                 plugins: [
190                                         "karma-*",
191                                         {
192                                                 "middleware:mockserver": [
193                                                         "factory",
194                                                         require( "./test/middleware-mockserver.js" )
195                                                 ]
196                                         }
197                                 ],
198                                 client: {
199                                         qunit: {
201                                                 // We're running `QUnit.start()` ourselves via `loadTests()`
202                                                 // in test/jquery.js
203                                                 autostart: false
204                                         }
205                                 },
206                                 files: [
207                                         "test/data/jquery-1.9.1.js",
208                                         "external/sinon/sinon.js",
209                                         "external/npo/npo.js",
210                                         "external/requirejs/require.js",
211                                         "test/data/testinit.js",
213                                         "test/jquery.js",
215                                         {
216                                                 pattern: "dist/jquery.*",
217                                                 included: false,
218                                                 served: true,
219                                                 nocache: true
220                                         },
221                                         {
222                                                 pattern: "src/**",
223                                                 type: "module",
224                                                 included: false,
225                                                 served: true,
226                                                 nocache: true
227                                         },
228                                         {
229                                                 pattern: "amd/**",
230                                                 included: false,
231                                                 served: true,
232                                                 nocache: true
233                                         },
234                                         { pattern: "external/**", included: false, served: true },
235                                         {
236                                                 pattern: "test/**/*.@(js|css|jpg|html|xml|svg)",
237                                                 included: false,
238                                                 served: true,
239                                                 nocache: true
240                                         }
241                                 ],
242                                 reporters: [ "dots" ],
243                                 autoWatch: false,
245                                 // 2 minutes; has to be longer than QUnit.config.testTimeout
246                                 browserNoActivityTimeout: 120e3,
248                                 concurrency: 3,
249                                 captureTimeout: 20 * 1000,
250                                 singleRun: true
251                         },
252                         main: {
253                                 browsers: customBrowsers ||
254                                         [ "ChromeHeadless", "FirefoxHeadless", "WebkitHeadless" ]
255                         },
256                         esmodules: {
257                                 browsers: customBrowsers || [ "ChromeHeadless" ],
258                                 options: {
259                                         client: {
260                                                 qunit: {
262                                                         // We're running `QUnit.start()` ourselves via `loadTests()`
263                                                         // in test/jquery.js
264                                                         autostart: false,
266                                                         esmodules: true
267                                                 }
268                                         }
269                                 }
270                         },
271                         amd: {
272                                 browsers: customBrowsers || [ "ChromeHeadless" ],
273                                 options: {
274                                         client: {
275                                                 qunit: {
277                                                         // We're running `QUnit.start()` ourselves via `loadTests()`
278                                                         // in test/jquery.js
279                                                         autostart: false,
281                                                         amd: true
282                                                 }
283                                         }
284                                 }
285                         },
287                         jsdom: {
288                                 options: {
289                                         files: [
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.
295                                                 "dist/jquery.js",
297                                                 // A partial replacement for testinit.js#loadTests()
298                                                 "test/data/testrunner.js",
300                                                 // jsdom only runs basic tests
301                                                 "test/unit/basic.js",
303                                                 {
304                                                         pattern: "test/**/*.@(js|css|jpg|html|xml|svg)",
305                                                         included: false,
306                                                         served: true
307                                                 }
308                                         ]
309                                 },
310                                 browsers: [ "jsdom" ]
311                         },
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.
319                         "chrome-debug": {
320                                 browsers: [ "Chrome" ],
321                                 singleRun: false
322                         },
323                         "firefox-debug": {
324                                 browsers: [ "Firefox" ],
325                                 singleRun: false
326                         },
327                         "ie-debug": {
328                                 browsers: [ "IE" ],
329                                 singleRun: false
330                         }
331                 },
332                 watch: {
333                         files: [ "<%= eslint.dev.src %>" ],
334                         tasks: [ "dev" ]
335                 },
336                 terser: {
337                         all: {
338                                 files: {
339                                         "dist/<%= grunt.option('filename').replace('.js', '.min.js') %>":
340                                                 "dist/<%= grunt.option('filename') %>"
341                                 },
342                                 options: {
343                                         ecma: 5,
344                                         sourceMap: {
345                                                 filename: "dist/<%= grunt.option('filename').replace('.js', '.min.map') %>"
346                                         },
347                                         format: {
348                                                 ascii_only: true,
349                                                 comments: false,
350                                                 preamble: "/*! jQuery v<%= pkg.version %> | " +
351                                                         "(c) OpenJS Foundation and other contributors | " +
352                                                         "jquery.org/license */"
353                                         },
354                                         compress: {
355                                                 hoist_funs: false,
356                                                 loops: false
357                                         }
358                                 }
359                         }
360                 }
361         } );
363         // Load grunt tasks from NPM packages
364         require( "load-grunt-tasks" )( grunt, {
365                 pattern: nodeV14OrNewer ? [ "grunt-*" ] : [ "grunt-*", "!grunt-eslint" ]
366         } );
368         // Integrate jQuery specific tasks
369         grunt.loadTasks( "build/tasks" );
371         grunt.registerTask( "print_old_node_message", ( ...args ) => {
372                 var task = args.join( ":" );
373                 grunt.log.writeln( "Old Node.js detected, running the task \"" + task + "\" skipped..." );
374         } );
376         grunt.registerTask( "print_jsdom_message", () => {
377                 grunt.log.writeln( "Node.js 17 or newer detected, skipping jsdom tests..." );
378         } );
380         grunt.registerTask( "lint", [
381                 "jsonlint",
383                 // Running the full eslint task without breaking it down to targets
384                 // would run the dist target first which would point to errors in the built
385                 // file, making it harder to fix them. We want to check the built file only
386                 // if we already know the source files pass the linter.
387                 runIfNewNode( "eslint:dev" ),
388                 runIfNewNode( "eslint:dist" )
389         ] );
391         grunt.registerTask( "lint:newer", [
392                 "newer:jsonlint",
394                 // Don't replace it with just the task; see the above comment.
395                 runIfNewNode( "newer:eslint:dev" ),
396                 runIfNewNode( "newer:eslint:dist" )
397         ] );
399         grunt.registerTask( "test:fast", runIfNewNode( "node_smoke_tests" ) );
400         grunt.registerTask( "test:slow", [
401                 runIfNewNode( "promises_aplus_tests" ),
403                 // Support: Node.js 17+
404                 // jsdom fails to connect to the Karma server in Node 17+.
405                 // Until we figure out a fix, skip jsdom tests there.
406                 nodeV17OrNewer ? "print_jsdom_message" : runIfNewNode( "karma:jsdom" )
407         ] );
409         grunt.registerTask( "test:prepare", [
410                 "npmcopy",
411                 "qunit_fixture",
412                 "babel:tests"
413         ] );
415         grunt.registerTask( "test", [
416                 "test:prepare",
417                 "test:fast",
418                 "test:slow"
419         ] );
421         grunt.registerTask( "dev", [
422                 "build:*:*",
423                 runIfNewNode( "newer:eslint:dev" ),
424                 "newer:terser",
425                 "remove_map_comment",
426                 "dist:*",
427                 "qunit_fixture",
428                 "compare_size"
429         ] );
431         grunt.registerTask( "default", [
432                 runIfNewNode( "eslint:dev" ),
433                 "build:*:*",
434                 "amd",
435                 "terser",
436                 "remove_map_comment",
437                 "dist:*",
438                 "test:prepare",
439                 runIfNewNode( "eslint:dist" ),
440                 "test:fast",
441                 "compare_size"
442         ] );