diff --git a/.editorconfig b/.editorconfig
index 1ba4f5faac0..fa81b6e2977 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -10,6 +10,10 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
+[*.yml]
+indent_style = space
+indent_size = 2
+
[external/**]
trim_trailing_whitespace = false
insert_final_newline = varies
diff --git a/.github/workflows/filestash.yml b/.github/workflows/filestash.yml
new file mode 100644
index 00000000000..d5755e61b82
--- /dev/null
+++ b/.github/workflows/filestash.yml
@@ -0,0 +1,51 @@
+name: Filestash
+
+on:
+ push:
+ branches:
+ - main
+
+permissions:
+ contents: read # to fetch code (actions/checkout)
+
+jobs:
+ update:
+ runs-on: ubuntu-latest
+ environment: filestash
+ env:
+ NODE_VERSION: 20.x
+ name: Update Filestash
+ steps:
+ - name: Checkout
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+
+ - name: Use Node.js ${{ env.NODE_VERSION }}
+ uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+
+ - name: Cache
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ~/.npm
+ key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: |
+ ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-
+
+ - name: Install dependencies
+ run: npm install
+
+ - name: Build
+ run: npm run build
+
+ - name: Set up SSH
+ run: |
+ install --directory ~/.ssh --mode 700
+ base64 --decode <<< "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
+ chmod 600 ~/.ssh/id_ed25519
+ ssh-keyscan -t ed25519 -H "${{ secrets.FILESTASH_SERVER }}" >> ~/.ssh/known_hosts
+
+ - name: Upload to Filestash
+ run: |
+ rsync dist/jquery-ui.js filestash@"${{ secrets.FILESTASH_SERVER }}":ui/jquery-ui-git.js
+ rsync dist/jquery-ui.css filestash@"${{ secrets.FILESTASH_SERVER }}":ui/jquery-ui-git.css
diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml
new file mode 100644
index 00000000000..221bb8b7077
--- /dev/null
+++ b/.github/workflows/node.js.yml
@@ -0,0 +1,163 @@
+name: Node
+
+on:
+ pull_request:
+ push:
+ branches-ignore: "dependabot/**"
+ # Once a week every Monday
+ schedule:
+ - cron: "42 1 * * 1"
+
+permissions:
+ contents: read
+
+env:
+ NODE_VERSION: 20.x
+
+jobs:
+ build-and-test:
+ runs-on: ubuntu-latest
+ name: ${{ matrix.BROWSER }} - jQuery ${{ matrix.JQUERY }}
+ strategy:
+ fail-fast: false
+ matrix:
+ BROWSER: [chrome, firefox]
+ JQUERY:
+ - "git"
+ - "3.x-git"
+ - "3.7.1"
+ - "2.2.4"
+ - "1.12.4"
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+
+ - name: Use Node.js ${{ env.NODE_VERSION }}
+ uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+
+ - name: Cache
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ~/.npm
+ key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: |
+ ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-
+
+ - name: Install npm dependencies
+ run: npm install
+
+ - name: Lint
+ run: npm run lint
+
+ - name: Build
+ run: npm run build
+
+ - name: Test
+ run: npm run test:unit -- -h -b ${{ matrix.BROWSER }} --jquery ${{ matrix.JQUERY }} --retries 3
+
+ edge:
+ runs-on: windows-latest
+ name: edge - jQuery ${{ matrix.JQUERY }}
+ strategy:
+ fail-fast: false
+ matrix:
+ JQUERY:
+ - "git"
+ - "3.x-git"
+ - "3.7.1"
+ - "2.2.4"
+ - "1.12.4"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+
+ - name: Use Node.js ${{ env.NODE_VERSION }}
+ uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+
+ - name: Cache
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ~/.npm
+ key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: |
+ ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-
+
+ - name: Install dependencies
+ run: npm install
+
+ - name: Build
+ run: npm run build
+
+ - name: Test
+ run: npm run test:unit -- -h -b edge --jquery ${{ matrix.JQUERY }} --retries 3
+
+ safari:
+ runs-on: macos-latest
+ name: safari - jQuery ${{ matrix.JQUERY }}
+ strategy:
+ fail-fast: false
+ matrix:
+ JQUERY:
+ - "git"
+ - "3.x-git"
+ - "3.7.1"
+ - "2.2.4"
+ - "1.12.4"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+
+ - name: Use Node.js ${{ env.NODE_VERSION }}
+ uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+
+ - name: Cache
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ~/.npm
+ key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: |
+ ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-
+
+ - name: Install dependencies
+ run: npm install
+
+ - name: Build
+ run: npm run build
+
+ - name: Test
+ run: npm run test:unit -- -b safari --jquery ${{ matrix.JQUERY }} --retries 3
+
+ legacy-build:
+ runs-on: ubuntu-latest
+ name: Build on Node 10.x
+ env:
+ NODE_VERSION: 10.x
+ steps:
+ - name: Checkout
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+
+ - name: Use Node.js ${{ env.NODE_VERSION }}
+ uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+
+ - name: Cache
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ~/.npm
+ key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: |
+ ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-
+
+ - name: Install npm dependencies
+ run: npm install
+
+ - name: Build
+ run: npm run build
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
deleted file mode 100644
index 0f958ac5059..00000000000
--- a/.github/workflows/test.yml
+++ /dev/null
@@ -1,63 +0,0 @@
-name: Grunt tests
-
-on: [push, pull_request]
-
-permissions:
- contents: read
-
-jobs:
- grunt:
- name: Grunt based tests with Node.js ${{ matrix.node-version }}
-
- runs-on: ubuntu-latest
- strategy:
- matrix:
- # Node.js 10 is required by jQuery infra
- node-version: [10.x, 18.x, 20.x]
-
- steps:
- - uses: actions/checkout@v4
-
- - uses: actions/setup-node@v4
- with:
- node-version: ${{ matrix.node-version }}
-
- - name: Get npm cache directory
- id: npm-cache-dir
- run: |
- echo "dir=\"$(npm config get cache)\"" >> $GITHUB_OUTPUT
-
- - name: Cache npm dependencies
- uses: actions/cache@v4
- with:
- path: ${{ steps.npm-cache-dir.outputs.dir }}
- key: ${{ runner.os }}-node-${{ matrix.node-version }}-npm-${{ hashFiles('**/package.json') }}
- restore-keys: |
- ${{ runner.os }}-node-${{ matrix.node-version }}-npm-
- ${{ runner.os }}-node-${{ matrix.node-version }}-
- ${{ runner.os }}-node-
- ${{ runner.os }}-
-
- - name: Install npm dependencies
- run: npm install
-
- # Keep these steps in sync with the default command tasks in our Gruntfile!
- - name: Run lint
- run: node_modules/.bin/grunt lint
-
- - name: Run RequireJS
- run: node_modules/.bin/grunt requirejs
-
- - name: Run Qunit
- run: node_modules/.bin/grunt test
-
- valid:
- name: Build & tests
-
- needs: grunt
-
- runs-on: ubuntu-latest
-
- steps:
- - name: Grunt based tests passed
- run: echo "✅"
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 00000000000..cffe8cdef13
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+save-exact=true
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a1b7fcfe41b..17321e179b2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -77,7 +77,7 @@ The tests require a local web server and the samples contain some PHP, so a PHP
### Running the Tests
-To lint the JavaScript, HTML, and CSS, as well as run a smoke test in PhantomJS, run the full test suite through npm:
+To lint the JavaScript, HTML, and CSS, as well as run the full test suite in Headless Chrome:
```bash
npm test
diff --git a/Gruntfile.js b/Gruntfile.js
index fd82b4c6c44..6df615825a9 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -77,7 +77,6 @@ const compareFiles = {
"dist/jquery-ui.min.js"
]
};
-const component = grunt.option( "component" ) || "**";
const htmllintBad = [
"demos/tabs/ajax/content*.html",
@@ -205,30 +204,6 @@ grunt.initConfig( {
src: htmllintBad
}
},
- qunit: {
- files: expandFiles( "tests/unit/" + component + "/*.html" ).filter( function( file ) {
- return !( /(all|index|test)\.html$/ ).test( file );
- } ),
- options: {
- puppeteer: {
- args: [
- "--allow-file-access-from-files"
- ]
- },
- inject: [
- require.resolve(
- "./tests/lib/grunt-contrib-qunit-bridges/bridge-wrapper.js.intro"
- ),
- require.resolve( "grunt-contrib-qunit/chrome/bridge" ),
- require.resolve(
- "./tests/lib/grunt-contrib-qunit-bridges/bridge-wrapper.js.outro"
- )
- ],
- page: {
- viewportSize: { width: 700, height: 500 }
- }
- }
- },
eslint: {
all: [
"ui/**/*.js",
@@ -430,6 +405,9 @@ grunt.initConfig( {
"jquery-3.7.0/jquery.js": "jquery-3.7.0/dist/jquery.js",
"jquery-3.7.0/LICENSE.txt": "jquery-3.7.0/LICENSE.txt",
+ "jquery-3.7.1/jquery.js": "jquery-3.7.1/dist/jquery.js",
+ "jquery-3.7.1/LICENSE.txt": "jquery-3.7.1/LICENSE.txt",
+
"jquery-migrate-1.4.1/jquery-migrate.js":
"jquery-migrate-1.4.1/dist/jquery-migrate.js",
"jquery-migrate-1.4.1/LICENSE.txt": "jquery-migrate-1.4.1/LICENSE.txt",
@@ -473,13 +451,12 @@ grunt.initConfig( {
require( "load-grunt-tasks" )( grunt, {
pattern: nodeV16OrNewer ? [ "grunt-*" ] : [
"grunt-*",
- "!grunt-contrib-qunit",
"!grunt-eslint",
"!grunt-html"
]
} );
-// local testswarm and build tasks
+// local tasks
grunt.loadTasks( "build/tasks" );
grunt.registerTask( "update-authors", function() {
@@ -518,15 +495,15 @@ grunt.registerTask( "print_old_node_message", ( ...args ) => {
} );
// Keep this task list in sync with the testing steps in our GitHub action test workflow file!
-grunt.registerTask( "default", [ "lint", "requirejs", "test" ] );
-grunt.registerTask( "jenkins", [ "default", "concat" ] );
grunt.registerTask( "lint", [
"asciilint",
runIfNewNode( "eslint" ),
"csslint",
runIfNewNode( "htmllint" )
] );
-grunt.registerTask( "test", [ runIfNewNode( "qunit" ) ] );
+grunt.registerTask( "build", [ "requirejs", "concat" ] );
+grunt.registerTask( "default", [ "lint", "build" ] );
+grunt.registerTask( "jenkins", [ "build" ] );
grunt.registerTask( "sizer", [ "requirejs:js", "uglify:main", "compare_size:all" ] );
grunt.registerTask( "sizer_all", [ "requirejs:js", "uglify", "compare_size" ] );
diff --git a/README.md b/README.md
index b4df566032d..fa88503b5cc 100644
--- a/README.md
+++ b/README.md
@@ -29,4 +29,4 @@ For more information, see the [contributing page](CONTRIBUTING.md).
Run the unit tests manually with appropriate browsers and any local web server. See our [environment setup](CONTRIBUTING.md#environment-minimum-required) and [information on running tests](CONTRIBUTING.md#running-the-tests).
-You can also run the unit tests inside phantomjs by [setting up your environment](CONTRIBUTING.md#user-content-environment-recommended-setup).
+You can also run the unit tests `npm run test:unit -- --help`.
diff --git a/bower.json b/bower.json
index a1fe6e1efc6..7dc19a1595e 100644
--- a/bower.json
+++ b/bower.json
@@ -17,7 +17,6 @@
"jquery-simulate": "1.1.1",
"qunit": "2.19.4",
"requirejs": "2.1.14",
-
"jquery-1.8.0": "jquery#1.8.0",
"jquery-1.8.1": "jquery#1.8.1",
"jquery-1.8.2": "jquery#1.8.2",
@@ -68,6 +67,7 @@
"jquery-3.6.3": "jquery#3.6.3",
"jquery-3.6.4": "jquery#3.6.4",
"jquery-3.7.0": "jquery#3.7.0",
+ "jquery-3.7.1": "jquery#3.7.1",
"jquery-migrate-1.4.1": "https://registry.npmjs.org/jquery-migrate/-/jquery-migrate-1.4.1.tgz",
"jquery-migrate-3.4.1": "https://registry.npmjs.org/jquery-migrate/-/jquery-migrate-3.4.1.tgz"
}
diff --git a/external/jquery-3.7.1/LICENSE.txt b/external/jquery-3.7.1/LICENSE.txt
new file mode 100644
index 00000000000..f642c3f7a77
--- /dev/null
+++ b/external/jquery-3.7.1/LICENSE.txt
@@ -0,0 +1,20 @@
+Copyright OpenJS Foundation and other contributors, https://openjsf.org/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/external/jquery-3.7.1/jquery.js b/external/jquery-3.7.1/jquery.js
new file mode 100644
index 00000000000..1a86433c223
--- /dev/null
+++ b/external/jquery-3.7.1/jquery.js
@@ -0,0 +1,10716 @@
+/*!
+ * jQuery JavaScript Library v3.7.1
+ * https://jquery.com/
+ *
+ * Copyright OpenJS Foundation and other contributors
+ * Released under the MIT license
+ * https://jquery.org/license
+ *
+ * Date: 2023-08-28T13:37Z
+ */
+( function( global, factory ) {
+
+ "use strict";
+
+ if ( typeof module === "object" && typeof module.exports === "object" ) {
+
+ // For CommonJS and CommonJS-like environments where a proper `window`
+ // is present, execute the factory and get jQuery.
+ // For environments that do not have a `window` with a `document`
+ // (such as Node.js), expose a factory as module.exports.
+ // This accentuates the need for the creation of a real `window`.
+ // e.g. var jQuery = require("jquery")(window);
+ // See ticket trac-14549 for more info.
+ module.exports = global.document ?
+ factory( global, true ) :
+ function( w ) {
+ if ( !w.document ) {
+ throw new Error( "jQuery requires a window with a document" );
+ }
+ return factory( w );
+ };
+ } else {
+ factory( global );
+ }
+
+// Pass this if window is not defined yet
+} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
+// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
+// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
+// enough that all such attempts are guarded in a try block.
+"use strict";
+
+var arr = [];
+
+var getProto = Object.getPrototypeOf;
+
+var slice = arr.slice;
+
+var flat = arr.flat ? function( array ) {
+ return arr.flat.call( array );
+} : function( array ) {
+ return arr.concat.apply( [], array );
+};
+
+
+var push = arr.push;
+
+var indexOf = arr.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var fnToString = hasOwn.toString;
+
+var ObjectFunctionString = fnToString.call( Object );
+
+var support = {};
+
+var isFunction = function isFunction( obj ) {
+
+ // Support: Chrome <=57, Firefox <=52
+ // In some browsers, typeof returns "function" for HTML