From 6306ca499433c45b58a02f1cf3a76cbafbc4a391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82=C4=99biowski-Owczarek?= Date: Wed, 14 Dec 2022 01:41:31 +0100 Subject: [PATCH] Selector: Inline Sizzle into the selector module: 3.x version (#5113) This commit removes Sizzle from jQuery, inlining its code & removing obsolete workarounds where applicable. The Sizzle AUTHORS.txt file has been merged with the jQuery one - people are sorted by their first contributions to either of the two repositories. The main `selector` module can be disabled in favor of `selector-native` via: grunt custom:-selector For backwards compatibility, the legacy `sizzle` alias is also supported (it will be dropped in jQuery `4.0.0`): grunt custom:-selector Sizzle tests have been ported to jQuery ones. Ones that are not compatible with the `selector-native` module are disabled if the regular selector module is excluded. Backwards compatibility is still kept for all `Sizzle` utils - they continue to be available under `jQuery.find` - but the primary implementation is now attached directly to jQuery. Some selector utils shared by `selector` & `selector-native` have been extracted & deduplicated. `jQuery.text` and `jQuery.isXMLDoc` have been moved to the `core` module. The commit reduces the gzipped jQuery size by 851 bytes compared to the `3.x-stable` branch. Closes gh-5113 Ref gh-4395 Ref gh-4406 --- .github/workflows/node.js.yml | 4 +- AUTHORS.txt | 181 +- Gruntfile.js | 8 +- README.md | 10 +- build/release.js | 9 - build/release/dist.js | 5 - build/release/ensure-sizzle.js | 35 - build/tasks/build.js | 55 +- dist/.eslintrc.json | 15 +- external/sizzle/LICENSE.txt | 36 - external/sizzle/dist/sizzle.js | 2543 ----------------- external/sizzle/dist/sizzle.min.js | 3 - external/sizzle/dist/sizzle.min.map | 1 - package.json | 5 +- src/.eslintrc.json | 7 + src/core.js | 41 +- src/core/isAttached.js | 2 +- src/core/var/rhtml.js | 7 + src/manipulation.js | 3 +- src/selector-native.js | 123 +- src/selector-sizzle.js | 19 - src/selector.js | 2129 +++++++++++++- src/selector/contains.js | 21 + src/selector/escapeSelector.js | 31 + src/traversing.js | 2 +- src/var/pop.js | 9 + src/var/sort.js | 9 + src/var/splice.js | 9 + src/wrapper.js | 3 - test/.eslintrc.json | 1 + test/data/qunit-fixture.html | 84 +- .../{sizzle_cache.html => cache.html} | 2 +- test/data/selector/mixed_sort.html | 22 + test/data/testinit.js | 60 +- test/unit/attributes.js | 16 +- test/unit/core.js | 16 +- test/unit/css.js | 17 +- test/unit/effects.js | 16 +- test/unit/event.js | 29 +- test/unit/manipulation.js | 14 +- test/unit/selector.js | 2090 +++++++++++++- test/unit/support.js | 583 ++-- test/unit/traversing.js | 95 +- 43 files changed, 5058 insertions(+), 3312 deletions(-) delete mode 100644 build/release/ensure-sizzle.js delete mode 100644 external/sizzle/LICENSE.txt delete mode 100644 external/sizzle/dist/sizzle.js delete mode 100644 external/sizzle/dist/sizzle.min.js delete mode 100644 external/sizzle/dist/sizzle.min.map create mode 100644 src/core/var/rhtml.js delete mode 100644 src/selector-sizzle.js create mode 100644 src/selector/contains.js create mode 100644 src/selector/escapeSelector.js create mode 100644 src/var/pop.js create mode 100644 src/var/sort.js create mode 100644 src/var/splice.js rename test/data/selector/{sizzle_cache.html => cache.html} (92%) create mode 100644 test/data/selector/mixed_sort.html diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index b464caf52..41f29384a 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -28,9 +28,9 @@ jobs: NODE_VERSION: "16.x" NPM_SCRIPT: "test:no-deprecated" BROWSERS: "ChromeHeadless" - - NAME: "Browser tests: no-Sizzle build, Chrome stable" + - NAME: "Browser tests: selector-native build, Chrome stable" NODE_VERSION: "16.x" - NPM_SCRIPT: "test:no-sizzle" + NPM_SCRIPT: "test:selector-native" BROWSERS: "ChromeHeadless" - NAME: "Browser tests: AMD build, Chrome stable" NODE_VERSION: "16.x" diff --git a/AUTHORS.txt b/AUTHORS.txt index d13860348..1b459ec3b 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -18,16 +18,24 @@ David Serduke Richard D. Worth Scott González Ariel Flesler +Cheah Chu Yeow +Andrew Chalkley +Fabio Buffoni +Stefan Bauckmeier  Jon Evans TJ Holowaychuk +Riccardo De Agostini Michael Bensoussan -Robert Katić Louis-Rémi Babé -Earle Castledine +Robert Katić Damian Janowski +Anton Kovalyov +Dušan B. Jovanovic +Earle Castledine Rich Dougherty Kim Dalsgaard Andrea Giammarchi +Fabian Jakobs Mark Gibson Karl Swedberg Justin Meyer @@ -35,9 +43,10 @@ Ben Alman James Padolsey David Petersen Batiste Bieler +Jake Archibald Alexander Farkas -Rick Waldron Filipe Fortes +Rick Waldron Neeraj Singh Paul Irish Iraê Carvalho @@ -45,23 +54,24 @@ Matt Curry Michael Monteleone Noah Sloan Tom Viner +J. Ryan Stinnett Douglas Neiner Adam J. Sontag +Heungsub Lee Dave Reed -Ralph Whitbeck Carl Fürstenberg Jacob Wright -J. Ryan Stinnett +Ralph Whitbeck unknown temp01 -Heungsub Lee Colin Snover +Jared Grippe Ryan W Tenney +Alex Sexton Pinhook Ron Otten Jephte Clain Anton Matzneller -Alex Sexton Dan Heberden Henri Wiechers Russell Holbrook @@ -71,21 +81,19 @@ Scott Jehl James Burke Jonas Pfenniger Xavi Ramirez -Jared Grippe Sylvester Keil Brandon Sterne Mathias Bynens +Lee Carpenter Timmy Willison <4timmywil@gmail.com> Corey Frang Digitalxero -Anton Kovalyov David Murdoch Josh Varner Charles McNulty Jordan Boesch Jess Thrysoee Michael Murray -Lee Carpenter Alexis Abril Rob Morgan John Firebaugh @@ -105,12 +113,13 @@ Timo Tijhof Steen Nielsen Anton Ryzhov Shi Chuan +Matt Mueller Berker Peksag Toby Brain -Matt Mueller Justin Daniel Herman Oleg Gaidarenko +Rock Hymas Richard Gibson Rafaël Blais Masson cmc3cn <59194618@qq.com> @@ -122,6 +131,7 @@ Andrew E Monat Oskari Joao Henrique de Andrade Bruni tsinha +Dominik D. Geyer Matt Farmer Trey Hunner Jason Moon @@ -130,164 +140,180 @@ Kris Borchers Vladimir Zhuravlev Jacob Thornton Chad Killingsworth +Vitya Muhachev Nowres Rafid David Benjamin +Alan Plum Uri Gilad Chris Faulkner +Marcel Greter Elijah Manor Daniel Chatfield +Daniel Gálvez Nikita Govorov Wesley Walser Mike Pennisi +Matthias Jäggli +Devin Cooper Markus Staab Dave Riddle Callum Macrae +Jonathan Sampson Benjamin Truyman +Jay Merrifield James Huston +Sai Lung Wong Erick Ruiz de Chávez David Bonner +Allen J Schmidt Jr Akintayo Akinwunmi MORGAN Ismail Khair Carl Danley Mike Petrovich Greg Lavallee -Daniel Gálvez -Sai Lung Wong Tom H Fuertes Roland Eckl -Jay Merrifield -Allen J Schmidt Jr -Jonathan Sampson -Marcel Greter -Matthias Jäggli -David Fox Yiming He -Devin Cooper +David Fox +Bennett Sorbo Paul Ramos Rod Vagg -Bennett Sorbo Sebastian Burkhard Zachary Adam Kaplan +Adam Coulombe nanto_vi nanto Danil Somsikov Ryunosuke SATO +Diego Tres Jean Boussier -Adam Coulombe Andrew Plummer Mark Raddatz +Pascal Borreli Isaac Z. Schlueter Karl Sieburg -Pascal Borreli Nguyen Phuc Lam Dmitry Gusev -Michał Gołębiowski-Owczarek -Li Xudong Steven Benner -Tom H Fuertes +Li Xudong +Michał Gołębiowski-Owczarek Renato Oliveira dos Santos +Frederic Junod +Tom H Fuertes +Mitch Foley ros3cin -Jason Bedard Kyle Robinson Young +John Paul +Jason Bedard Chris Talkington Eddie Monge Terry Jones Jason Merino +Dan Burzo Jeremy Dunck Chris Price Guy Bedford +njhamann +Goare Mao Amey Sakhadeo Mike Sidorov Anthony Ryan -Dominik D. Geyer -George Kats Lihan Li +George Kats +Dongseok Paeng Ronny Springer -Chris Antaki -Marian Sollmann -njhamann Ilya Kantor +Marian Sollmann +Chris Antaki David Hong -John Paul Jakob Stoeck Christopher Jones Forbes Lindesay S. Andrew Sheppard Leonardo Balter +Rodrigo Rosenfeld Rosas +Daniel Husar +Philip Jägenstedt +John Hoven Roman Reiß Benjy Cui -Rodrigo Rosenfeld Rosas -John Hoven -Philip Jägenstedt Christian Kosmowski +David Corbacho Liang Peng TJ VanToll -Senya Pugach Aurelio De Rosa +Senya Pugach +Dan Hart Nazar Mokrynskyi +Benjamin Tan Amit Merchant Jason Bedard -Arthur Verschaeve -Dan Hart -Bin Xin -David Corbacho Veaceslav Grimalschi -Daniel Husar -Frederic Hemberger -Ben Toews -Aditya Raghavan -Victor Homyakov +Richard McDaniel +Arthur Verschaeve Shivaji Varma +Ben Toews +Bin Xin +Neftaly Hernandez +T.J. Crowder Nicolas HENRY +Frederic Hemberger +Victor Homyakov +Aditya Raghavan Anne-Gaelle Colom -George Mauer Leonardo Braga +George Mauer Stephen Edgar Thomas Tortorini -Winston Howes +Jörn Wagner Jon Hester +Colin Frick +Winston Howes Alexander O'Mara -Bastian Buchholz -Arthur Stolyar -Calvin Metcalf -Mu Haibao -Richard McDaniel Chris Rebert +Bastian Buchholz +Mu Haibao +Calvin Metcalf +Arthur Stolyar Gabriel Schulhof Gilad Peleg +Julian Alexander Murillo +Kevin Kirsche Martin Naumann +Yongwoo Jeon +John-David Dalton Marek Lewandowski Bruno Pérel -Reed Loden Daniel Nill -Yongwoo Jeon +Reed Loden Sean Henderson +Gary Ye Richard Kraaijenhagen Connor Atherton -Gary Ye Christian Grete +Tom von Clef Liza Ramo -Julian Alexander Murillo Joelle Fleurantin -Jae Sung Park -Jun Sun -Josh Soref -Henry Wong +Steve Mao Jon Dufresne +Jae Sung Park +Josh Soref +Saptak Sengupta +Henry Wong +Jun Sun Martijn W. van der Lee Devin Wilson -Steve Mao +Damian Senn Zack Hall -Bernhard M. Wiedemann -Todor Prikumov -Jha Naman -William Robinet -Alexander Lisianoi Vitaliy Terziev +Todor Prikumov +Bernhard M. Wiedemann +Jha Naman +Alexander Lisianoi +William Robinet Joe Trumbull Alexander K -Damian Senn Ralin Chimev Felipe Sateler Christophe Tafani-Dereeper @@ -295,31 +321,36 @@ Manoj Kumar David Broder-Rodgers Alex Louden Alex Padilla -南漂一卒 karan-96 +南漂一卒 +Erik Lax Boom Lee Andreas Solleder -CDAGaming Pierre Spring Shashanka Nataraj -Erik Lax +CDAGaming Matan Kotler-Berkowitz <205matan@gmail.com> Jordan Beland Henry Zhu -Saptak Sengupta Nilton Cesar basil.belokon +Andrey Meshkov tmybr11 Luis Emilio Velasco Sanchez Ed S Bert Zhang +Sébastien Règne +wartmanm <3869625+wartmanm@users.noreply.github.com> +Siddharth Dungarwal +abnud1 Andrei Fangli Marja Hölttä -abnud1 buddh4 -Pat O'Callaghan -Ahmed.S.ElAfifi +Hoang Wonseop Kim +Pat O'Callaghan +JuanMa Ruiz +Ahmed.S.ElAfifi Christian Oliff Christian Wenz Sean Robinson diff --git a/Gruntfile.js b/Gruntfile.js index f93c3a2b5..cc904cdc0 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -61,8 +61,7 @@ module.exports = function( grunt ) { all: { dest: "dist/jquery.js", minimum: [ - "core", - "selector" + "core" ], // Exclude specified modules if the module matching the key is removed @@ -76,7 +75,7 @@ module.exports = function( grunt ) { include: [ "core/ready-no-deferred" ] }, event: [ "deprecated/ajax-event-alias", "deprecated/event" ], - sizzle: [ "css/hiddenVisibleSelectors", "effects/animatedSelector" ] + selector: [ "css/hiddenVisibleSelectors", "effects/animatedSelector" ] } } }, @@ -86,9 +85,6 @@ module.exports = function( grunt ) { destPrefix: "external" }, files: { - "sizzle/dist": "sizzle/dist", - "sizzle/LICENSE.txt": "sizzle/LICENSE.txt", - "core-js/core-js.js": "core-js/client/core.min.js", "core-js/LICENSE.txt": "core-js/LICENSE", diff --git a/README.md b/README.md index c05254e30..f92573666 100644 --- a/README.md +++ b/README.md @@ -106,11 +106,13 @@ Some example modules that can be excluded are: - **exports/global**: Exclude the attachment of global jQuery variables ($ and jQuery) to the window. - **exports/amd**: Exclude the AMD definition. -As a special case, you may also replace Sizzle by using a special flag `grunt custom:-sizzle`. +As a special case, you may also replace the full jQuery `selector` module by using a special flag `grunt custom:-selector`. -- **sizzle**: The Sizzle selector engine. When this module is excluded, it is replaced by a rudimentary selector engine based on the browser's `querySelectorAll` method that does not support jQuery selector extensions or enhanced semantics. See the [selector-native.js](https://github.com/jquery/jquery/blob/main/src/selector-native.js) file for details. +- **selector**: The full jQuery selector engine. When this module is excluded, it is replaced by a rudimentary selector engine based on the browser's `querySelectorAll` method that does not support jQuery selector extensions or enhanced semantics. See the [selector-native.js](https://github.com/jquery/jquery/blob/main/src/selector-native.js) file for details. -*Note*: Excluding Sizzle will also exclude all jQuery selector extensions (such as `effects/animatedSelector` and `css/hiddenVisibleSelectors`). +For backwards compatibility purposes, the name `sizzle` is recognized as the alias for `selector`. + +*Note*: Excluding the full `selector` module will also exclude all jQuery selector extensions (such as `effects/animatedSelector` and `css/hiddenVisibleSelectors`). The build process shows a message for each dependent module it excludes or includes. @@ -167,7 +169,7 @@ There is also a special alias to generate a build with the same configuration as grunt custom:slim ``` -For questions or requests regarding custom builds, please start a thread on the [Developing jQuery Core](https://forum.jquery.com/developing-jquery-core) section of the forum. Due to the combinatorics and custom nature of these builds, they are not regularly tested in jQuery's unit test process. The non-Sizzle selector engine currently does not pass unit tests because it is missing too much essential functionality. +For questions or requests regarding custom builds, please start a thread on the [Developing jQuery Core](https://forum.jquery.com/developing-jquery-core) section of the forum. Due to the combinatorics and custom nature of these builds, they are not regularly tested in jQuery's unit test process. Running the Unit Tests -------------------------------------- diff --git a/build/release.js b/build/release.js index 6b22d95c0..3b3ca16a3 100644 --- a/build/release.js +++ b/build/release.js @@ -18,7 +18,6 @@ module.exports = function( Release ) { ]; const cdn = require( "./release/cdn" ); const dist = require( "./release/dist" ); - const ensureSizzle = require( "./release/ensure-sizzle" ); const npmTags = Release.npmTags; @@ -26,14 +25,6 @@ module.exports = function( Release ) { npmPublish: true, issueTracker: "github", - /** - * Ensure the repo is in a proper state before release - * @param {Function} callback - */ - checkRepoState: function( callback ) { - ensureSizzle( Release, callback ); - }, - /** * Set the version in the src folder for distributing AMD */ diff --git a/build/release/dist.js b/build/release/dist.js index 3bbccd41a..eb8adc7e7 100644 --- a/build/release/dist.js +++ b/build/release/dist.js @@ -69,7 +69,6 @@ module.exports = function( Release, files, complete ) { // Copy dist files const distFolder = `${ Release.dir.dist }/dist`; - const externalFolder = `${ Release.dir.dist }/external`; const readme = await fs.readFile( `${ Release.dir.repo }/build/fixtures/README.md`, "utf8" ); const rmIgnore = [ ...files, "node_modules" ] @@ -93,10 +92,6 @@ module.exports = function( Release, files, complete ) { shell.cp( "-f", `${ Release.dir.repo }/${ file }`, distFolder ); } ); - // Copy Sizzle - shell.mkdir( "-p", externalFolder ); - shell.cp( "-rf", `${ Release.dir.repo }/external/sizzle`, externalFolder ); - // Copy other files extras.forEach( function( file ) { shell.cp( "-rf", `${ Release.dir.repo }/${ file }`, Release.dir.dist ); diff --git a/build/release/ensure-sizzle.js b/build/release/ensure-sizzle.js deleted file mode 100644 index 605b141ba..000000000 --- a/build/release/ensure-sizzle.js +++ /dev/null @@ -1,35 +0,0 @@ -"use strict"; - -var fs = require( "fs" ), - chalk = require( "chalk" ), - sizzleLoc = __dirname + "/../../external/sizzle/dist/sizzle.js", - rversion = /Engine v(\d+\.\d+\.\d+(?:-[-\.\d\w]+)?)/; - -/** - * Ensure the /src folder has the latest tag of Sizzle - * @param {Object} Release - * @param {Function} callback - */ -function ensureSizzle( Release, callback ) { - console.log(); - console.log( "Checking Sizzle version..." ); - var match = rversion.exec( fs.readFileSync( sizzleLoc, "utf8" ) ), - version = match ? match[ 1 ] : "Not Found", - latest = Release.exec( { - command: "npm info sizzle version", - silent: true - } ); - - if ( version !== latest ) { - console.log( - "The Sizzle version in the src folder (" + chalk.red( version ) + - ") is not the latest tag (" + chalk.green( latest ) + ")." - ); - Release.confirm( callback ); - } else { - console.log( "Sizzle is latest (" + chalk.green( latest ) + ")" ); - callback(); - } -} - -module.exports = ensureSizzle; diff --git a/build/tasks/build.js b/build/tasks/build.js index 71c20a81a..01b19e4d4 100644 --- a/build/tasks/build.js +++ b/build/tasks/build.js @@ -72,13 +72,6 @@ module.exports = function( grunt ) { ) .replace( rdefineEnd, "" ); - // Sizzle treatment - } else if ( /\/sizzle$/.test( name ) ) { - contents = "var Sizzle =\n" + contents - - // Remove EXPOSE lines from Sizzle - .replace( /\/\/\s*EXPOSE[\w\W]*\/\/\s*EXPOSE/, "return Sizzle;" ); - } else { contents = contents @@ -101,7 +94,7 @@ module.exports = function( grunt ) { // Remove empty definitions contents = contents - .replace( /define\(\[[^\]]*\]\)[\W\n]+$/, "" ); + .replace( /define\(\s*\[[^\]]*\]\s*\)[\W\n]+$/, "" ); } // AMD Name @@ -178,14 +171,19 @@ module.exports = function( grunt ) { * Adds the specified module to the excluded or included list, depending on the flag * @param {String} flag A module path relative to * the src directory starting with + or - to indicate - * whether it should included or excluded + * whether it should be included or excluded */ excluder = function( flag ) { var additional, - m = /^(\+|\-|)([\w\/-]+)$/.exec( flag ), + m = /^(\+|-|)([\w\/-]+)$/.exec( flag ), exclude = m[ 1 ] === "-", module = m[ 2 ]; + // Recognize the legacy `sizzle` alias + if ( module === "sizzle" ) { + module = "selector"; + } + if ( exclude ) { // Can't exclude certain modules @@ -200,7 +198,16 @@ module.exports = function( grunt ) { // These are the removable dependencies // It's fine if the directory is not there try { - excludeList( fs.readdirSync( srcFolder + module ), module ); + + // `selector` is a special case as we don't just remove + // the module, but we replace it with `selector-native` + // which re-uses parts of the `src/selector` folder. + if ( module !== "selector" ) { + excludeList( + fs.readdirSync( `${ srcFolder }/${ module }` ), + module + ); + } } catch ( e ) { grunt.verbose.writeln( e ); } @@ -218,11 +225,6 @@ module.exports = function( grunt ) { } } else { grunt.log.error( "Module \"" + module + "\" is a minimum requirement." ); - if ( module === "selector" ) { - grunt.log.error( - "If you meant to replace Sizzle, use -sizzle instead." - ); - } } } else { grunt.log.writeln( flag ); @@ -259,17 +261,16 @@ module.exports = function( grunt ) { excluder( flag ); } - // Handle Sizzle exclusion - // Replace with selector-native - if ( ( index = excluded.indexOf( "sizzle" ) ) > -1 ) { - config.rawText.selector = "define(['./selector-native']);"; - excluded.splice( index, 1 ); + // Handle full selector module exclusion. + // Replace with selector-native. + if ( excluded.indexOf( "selector" ) > -1 ) { + config.rawText.selector = "define([ \"./selector-native\" ]);"; } // Replace exports/global with a noop noConflict if ( ( index = excluded.indexOf( "exports/global" ) ) > -1 ) { - config.rawText[ "exports/global" ] = "define(['../core']," + - "function( jQuery ) {\njQuery.noConflict = function() {};\n});"; + config.rawText[ "exports/global" ] = "define( [\n\t\"../core\"\n], " + + "function( jQuery ) {\n\tjQuery.noConflict = function() {};\n} );"; excluded.splice( index, 1 ); } @@ -311,9 +312,11 @@ module.exports = function( grunt ) { if ( !optIn ) { // Overwrite the default inclusions with the explicit ones provided - config.rawText.jquery = "define([" + - ( included.length ? included.join( "," ) : "" ) + - "]);"; + config.rawText.jquery = "define( [\n" + + ( included.length ? + included.map( module => "\t\"./" + module + "\"" ).join( ",\n" ) : + "" ) + + "\n] );"; } // Trace dependencies and concatenate files diff --git a/dist/.eslintrc.json b/dist/.eslintrc.json index a86695799..50a3ba77a 100644 --- a/dist/.eslintrc.json +++ b/dist/.eslintrc.json @@ -14,20 +14,7 @@ "rules": { // That is okay for the built version "no-multiple-empty-lines": "off", - "one-var": "off", - - // Sizzle is not compatible with jQuery code style - "no-nested-ternary": "off", - "no-unused-expressions": "off", - "no-unused-vars": "off", - "lines-around-comment": "off", - "space-in-parens": "off", - "camelcase": "off", - "computed-property-spacing": "off", - "max-len": "off", - "dot-notation": "off", - "semi-spacing": "off", - "brace-style": "off" + "one-var": "off" } } ] diff --git a/external/sizzle/LICENSE.txt b/external/sizzle/LICENSE.txt deleted file mode 100644 index 88fcd178b..000000000 --- a/external/sizzle/LICENSE.txt +++ /dev/null @@ -1,36 +0,0 @@ -Copyright JS Foundation and other contributors, https://js.foundation/ - -This software consists of voluntary contributions made by many -individuals. For exact contribution history, see the revision history -available at https://github.com/jquery/sizzle - -The following license applies to all parts of this software except as -documented below: - -==== - -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. - -==== - -All files located in the node_modules and external directories are -externally maintained libraries used by this software which have their -own licenses; we recommend you read them, as their terms may differ from -the terms above. diff --git a/external/sizzle/dist/sizzle.js b/external/sizzle/dist/sizzle.js deleted file mode 100644 index f6cf278ac..000000000 --- a/external/sizzle/dist/sizzle.js +++ /dev/null @@ -1,2543 +0,0 @@ -/*! - * Sizzle CSS Selector Engine v2.3.8 - * https://sizzlejs.com/ - * - * Copyright JS Foundation and other contributors - * Released under the MIT license - * https://js.foundation/ - * - * Date: 2022-11-16 - */ -( function( window ) { -var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + 1 * new Date(), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - nonnativeSelectorCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // Instance methods - hasOwn = ( {} ).hasOwnProperty, - arr = [], - pop = arr.pop, - pushNative = arr.push, - push = arr.push, - slice = arr.slice, - - // Use a stripped-down indexOf as it's faster than native - // https://jsperf.com/thor-indexof-vs-for/5 - indexOf = function( list, elem ) { - var i = 0, - len = list.length; - for ( ; i < len; i++ ) { - if ( list[ i ] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + - "ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - - // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram - identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + - "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + - - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - - // "Attribute values must be CSS identifiers [capture 5] - // or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + - whitespace + "*\\]", - - pseudos = ":(" + identifier + ")(?:\\((" + - - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + - whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + - "*" ), - rdescend = new RegExp( whitespace + "|>" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + identifier + ")" ), - "CLASS": new RegExp( "^\\.(" + identifier + ")" ), - "TAG": new RegExp( "^(" + identifier + "|[*])" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + - whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + - whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + - "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + - "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rhtml = /HTML$/i, - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - - // CSS escapes - // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), - funescape = function( escape, nonHex ) { - var high = "0x" + escape.slice( 1 ) - 0x10000; - - return nonHex ? - - // Strip the backslash prefix from a non-hex escape sequence - nonHex : - - // Replace a hexadecimal escape sequence with the encoded Unicode code point - // Support: IE <=11+ - // For values outside the Basic Multilingual Plane (BMP), manually construct a - // surrogate pair - high < 0 ? - String.fromCharCode( high + 0x10000 ) : - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }, - - // CSS string/identifier serialization - // https://drafts.csswg.org/cssom/#common-serializing-idioms - rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, - fcssescape = function( ch, asCodePoint ) { - if ( asCodePoint ) { - - // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER - if ( ch === "\0" ) { - return "\uFFFD"; - } - - // Control characters and (dependent upon position) numbers get escaped as code points - return ch.slice( 0, -1 ) + "\\" + - ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; - } - - // Other potentially-special ASCII characters get backslash-escaped - return "\\" + ch; - }, - - // Used for iframes - // See setDocument() - // Removing the function wrapper causes a "Permission Denied" - // error in IE - unloadHandler = function() { - setDocument(); - }, - - inDisabledFieldset = addCombinator( - function( elem ) { - return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; - }, - { dir: "parentNode", next: "legend" } - ); - -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - ( arr = slice.call( preferredDoc.childNodes ) ), - preferredDoc.childNodes - ); - - // Support: Android<4.0 - // Detect silently failing push.apply - // eslint-disable-next-line no-unused-expressions - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - pushNative.apply( target, slice.call( els ) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - - // Can't trust NodeList.length - while ( ( target[ j++ ] = els[ i++ ] ) ) {} - target.length = j - 1; - } - }; -} - -function Sizzle( selector, context, results, seed ) { - var m, i, elem, nid, match, groups, newSelector, - newContext = context && context.ownerDocument, - - // nodeType defaults to 9, since context defaults to document - nodeType = context ? context.nodeType : 9; - - results = results || []; - - // Return early from calls with invalid selector or context - if ( typeof selector !== "string" || !selector || - nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { - - return results; - } - - // Try to shortcut find operations (as opposed to filters) in HTML documents - if ( !seed ) { - setDocument( context ); - context = context || document; - - if ( documentIsHTML ) { - - // If the selector is sufficiently simple, try using a "get*By*" DOM method - // (excepting DocumentFragment context, where the methods don't exist) - if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { - - // ID selector - if ( ( m = match[ 1 ] ) ) { - - // Document context - if ( nodeType === 9 ) { - if ( ( elem = context.getElementById( m ) ) ) { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - - // Element context - } else { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( newContext && ( elem = newContext.getElementById( m ) ) && - contains( context, elem ) && - elem.id === m ) { - - results.push( elem ); - return results; - } - } - - // Type selector - } else if ( match[ 2 ] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Class selector - } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && - context.getElementsByClassName ) { - - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // Take advantage of querySelectorAll - if ( support.qsa && - !nonnativeSelectorCache[ selector + " " ] && - ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && - - // Support: IE 8 only - // Exclude object elements - ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { - - newSelector = selector; - newContext = context; - - // qSA considers elements outside a scoping root when evaluating child or - // descendant combinators, which is not what we want. - // In such cases, we work around the behavior by prefixing every selector in the - // list with an ID selector referencing the scope context. - // The technique has to be used as well when a leading combinator is used - // as such selectors are not recognized by querySelectorAll. - // Thanks to Andrew Dupont for this technique. - if ( nodeType === 1 && - ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { - - // Expand context for sibling selectors - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || - context; - - // We can use :scope instead of the ID hack if the browser - // supports it & if we're not changing the context. - if ( newContext !== context || !support.scope ) { - - // Capture the context ID, setting it first if necessary - if ( ( nid = context.getAttribute( "id" ) ) ) { - nid = nid.replace( rcssescape, fcssescape ); - } else { - context.setAttribute( "id", ( nid = expando ) ); - } - } - - // Prefix every selector in the list - groups = tokenize( selector ); - i = groups.length; - while ( i-- ) { - groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + - toSelector( groups[ i ] ); - } - newSelector = groups.join( "," ); - } - - try { - - // `qSA` may not throw for unrecognized parts using forgiving parsing: - // https://drafts.csswg.org/selectors/#forgiving-selector - // like the `:has()` pseudo-class: - // https://drafts.csswg.org/selectors/#relational - // `CSS.supports` is still expected to return `false` then: - // https://drafts.csswg.org/css-conditional-4/#typedef-supports-selector-fn - // https://drafts.csswg.org/css-conditional-4/#dfn-support-selector - if ( support.cssSupportsSelector && - - // eslint-disable-next-line no-undef - !CSS.supports( "selector(" + newSelector + ")" ) ) { - - // Support: IE 11+ - // Throw to get to the same code path as an error directly in qSA. - // Note: once we only support browser supporting - // `CSS.supports('selector(...)')`, we can most likely drop - // the `try-catch`. IE doesn't implement the API. - throw new Error(); - } - - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch ( qsaError ) { - nonnativeSelectorCache( selector, true ); - } finally { - if ( nid === expando ) { - context.removeAttribute( "id" ); - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} - -/** - * Create key-value caches of limited size - * @returns {function(string, object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; - - function cache( key, value ) { - - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return ( cache[ key + " " ] = value ); - } - return cache; -} - -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} - -/** - * Support testing using an element - * @param {Function} fn Passed the created element and returns a boolean result - */ -function assert( fn ) { - var el = document.createElement( "fieldset" ); - - try { - return !!fn( el ); - } catch ( e ) { - return false; - } finally { - - // Remove from its parent by default - if ( el.parentNode ) { - el.parentNode.removeChild( el ); - } - - // release memory in IE - el = null; - } -} - -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split( "|" ), - i = arr.length; - - while ( i-- ) { - Expr.attrHandle[ arr[ i ] ] = handler; - } -} - -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - a.sourceIndex - b.sourceIndex; - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( ( cur = cur.nextSibling ) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; -} - -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return ( name === "input" || name === "button" ) && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for :enabled/:disabled - * @param {Boolean} disabled true for :disabled; false for :enabled - */ -function createDisabledPseudo( disabled ) { - - // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable - return function( elem ) { - - // Only certain elements can match :enabled or :disabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled - if ( "form" in elem ) { - - // Check for inherited disabledness on relevant non-disabled elements: - // * listed form-associated elements in a disabled fieldset - // https://html.spec.whatwg.org/multipage/forms.html#category-listed - // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled - // * option elements in a disabled optgroup - // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled - // All such elements have a "form" property. - if ( elem.parentNode && elem.disabled === false ) { - - // Option elements defer to a parent optgroup if present - if ( "label" in elem ) { - if ( "label" in elem.parentNode ) { - return elem.parentNode.disabled === disabled; - } else { - return elem.disabled === disabled; - } - } - - // Support: IE 6 - 11 - // Use the isDisabled shortcut property to check for disabled fieldset ancestors - return elem.isDisabled === disabled || - - // Where there is no isDisabled, check manually - /* jshint -W018 */ - elem.isDisabled !== !disabled && - inDisabledFieldset( elem ) === disabled; - } - - return elem.disabled === disabled; - - // Try to winnow out elements that can't be disabled before trusting the disabled property. - // Some victims get caught in our net (label, legend, menu, track), but it shouldn't - // even exist on them, let alone have a boolean value. - } else if ( "label" in elem ) { - return elem.disabled === disabled; - } - - // Remaining elements are neither :enabled nor :disabled - return false; - }; -} - -/** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ -function createPositionalPseudo( fn ) { - return markFunction( function( argument ) { - argument = +argument; - return markFunction( function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ ( j = matchIndexes[ i ] ) ] ) { - seed[ j ] = !( matches[ j ] = seed[ j ] ); - } - } - } ); - } ); -} - -/** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ -function testContext( context ) { - return context && typeof context.getElementsByTagName !== "undefined" && context; -} - -// Expose support vars for convenience -support = Sizzle.support = {}; - -/** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ -isXML = Sizzle.isXML = function( elem ) { - var namespace = elem && elem.namespaceURI, - docElem = elem && ( elem.ownerDocument || elem ).documentElement; - - // Support: IE <=8 - // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes - // https://bugs.jquery.com/ticket/4833 - return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); -}; - -/** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ -setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, subWindow, - doc = node ? node.ownerDocument || node : preferredDoc; - - // Return early if doc is invalid or already selected - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } - - // Update global variables - document = doc; - docElem = document.documentElement; - documentIsHTML = !isXML( document ); - - // Support: IE 9 - 11+, Edge 12 - 18+ - // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( preferredDoc != document && - ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { - - // Support: IE 11, Edge - if ( subWindow.addEventListener ) { - subWindow.addEventListener( "unload", unloadHandler, false ); - - // Support: IE 9 - 10 only - } else if ( subWindow.attachEvent ) { - subWindow.attachEvent( "onunload", unloadHandler ); - } - } - - // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, - // Safari 4 - 5 only, Opera <=11.6 - 12.x only - // IE/Edge & older browsers don't support the :scope pseudo-class. - // Support: Safari 6.0 only - // Safari 6.0 supports :scope but it's an alias of :root there. - support.scope = assert( function( el ) { - docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); - return typeof el.querySelectorAll !== "undefined" && - !el.querySelectorAll( ":scope fieldset div" ).length; - } ); - - // Support: Chrome 105+, Firefox 104+, Safari 15.4+ - // Make sure forgiving mode is not used in `CSS.supports( "selector(...)" )`. - // - // `:is()` uses a forgiving selector list as an argument and is widely - // implemented, so it's a good one to test against. - support.cssSupportsSelector = assert( function() { - /* eslint-disable no-undef */ - - return CSS.supports( "selector(*)" ) && - - // Support: Firefox 78-81 only - // In old Firefox, `:is()` didn't use forgiving parsing. In that case, - // fail this test as there's no selector to test against that. - // `CSS.supports` uses unforgiving parsing - document.querySelectorAll( ":is(:jqfake)" ) && - - // `*` is needed as Safari & newer Chrome implemented something in between - // for `:has()` - it throws in `qSA` if it only contains an unsupported - // argument but multiple ones, one of which is supported, are fine. - // We want to play safe in case `:is()` gets the same treatment. - !CSS.supports( "selector(:is(*,:jqfake))" ); - - /* eslint-enable */ - } ); - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties - // (excepting IE8 booleans) - support.attributes = assert( function( el ) { - el.className = "i"; - return !el.getAttribute( "className" ); - } ); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert( function( el ) { - el.appendChild( document.createComment( "" ) ); - return !el.getElementsByTagName( "*" ).length; - } ); - - // Support: IE<9 - support.getElementsByClassName = rnative.test( document.getElementsByClassName ); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programmatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert( function( el ) { - docElem.appendChild( el ).id = expando; - return !document.getElementsByName || !document.getElementsByName( expando ).length; - } ); - - // ID filter and find - if ( support.getById ) { - Expr.filter[ "ID" ] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute( "id" ) === attrId; - }; - }; - Expr.find[ "ID" ] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var elem = context.getElementById( id ); - return elem ? [ elem ] : []; - } - }; - } else { - Expr.filter[ "ID" ] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== "undefined" && - elem.getAttributeNode( "id" ); - return node && node.value === attrId; - }; - }; - - // Support: IE 6 - 7 only - // getElementById is not reliable as a find shortcut - Expr.find[ "ID" ] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var node, i, elems, - elem = context.getElementById( id ); - - if ( elem ) { - - // Verify the id attribute - node = elem.getAttributeNode( "id" ); - if ( node && node.value === id ) { - return [ elem ]; - } - - // Fall back on getElementsByName - elems = context.getElementsByName( id ); - i = 0; - while ( ( elem = elems[ i++ ] ) ) { - node = elem.getAttributeNode( "id" ); - if ( node && node.value === id ) { - return [ elem ]; - } - } - } - - return []; - } - }; - } - - // Tag - Expr.find[ "TAG" ] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( tag ); - - // DocumentFragment nodes don't have gEBTN - } else if ( support.qsa ) { - return context.querySelectorAll( tag ); - } - } : - - function( tag, context ) { - var elem, - tmp = [], - i = 0, - - // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too - results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - while ( ( elem = results[ i++ ] ) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See https://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { - - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert( function( el ) { - - var input; - - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // https://bugs.jquery.com/ticket/12359 - docElem.appendChild( el ).innerHTML = "" + - ""; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !el.querySelectorAll( "[selected]" ).length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } - - // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ - if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { - rbuggyQSA.push( "~=" ); - } - - // Support: IE 11+, Edge 15 - 18+ - // IE 11/Edge don't find elements on a `[name='']` query in some cases. - // Adding a temporary attribute to the document before the selection works - // around the issue. - // Interestingly, IE 10 & older don't seem to have the issue. - input = document.createElement( "input" ); - input.setAttribute( "name", "" ); - el.appendChild( input ); - if ( !el.querySelectorAll( "[name='']" ).length ) { - rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + - whitespace + "*(?:''|\"\")" ); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !el.querySelectorAll( ":checked" ).length ) { - rbuggyQSA.push( ":checked" ); - } - - // Support: Safari 8+, iOS 8+ - // https://bugs.webkit.org/show_bug.cgi?id=136851 - // In-page `selector#id sibling-combinator selector` fails - if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { - rbuggyQSA.push( ".#.+[+~]" ); - } - - // Support: Firefox <=3.6 - 5 only - // Old Firefox doesn't throw on a badly-escaped identifier. - el.querySelectorAll( "\\\f" ); - rbuggyQSA.push( "[\\r\\n\\f]" ); - } ); - - assert( function( el ) { - el.innerHTML = "" + - ""; - - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = document.createElement( "input" ); - input.setAttribute( "type", "hidden" ); - el.appendChild( input ).setAttribute( "name", "D" ); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( el.querySelectorAll( "[name=d]" ).length ) { - rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Support: IE9-11+ - // IE's :disabled selector does not pick up the children of disabled fieldsets - docElem.appendChild( el ).disabled = true; - if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Support: Opera 10 - 11 only - // Opera 10-11 does not throw on post-comma invalid pseudos - el.querySelectorAll( "*,:x" ); - rbuggyQSA.push( ",.*:" ); - } ); - } - - if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector ) ) ) ) { - - assert( function( el ) { - - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( el, "*" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( el, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - } ); - } - - if ( !support.cssSupportsSelector ) { - - // Support: Chrome 105+, Safari 15.4+ - // `:has()` uses a forgiving selector list as an argument so our regular - // `try-catch` mechanism fails to catch `:has()` with arguments not supported - // natively like `:has(:contains("Foo"))`. Where supported & spec-compliant, - // we now use `CSS.supports("selector(SELECTOR_TO_BE_TESTED)")` but outside - // that, let's mark `:has` as buggy to always use jQuery traversal for - // `:has()`. - rbuggyQSA.push( ":has" ); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); - - // Element contains another - // Purposefully self-exclusive - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - - // Support: IE <9 only - // IE doesn't have `contains` on `document` so we need to check for - // `documentElement` presence. - // We need to fall back to `a` when `documentElement` is missing - // as `ownerDocument` of elements within `