diff --git a/.gitignore b/.gitignore index 9cf6fff..dfd2175 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules/ .idea +.DS_Store \ No newline at end of file diff --git a/src/preload/LICENSE b/src/preload/LICENSE index 2e176b0..43bd9a1 100644 --- a/src/preload/LICENSE +++ b/src/preload/LICENSE @@ -1,6 +1,6 @@ BSD Zero Clause License -Copyright (c) 2023, Alexander Petros +Copyright (c) 2024, Alexander Petros and Mariss Tubelis Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. diff --git a/src/preload/package-lock.json b/src/preload/package-lock.json index 43774a3..d356bb8 100644 --- a/src/preload/package-lock.json +++ b/src/preload/package-lock.json @@ -1,28 +1,30 @@ { "name": "htmx-ext-preload", - "version": "2.0.0", + "version": "2.0.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "htmx-ext-preload", - "version": "2.0.0", + "version": "2.0.3", "devDependencies": { "chai": "^4.3.10", "chai-dom": "^1.12.0", - "htmx.org": "^2.0.2", + "htmx.org": "^2.0.3", "mocha": "10.1.0", "mocha-chrome": "https://github.com/Telroshan/mocha-chrome", "sinon": "^9.2.4" } }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.7", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -30,105 +32,21 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@sinonjs/commons": { "version": "1.8.6", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } @@ -138,6 +56,7 @@ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -147,6 +66,7 @@ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^1.7.0" } @@ -156,6 +76,7 @@ "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^1.6.0", "lodash.get": "^4.4.2", @@ -163,37 +84,42 @@ } }, "node_modules/@sinonjs/text-encoding": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", - "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", - "dev": true + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", + "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", + "dev": true, + "license": "(Unlicense OR Apache-2.0)" }, "node_modules/@types/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { - "version": "22.3.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.3.0.tgz", - "integrity": "sha512-nrWpWVaDZuaVc5X84xJ0vNrLvomM205oQyLsRt7OHNZbSHslcWsvgFR7O7hire2ZonjLrWBbedmotmIlJDVd6g==", + "version": "22.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.6.tgz", + "integrity": "sha512-tosuJYKrIqjQIlVCM4PEGxOmyg3FCPa/fViuJChnGeEIhjA46oy8FMVoF9su1/v8PNs2a8Q0iFNyOx0uOF91nw==", "dev": true, + "license": "MIT", "dependencies": { - "undici-types": "~6.18.2" + "undici-types": "~6.19.8" } }, "node_modules/@types/normalize-package-data": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -203,6 +129,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -212,6 +139,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -227,6 +155,7 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -239,13 +168,15 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -255,6 +186,7 @@ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -263,13 +195,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -282,6 +216,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -291,6 +226,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -302,13 +238,15 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/camelcase": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.16" }, @@ -321,6 +259,7 @@ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-8.0.2.tgz", "integrity": "sha512-qMKdlOfsjlezMqxkUGGMaWWs17i2HoL15tM+wtx8ld4nLrUwU58TFdvyGOz/piNP842KeO8yXvggVQSdQ828NA==", "dev": true, + "license": "MIT", "dependencies": { "camelcase": "^7.0.0", "map-obj": "^4.3.0", @@ -339,6 +278,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=12.20" }, @@ -351,6 +291,7 @@ "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", "dev": true, + "license": "MIT", "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.3", @@ -369,6 +310,7 @@ "resolved": "https://registry.npmjs.org/chai-dom/-/chai-dom-1.12.0.tgz", "integrity": "sha512-pLP8h6IBR8z1AdeQ+EMcJ7dXPdsax/1Q7gdGZjsnAmSBl3/gItQUYSCo32br1qOy4SlcBjvqId7ilAf3uJ2K1w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.12.0" }, @@ -381,6 +323,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -397,6 +340,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -409,6 +353,7 @@ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, + "license": "MIT", "dependencies": { "get-func-name": "^2.0.2" }, @@ -427,6 +372,7 @@ "url": "https://paulmillr.com/funding/" } ], + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -448,6 +394,7 @@ "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", @@ -466,6 +413,7 @@ "resolved": "https://registry.npmjs.org/chrome-remote-interface/-/chrome-remote-interface-0.32.2.tgz", "integrity": "sha512-3UbFKtEmqApehPQnqdblcggx7KveQphEMKQmdJZsOguE9ylw2N2/9Z7arO7xS55+DBJ/hyP8RrayLt4MMdJvQg==", "dev": true, + "license": "MIT", "dependencies": { "commander": "2.11.x", "ws": "^7.2.0" @@ -479,6 +427,7 @@ "resolved": "https://registry.npmjs.org/chrome-unmirror/-/chrome-unmirror-0.1.0.tgz", "integrity": "sha512-HmQgCN2UTpcrP85oOGnKpkGJFyOUwjsjnPBZlE8MkG0i+NoynGIkuPDZFKh+K4NLQlPiKKde16FAQ98JC1j8ew==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0", "npm": ">=2.0.0" @@ -489,6 +438,7 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -500,6 +450,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -511,25 +462,29 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/commander": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -546,13 +501,15 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/decamelize": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -565,6 +522,7 @@ "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", "dev": true, + "license": "MIT", "dependencies": { "decamelize": "^1.1.0", "map-obj": "^1.0.0" @@ -581,6 +539,7 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -590,6 +549,7 @@ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -600,6 +560,7 @@ "integrity": "sha512-YX2i9XjJ7h5q/aQ/IM9PEwEnDqETAIYbggmdDB3HLTlSgo1CxPsj6pvhPG68rq6SVE0+p+6Ywsm5fTYNrYtBWw==", "deprecated": "Check out `lodash.merge` or `merge-options` instead.", "dev": true, + "license": "MIT", "dependencies": { "is-obj": "^1.0.0" }, @@ -612,6 +573,7 @@ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", "dev": true, + "license": "MIT", "dependencies": { "type-detect": "^4.0.0" }, @@ -624,6 +586,7 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -632,22 +595,25 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -657,6 +623,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -669,6 +636,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -681,6 +649,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -697,6 +666,7 @@ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, + "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } @@ -705,7 +675,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", @@ -713,6 +684,7 @@ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -726,6 +698,7 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -735,6 +708,7 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -744,6 +718,7 @@ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -754,6 +729,7 @@ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -774,6 +750,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -786,6 +763,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -796,6 +774,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -808,6 +787,7 @@ "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -817,6 +797,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -826,6 +807,7 @@ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -838,6 +820,7 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, + "license": "MIT", "bin": { "he": "bin/he" } @@ -847,6 +830,7 @@ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz", "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^7.5.1" }, @@ -855,16 +839,18 @@ } }, "node_modules/htmx.org": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-2.0.2.tgz", - "integrity": "sha512-eUPIpQaWKKstX393XNCRCMJTrqPzikh36Y9RceqsUZLTtlFjFaVDgwZLUsrFk8J2uzZxkkfiy0TE359j2eN6hA==", - "dev": true + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-2.0.3.tgz", + "integrity": "sha512-AeoJUAjkCVVajbfKX+3sVQBTCt8Ct4lif1T+z/tptTXo8+8yyq3QIMQQe/IT+R8ssfrO1I0DeX4CAronzCL6oA==", + "dev": true, + "license": "0BSD" }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, + "license": "MIT", "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -884,6 +870,7 @@ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -897,6 +884,7 @@ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -906,19 +894,22 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -927,10 +918,11 @@ } }, "node_modules/is-core-module": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", - "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dev": true, + "license": "MIT", "dependencies": { "hasown": "^2.0.2" }, @@ -946,6 +938,7 @@ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true, + "license": "MIT", "bin": { "is-docker": "cli.js" }, @@ -961,6 +954,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -970,6 +964,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -979,6 +974,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -991,6 +987,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -1000,6 +997,7 @@ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1009,6 +1007,7 @@ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1018,6 +1017,7 @@ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -1030,6 +1030,7 @@ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, + "license": "MIT", "dependencies": { "is-docker": "^2.0.0" }, @@ -1041,19 +1042,22 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -1065,19 +1069,22 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/just-extend": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1087,6 +1094,7 @@ "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", "dev": true, + "license": "Apache-2.0", "dependencies": { "debug": "^2.6.9", "marky": "^1.2.2" @@ -1097,6 +1105,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -1105,19 +1114,22 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -1132,13 +1144,15 @@ "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -1151,10 +1165,11 @@ } }, "node_modules/loglevel": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz", - "integrity": "sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz", + "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6.0" }, @@ -1168,6 +1183,7 @@ "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, + "license": "MIT", "dependencies": { "get-func-name": "^2.0.1" } @@ -1177,6 +1193,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } @@ -1186,6 +1203,7 @@ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -1197,13 +1215,15 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/meow": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-11.0.0.tgz", "integrity": "sha512-Cl0yeeIrko6d94KpUo1M+0X1sB14ikoaqlIGuTH1fW4I+E3+YljL54/hb/BWmVfrV9tTV9zU04+xjw08Fh2WkA==", "dev": true, + "license": "MIT", "dependencies": { "@types/minimist": "^1.2.2", "camelcase-keys": "^8.0.2", @@ -1230,6 +1250,7 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } @@ -1239,6 +1260,7 @@ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -1248,6 +1270,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -1260,6 +1283,7 @@ "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, + "license": "MIT", "dependencies": { "arrify": "^1.0.1", "is-plain-obj": "^1.1.0", @@ -1274,6 +1298,7 @@ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", @@ -1341,6 +1366,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, + "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -1352,19 +1378,22 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nanoassert": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz", "integrity": "sha512-C40jQ3NzfkP53NsO8kEOFd79p4b9kDXQMwgiY1z8ZwrDZgUyom0AHwGegF4Dm99L+YoYhuaB0ceerUcXmqr1rQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/nanobus": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/nanobus/-/nanobus-4.5.0.tgz", "integrity": "sha512-7sBZo9wthqNJ7QXnfVXZL7fkKJLN55GLOdX+RyZT34UOvxxnFtJe/c7K0ZRLAKOvaY1xJThFFn0Usw2H9R6Frg==", "dev": true, + "license": "MIT", "dependencies": { "nanoassert": "^1.1.0", "nanotiming": "^7.2.0", @@ -1376,6 +1405,7 @@ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", "dev": true, + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -1388,6 +1418,7 @@ "resolved": "https://registry.npmjs.org/nanoscheduler/-/nanoscheduler-1.0.3.tgz", "integrity": "sha512-jBbrF3qdU9321r8n9X7yu18DjP31Do2ItJm3mWrt90wJTrnDO+HXpoV7ftaUglAtjgj9s+OaCxGufbvx6pvbEQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "nanoassert": "^1.1.0" } @@ -1397,6 +1428,7 @@ "resolved": "https://registry.npmjs.org/nanotiming/-/nanotiming-7.3.1.tgz", "integrity": "sha512-l3lC7v/PfOuRWQa8vV29Jo6TG10wHtnthLElFXs4Te4Aas57Fo4n1Q8LH9n+NDh9riOzTVvb2QNBhTS4JUKNjw==", "dev": true, + "license": "MIT", "dependencies": { "nanoassert": "^1.1.0", "nanoscheduler": "^1.0.2" @@ -1407,6 +1439,7 @@ "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^1.7.0", "@sinonjs/fake-timers": "^6.0.0", @@ -1420,6 +1453,7 @@ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^5.0.0", "is-core-module": "^2.8.1", @@ -1435,6 +1469,7 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1444,6 +1479,7 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -1453,6 +1489,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -1468,6 +1505,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -1483,6 +1521,7 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1492,6 +1531,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -1510,6 +1550,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1519,15 +1560,17 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", "dev": true, + "license": "MIT", "dependencies": { "isarray": "0.0.1" } @@ -1537,21 +1580,24 @@ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -1564,6 +1610,7 @@ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -1576,6 +1623,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -1589,6 +1637,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -1601,6 +1650,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -1616,6 +1666,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -1628,6 +1679,7 @@ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.2.tgz", "integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -1640,6 +1692,7 @@ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } @@ -1649,6 +1702,7 @@ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-7.1.0.tgz", "integrity": "sha512-5iOehe+WF75IccPc30bWTbpdDQLOCc3Uu8bi3Dte3Eueij81yx1Mrufk8qBx/YAbR4uL1FdUr+7BKXDwEtisXg==", "dev": true, + "license": "MIT", "dependencies": { "@types/normalize-package-data": "^2.4.1", "normalize-package-data": "^3.0.2", @@ -1667,6 +1721,7 @@ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-9.1.0.tgz", "integrity": "sha512-vaMRR1AC1nrd5CQM0PhlRsO5oc2AAigqr7cCrZ/MW/Rsaflz4RlgzkpL4qoU/z1F6wrbd85iFv1OQj/y5RdGvg==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^6.3.0", "read-pkg": "^7.1.0", @@ -1684,6 +1739,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^7.1.0", "path-exists": "^5.0.0" @@ -1700,6 +1756,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^6.0.0" }, @@ -1715,6 +1772,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^1.0.0" }, @@ -1730,6 +1788,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^4.0.0" }, @@ -1745,6 +1804,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } @@ -1754,6 +1814,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=12.20" }, @@ -1766,6 +1827,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.20" }, @@ -1778,6 +1840,7 @@ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -1790,6 +1853,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -1802,6 +1866,7 @@ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^4.0.1", "is-core-module": "^2.5.0", @@ -1817,6 +1882,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=12.20" }, @@ -1829,6 +1895,7 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -1841,6 +1908,7 @@ "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", "dev": true, + "license": "MIT", "dependencies": { "indent-string": "^5.0.0", "strip-indent": "^4.0.0" @@ -1856,13 +1924,15 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/remove-array-items/-/remove-array-items-1.1.1.tgz", "integrity": "sha512-MXW/jtHyl5F1PZI7NbpS8SOtympdLuF20aoWJT5lELR1p/HJDd5nqW8Eu9uLh/hCRY3FgvrIT5AwDCgBODklcA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1872,6 +1942,7 @@ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, + "license": "MIT", "dependencies": { "resolve-from": "^5.0.0" }, @@ -1884,6 +1955,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1906,13 +1978,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -1925,6 +1999,7 @@ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } @@ -1935,6 +2010,7 @@ "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", "deprecated": "16.1.1", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^1.8.1", "@sinonjs/fake-timers": "^6.0.1", @@ -1953,6 +2029,7 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -1962,6 +2039,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -1974,6 +2052,7 @@ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -1983,29 +2062,33 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true + "dev": true, + "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, + "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-license-ids": { - "version": "3.0.18", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", - "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", - "dev": true + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "dev": true, + "license": "CC0-1.0" }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -2020,6 +2103,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -2032,6 +2116,7 @@ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", "dev": true, + "license": "MIT", "dependencies": { "min-indent": "^1.0.1" }, @@ -2047,6 +2132,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -2059,6 +2145,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -2074,6 +2161,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -2086,6 +2174,7 @@ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz", "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -2098,6 +2187,7 @@ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -2107,6 +2197,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=14.16" }, @@ -2115,16 +2206,18 @@ } }, "node_modules/undici-types": { - "version": "6.18.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.18.2.tgz", - "integrity": "sha512-5ruQbENj95yDYJNS3TvcaxPMshV7aizdv/hWYjGIKoANWKjhWNBsr2YEuYZKodQulB1b8l7ILOuDQep3afowQQ==", - "dev": true + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, + "license": "Apache-2.0", "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -2134,13 +2227,15 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -2157,13 +2252,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/ws": { "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.3.0" }, @@ -2185,6 +2282,7 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } @@ -2193,13 +2291,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -2218,6 +2318,7 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } @@ -2227,6 +2328,7 @@ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, + "license": "MIT", "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -2242,6 +2344,7 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2254,6 +2357,7 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2266,6 +2370,7 @@ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2275,6 +2380,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, diff --git a/src/preload/package.json b/src/preload/package.json index d1e76ae..9b40370 100644 --- a/src/preload/package.json +++ b/src/preload/package.json @@ -1,7 +1,7 @@ { "name": "htmx-ext-preload", "main": "preload.js", - "version": "2.0.1", + "version": "2.1.0", "scripts": { "lint": "eslint test/ext test", "lint-fix": "eslint test/ext test --fix", @@ -19,6 +19,6 @@ "mocha": "10.1.0", "mocha-chrome": "https://github.com/Telroshan/mocha-chrome", "sinon": "^9.2.4", - "htmx.org": "^2.0.2" + "htmx.org": "^2.0.3" } } diff --git a/src/preload/preload.js b/src/preload/preload.js index 5f6e1c0..3bb56a1 100644 --- a/src/preload/preload.js +++ b/src/preload/preload.js @@ -1,141 +1,388 @@ -// This adds the "preload" extension to htmx. By default, this will -// preload the targets of any tags with `href` or `hx-get` attributes -// if they also have a `preload` attribute as well. See documentation -// for more details -htmx.defineExtension('preload', { - - onEvent: function(name, event) { - // Only take actions on "htmx:afterProcessNode" - if (name !== 'htmx:afterProcessNode') { - return - } +(function() { + /** + * This adds the "preload" extension to htmx. The extension will + * preload the targets of elements with "preload" attribute if: + * - they also have `href`, `hx-get` or `data-hx-get` attributes + * - they are radio buttons, checkboxes, select elements and submit + * buttons of forms with `method="get"` or `hx-get` attributes + * The extension relies on browser cache and for it to work + * server response must include `Cache-Control` header + * e.g. `Cache-Control: private, max-age=60`. + * For more details @see https://htmx.org/extensions/preload/ + */ - // SOME HELPER FUNCTIONS WE'LL NEED ALONG THE WAY + htmx.defineExtension('preload', { + onEvent: function(name, event) { + // Process preload attributes on `htmx:afterProcessNode` + if (name === 'htmx:afterProcessNode') { + // Initialize all nodes with `preload` attribute + const parent = event.target || event.detail.elt; + const preloadNodes = [ + ...parent.hasAttribute("preload") ? [parent] : [], + ...parent.querySelectorAll("[preload]")] + preloadNodes.forEach(function(node) { + // Initialize the node with the `preload` attribute + init(node) - // attr gets the closest non-empty value from the attribute. - var attr = function(node, property) { - if (node == undefined) { return undefined } - return node.getAttribute(property) || node.getAttribute('data-' + property) || attr(node.parentElement, property) - } + // Initialize all child elements which has + // `href`, `hx-get` or `data-hx-get` attributes + node.querySelectorAll('[href],[hx-get],[data-hx-get]').forEach(init) + }) + return + } - // load handles the actual HTTP fetch, and uses htmx.ajax in cases where we're - // preloading an htmx resource (this sends the same HTTP headers as a regular htmx request) - var load = function(node) { - // Called after a successful AJAX request, to mark the - // content as loaded (and prevent additional AJAX calls.) - var done = function(html) { - if (!node.preloadAlways) { - node.preloadState = 'DONE' + // Intercept HTMX preload requests on `htmx:beforeRequest` and + // send them as XHR requests instead to avoid side-effects, + // such as showing loading indicators while preloading data. + if (name === 'htmx:beforeRequest') { + const requestHeaders = event.detail.requestConfig.headers + if (!("HX-Preloaded" in requestHeaders + && requestHeaders["HX-Preloaded"] === "true")) { + return } - if (attr(node, 'preload-images') == 'true') { - document.createElement('div').innerHTML = html // create and populate a node to load linked resources, too. + event.preventDefault() + // Reuse XHR created by HTMX with replaced callbacks + const xhr = event.detail.xhr + xhr.onload = function() { + processResponse(event.detail.elt, xhr.responseText) } + xhr.onerror = null + xhr.onabort = null + xhr.ontimeout = null + xhr.send() } + } + }) - return function() { - // If this value has already been loaded, then do not try again. - if (node.preloadState !== 'READY') { - return - } + /** + * Initialize `node`, set up event handlers based on own or inherited + * `preload` attributes and set `node.preloadState` to `READY`. + * + * `node.preloadState` can have these values: + * - `READY` - event handlers have been set up and node is ready to preload + * - `TIMEOUT` - a triggering event has been fired, but `node` is not + * yet being loaded because some time need to pass first e.g. user + * has to keep hovering over an element for 100ms for preload to start + * - `LOADING` means that `node` is in the process of being preloaded + * - `DONE` means that the preloading process is complete and `node` + * doesn't need a repeated preload (indicated by preload="always") + * @param {Node} node + */ + function init(node) { + // Guarantee that each node is initialized only once + if (node.preloadState !== undefined) { + return + } - // Special handling for HX-GET - use built-in htmx.ajax function - // so that headers match other htmx requests, then set - // node.preloadState = TRUE so that requests are not duplicated - // in the future - var hxGet = node.getAttribute('hx-get') || node.getAttribute('data-hx-get') - if (hxGet) { - htmx.ajax('GET', hxGet, { - source: node, - handler: function(elt, info) { - done(info.xhr.responseText) - } - }) - return - } + if (!isValidNodeForPreloading(node)) { + return + } - // Otherwise, perform a standard xhr request, then set - // node.preloadState = TRUE so that requests are not duplicated - // in the future. - if (node.getAttribute('href')) { - var r = new XMLHttpRequest() - r.open('GET', node.getAttribute('href')) - r.onload = function() { done(r.responseText) } - r.send() - } + // Initialize form element preloading + if (node instanceof HTMLFormElement) { + const form = node + // Only initialize forms with `method="get"` or `hx-get` attributes + if (!((form.hasAttribute('method') && form.method === 'get') + || form.hasAttribute('hx-get') || form.hasAttribute('hx-data-get'))) { + return + } + for (let i = 0; i < form.elements.length; i++) { + const element = form.elements.item(i); + init(element); + element.labels.forEach(init); } + return + } + + // Process node configuration from preload attribute + let preloadAttr = getClosestAttribute(node, 'preload'); + node.preloadAlways = preloadAttr && preloadAttr.includes('always'); + if (node.preloadAlways) { + preloadAttr = preloadAttr.replace('always', '').trim(); + } + let triggerEventName = preloadAttr || 'mousedown'; + + // Set up event handlers listening for triggering events + const needsTimeout = triggerEventName === 'mouseover' + node.addEventListener(triggerEventName, getEventHandler(node, needsTimeout)) + + // Add `touchstart` listener for touchscreen support + // if `mousedown` or `mouseover` is used + if (triggerEventName === 'mousedown' || triggerEventName === 'mouseover') { + node.addEventListener('touchstart', getEventHandler(node)) + } + + // If `mouseover` is used, set up `mouseout` listener, + // which will abort preloading if user moves mouse outside + // the element in less than 100ms after hovering over it + if (triggerEventName === 'mouseover') { + node.addEventListener('mouseout', function(evt) { + if ((evt.target === node) && (node.preloadState === 'TIMEOUT')) { + node.preloadState = 'READY' + } + }) } - // This function processes a specific node and sets up event handlers. - // We'll search for nodes and use it below. - var init = function(node) { - // If this node DOES NOT include a "GET" transaction, then there's nothing to do here. - if (node.getAttribute('href') + node.getAttribute('hx-get') + node.getAttribute('data-hx-get') == '') { + // Mark the node as ready to be preloaded + node.preloadState = 'READY' + + // This event can be used to load content immediately + htmx.trigger(node, 'preload:init') + } + + /** + * Return event handler which can be called by event listener to start + * the preloading process of `node` with or without a timeout + * @param {Node} node + * @param {boolean=} needsTimeout + * @returns {function(): void} + */ + function getEventHandler(node, needsTimeout = false) { + return function() { + // Do not preload uninitialized nodes, nodes which are in process + // of being preloaded or have been preloaded and don't need repeat + if (node.preloadState !== 'READY') { return } - // Guarantee that we only initialize each node once. - if (node.preloadState !== undefined) { + if (needsTimeout) { + node.preloadState = 'TIMEOUT' + const timeoutMs = 100 + window.setTimeout(function() { + if (node.preloadState === 'TIMEOUT') { + node.preloadState = 'READY' + load(node) + } + }, timeoutMs) return } - // Get event name from config. - var on = attr(node, 'preload') || 'mousedown' - const always = on.indexOf('always') !== -1 - if (always) { - on = on.replace('always', '').trim() + load(node) + } + } + + /** + * Preload the target of node, which can be: + * - hx-get or data-hx-get attribute + * - href or form action attribute + * @param {Node} node + */ + function load(node) { + // Do not preload uninitialized nodes, nodes which are in process + // of being preloaded or have been preloaded and don't need repeat + if (node.preloadState !== 'READY') { + return + } + node.preloadState = 'LOADING' + + // Load nodes with `hx-get` or `data-hx-get` attribute + // Forms don't reach this because only their elements are initialized + const hxGet = node.getAttribute('hx-get') || node.getAttribute('data-hx-get') + if (hxGet) { + sendHxGetRequest(hxGet, node); + return + } + + // Load nodes with `href` attribute + const hxBoost = getClosestAttribute(node, "hx-boost") === "true" + if (node.hasAttribute('href')) { + const url = node.getAttribute('href'); + if (hxBoost) { + sendHxGetRequest(url, node); + } else { + sendXmlGetRequest(url, node); } + return + } - // FALL THROUGH to here means we need to add an EventListener + // Load form elements + if (isPreloadableFormElement(node)) { + const url = node.form.getAttribute('action') + || node.form.getAttribute('hx-get') + || node.form.getAttribute('data-hx-get'); + const formData = htmx.values(node.form); + const isStandardForm = !(node.form.getAttribute('hx-get') + || node.form.getAttribute('data-hx-get') + || hxBoost); + const sendGetRequest = isStandardForm ? sendXmlGetRequest : sendHxGetRequest - // Apply the listener to the node - node.addEventListener(on, function(evt) { - if (node.preloadState === 'PAUSE') { // Only add one event listener - node.preloadState = 'READY' // Required for the `load` function to trigger + // submit button + if (node.type === 'submit') { + sendGetRequest(url, node.form, formData) + return + } + + // select + const inputName = node.name || node.control.name; + if (node.tagName === 'SELECT') { + Array.from(node.options).forEach(option => { + if (option.selected) return; + formData.set(inputName, option.value); + const formDataOrdered = forceFormDataInOrder(node.form, formData); + sendGetRequest(url, node.form, formDataOrdered) + }); + return + } - // Special handling for "mouseover" events. Wait 100ms before triggering load. - if (on === 'mouseover') { - window.setTimeout(load(node), 100) - } else { - load(node)() // all other events trigger immediately. - } + // radio and checkbox + const inputType = node.getAttribute("type") || node.control.getAttribute("type"); + const nodeValue = node.value || node.control?.value; + if (inputType === 'radio') { + formData.set(inputName, nodeValue); + } else if (inputType === 'checkbox'){ + const inputValues = formData.getAll(inputName); + if (inputValues.includes(nodeValue)) { + formData[inputName] = inputValues.filter(value => value !== nodeValue); + } else { + formData.append(inputName, nodeValue); } - }) + } + const formDataOrdered = forceFormDataInOrder(node.form, formData); + sendGetRequest(url, node.form, formDataOrdered) + return + } + } - // Special handling for certain built-in event handlers - switch (on) { - case 'mouseover': - // Mirror `touchstart` events (fires immediately) - node.addEventListener('touchstart', load(node)) - - // WHhen the mouse leaves, immediately disable the preload - node.addEventListener('mouseout', function(evt) { - if ((evt.target === node) && (node.preloadState === 'READY')) { - node.preloadState = 'PAUSE' - } - }) - break - - case 'mousedown': - // Mirror `touchstart` events (fires immediately) - node.addEventListener('touchstart', load(node)) - break + /** + * Force formData values to be in the order of form elements. + * This is useful to apply after alternating formData values + * and before passing them to a HTTP request because cache is + * sensitive to GET parameter order e.g., cached `/link?a=1&b=2` + * will not be used for `/link?b=2&a=1`. + * @param {HTMLFormElement} form + * @param {FormData} formData + * @returns {FormData} + */ + function forceFormDataInOrder(form, formData) { + const formElements = form.elements; + const orderedFormData = new FormData(); + for(let i = 0; i < formElements.length; i++) { + const element = formElements.item(i); + if (formData.has(element.name) && element.tagName === 'SELECT') { + orderedFormData.append( + element.name, formData.get(element.name)); + continue; } + if (formData.has(element.name) && formData.getAll(element.name) + .includes(element.value)) { + orderedFormData.append(element.name, element.value); + } + } + return orderedFormData; + } + + /** + * Send GET request with `hx-request` headers as if `sourceNode` + * target was loaded. Send alternated values if `formData` is set. + * + * Note that this request is intercepted and sent as XMLHttpRequest. + * It is necessary to use `htmx.ajax` to acquire correct headers which + * HTMX and extensions add based on `sourceNode`. But it cannot be used + * to perform the request due to side-effects e.g. loading indicators. + * @param {string} url + * @param {Node} sourceNode + * @param {FormData=} formData + */ + function sendHxGetRequest(url, sourceNode, formData = undefined) { + htmx.ajax('GET', url, { + source: sourceNode, + values: formData, + headers: {"HX-Preloaded": "true"} + }); + } - // Mark the node as ready to run. - node.preloadState = 'PAUSE' - node.preloadAlways = always - htmx.trigger(node, 'preload:init') // This event can be used to load content immediately. + /** + * Send XML GET request to `url`. Send `formData` as URL params if set. + * @param {string} url + * @param {Node} sourceNode + * @param {FormData=} formData + */ + function sendXmlGetRequest(url, sourceNode, formData = undefined) { + const xhr = new XMLHttpRequest() + if (formData) { + url += '?' + new URLSearchParams(formData.entries()).toString() } + xhr.open('GET', url); + xhr.setRequestHeader("HX-Preloaded", "true") + xhr.onload = function() { processResponse(sourceNode, xhr.responseText) } + xhr.send() + } + + /** + * Process request response by marking node `DONE` to prevent repeated + * requests, except if preload attribute contains `always`, + * and load linked resources (e.g. images) returned in the response + * if `preload-images` attribute is `true` + * @param {Node} node + * @param {string} responseText + */ + function processResponse(node, responseText) { + node.preloadState = node.preloadAlways ? 'READY' : 'DONE' - // Search for all child nodes that have a "preload" attribute - const parent = event.target || event.detail.elt; - parent.querySelectorAll("[preload]").forEach(function(node) { - // Initialize the node with the "preload" attribute - init(node) + if (getClosestAttribute(node, 'preload-images') === 'true') { + // Load linked resources + document.createElement('div').innerHTML = responseText + } + } + + /** + * Gets attribute value from node or one of its parents + * @param {Node} node + * @param {string} attribute + * @returns { string | undefined } + */ + function getClosestAttribute(node, attribute) { + if (node == undefined) { return undefined } + return node.getAttribute(attribute) + || node.getAttribute('data-' + attribute) + || getClosestAttribute(node.parentElement, attribute) + } - // Initialize all child elements that are anchors or have `hx-get` (use with care) - node.querySelectorAll('a,[hx-get],[data-hx-get]').forEach(init) - }) + /** + * Determines if node is valid for preloading and should be + * initialized by setting up event listeners and handlers + * @param {Node} node + * @returns {boolean} + */ + function isValidNodeForPreloading(node) { + // Add listeners only to nodes which include "GET" transactions + // or preloadable "GET" form elements + const getReqAttrs = ['href', 'hx-get', 'data-hx-get']; + const includesGetRequest = node => getReqAttrs.some(a => node.hasAttribute(a)) + || node.method === 'get'; + const isPreloadableGetFormElement = node.form instanceof HTMLFormElement + && includesGetRequest(node.form) + && isPreloadableFormElement(node) + if (!includesGetRequest(node) && !isPreloadableGetFormElement) { + return false + } + + // Don't preload elements contained in + // to prevent sending two requests. Interaction on in a + // situation activates too. + if (node instanceof HTMLInputElement && node.closest('label')) { + return false + } + + return true + } + + /** + * Determine if node is a form element which can be preloaded, + * i.e., `radio`, `checkbox`, `select` or `submit` button + * or a `label` of a form element which can be preloaded. + * @param {Node} node + * @returns {boolean} + */ + function isPreloadableFormElement(node) { + if (node instanceof HTMLInputElement || node instanceof HTMLButtonElement) { + const type = node.getAttribute('type'); + return ['checkbox', 'radio', 'submit'].includes(type); + } + if (node instanceof HTMLLabelElement) { + return node.control && isPreloadableFormElement(node.control); + } + return node instanceof HTMLSelectElement; } -}) +})() \ No newline at end of file diff --git a/src/preload/test/ext/elements.js b/src/preload/test/ext/elements.js new file mode 100644 index 0000000..2fe7aa9 --- /dev/null +++ b/src/preload/test/ext/elements.js @@ -0,0 +1,73 @@ +describe('preload extension preloads hyperlinks and hx-get elements', function() { + let requests = []; + + beforeEach(function() { + this.server = makeServer() + const defaultOnCreateFunction = this.server.xhr.onCreate + this.server.xhr.onCreate = function(xhr) { + defaultOnCreateFunction(xhr) + requests.push(xhr) + } + clearWorkArea() + getWorkArea().setAttribute('hx-ext', 'preload') + }) + + afterEach(function() { + this.server.restore() + requests = [] + getWorkArea().removeAttribute('hx-ext') + clearWorkArea() + }) + + it('preloads hyperlink with preload attribute', function() { + const hyperlink = make('Link') + + htmx.trigger(hyperlink, 'mousedown') + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test') + }) + + it('preloads hyperlink which inherits preload attribute form parent div', function() { + make('Link') + const hyperlink = byId("link") + + htmx.trigger(hyperlink, 'mousedown') + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test') + }) + + it('does not preload hyperlink without preload attribute', function() { + const hyperlink = make('Link') + + htmx.trigger(hyperlink, 'mousedown') + + should.equal(requests.length, 0) + }) + + it('preloads button with hx-get and preload attributes', function() { + const button = make('Button') + + htmx.trigger(button, 'mousedown') + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test') + }) + + it('does not preload button with hx-get and without preload attribute', function() { + const button = make('Button') + + htmx.trigger(button, 'mousedown') + + should.equal(requests.length, 0) + }) + + it('does not preload button with hx-post and preload attributes', function() { + const button = make('Button') + + htmx.trigger(button, 'mousedown') + + should.equal(requests.length, 0) + }) +}) diff --git a/src/preload/test/ext/events.js b/src/preload/test/ext/events.js new file mode 100644 index 0000000..9dcca57 --- /dev/null +++ b/src/preload/test/ext/events.js @@ -0,0 +1,72 @@ +describe('preload extension handles different trigger events', function() { + let requests = []; + + beforeEach(function() { + this.server = makeServer() + const defaultOnCreateFunction = this.server.xhr.onCreate + this.server.xhr.onCreate = function(xhr) { + defaultOnCreateFunction(xhr) + requests.push(xhr) + } + this.clock = sinon.useFakeTimers() + clearWorkArea() + getWorkArea().setAttribute('hx-ext', 'preload') + }) + + afterEach(function() { + this.server.restore() + requests = [] + this.clock.restore() + getWorkArea().removeAttribute('hx-ext') + clearWorkArea() + }) + + it('preloads element with preload attribute on touchstart', function() { + const hyperlink = make('Link') + + htmx.trigger(hyperlink, 'touchstart') + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test') + }) + + it('preloads element with preload="mouseover" attribute 100ms after mouseover', function() { + const hyperlink = make('Link') + + htmx.trigger(hyperlink, 'mouseover') + this.clock.tick(100) + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test') + }) + + it('preloads element with preload="mouseover" attribute on touchstart', function() { + const hyperlink = make('Link') + + htmx.trigger(hyperlink, 'touchstart') + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test') + }) + + it('does not preload element with preload="mouseover" attribute if mouseout fires 99ms after mouseover', function() { + const hyperlink = make('Link') + + htmx.trigger(hyperlink, 'mouseover') + setTimeout(() => { + htmx.trigger(hyperlink, 'mouseout') + }, 99) + this.clock.tick(99) + + should.equal(requests.length, 0) + }) + + it('does not preload element with preload attribute 100ms after mouseover', function() { + const hyperlink = make('Link') + + htmx.trigger(hyperlink, 'mouseover') + this.clock.tick(100) + + should.equal(requests.length, 0) + }) +}) diff --git a/src/preload/test/ext/forms.js b/src/preload/test/ext/forms.js new file mode 100644 index 0000000..ef685d3 --- /dev/null +++ b/src/preload/test/ext/forms.js @@ -0,0 +1,248 @@ +describe('preload extension preloads forms', function() { + let requests = []; + + beforeEach(function() { + this.server = makeServer() + const defaultOnCreateFunction = this.server.xhr.onCreate + this.server.xhr.onCreate = function(xhr) { + defaultOnCreateFunction(xhr) + requests.push(xhr) + } + this.clock = sinon.useFakeTimers() + clearWorkArea() + getWorkArea().setAttribute('hx-ext', 'preload') + }) + + afterEach(function() { + this.server.restore() + requests = [] + this.clock.restore() + getWorkArea().removeAttribute('hx-ext') + clearWorkArea() + }) + + it('preloads form with method="get" and preload attribute', function() { + const form = make(` + + + + + `) + const submitButton = form.querySelector("input[type='submit']") + + htmx.trigger(submitButton, 'mousedown') + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test?name=John') + }) + + it('preloads form with hx-get and preload attribute', function() { + const form = make(` + + + + + `) + const submitButton = form.querySelector("input[type='submit']") + + htmx.trigger(submitButton, 'mousedown') + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test?name=John') + }) + + it('does not preload form with method="post" and preload attribute', function() { + const form = make(` + + + + + `) + const submitButton = form.querySelector("input[type='submit']") + + htmx.trigger(submitButton, 'mousedown') + + should.equal(requests.length, 0) + }) + + it('does not preload form with hx-post and preload attribute', function() { + const form = make(` + + + + + `) + const submitButton = form.querySelector("input[type='submit']") + + htmx.trigger(submitButton, 'mousedown') + + should.equal(requests.length, 0) + }) + + it('preloads ', function() { + const form = make(` + + + Submit + + `) + const submitButton = form.querySelector("button[type='submit']") + + htmx.trigger(submitButton, 'mousedown') + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test?name=John') + }) + + it('preloads radio button inheriting preload from parent form', function() { + const form = make(` + + Visa + Mastercard + + `) + const visaRadioButton = form.querySelector("input[value='Visa']") + + htmx.trigger(visaRadioButton, 'mouseover') + this.clock.tick(100) + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test?card_type=Visa') + }) + + it('preloads radio button with preload tag', function() { + const form = make(` + + Visa + Mastercard + + `) + const visaRadioButton = form.querySelector("input[value='Visa']") + + htmx.trigger(visaRadioButton, 'mouseover') + this.clock.tick(100) + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test?card_type=Visa') + }) + + it('does not preload radio button without preload tag', function() { + const form = make(` + + Visa + Mastercard + + `) + const mastercardRadioButton = form.querySelector("input[value='Mastercard']") + + htmx.trigger(mastercardRadioButton, 'mouseover') + this.clock.tick(100) + + should.equal(requests.length, 0) + }) + + it('preloads label containing radio button', function() { + const form = make(` + + Visa + Mastercard + + `) + const visaRadioLabel = form.querySelector("label:has(input[value='Visa'])") + + htmx.trigger(visaRadioLabel, 'mouseover') + this.clock.tick(100) + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test?card_type=Visa') + }) + + it('preloads unchecked checkbox', function() { + const form = make(` + + Coding + Music + Sports + + `) + const musicCheckbox = form.querySelector("input[value='Music']") + + htmx.trigger(musicCheckbox, 'mouseover') + this.clock.tick(100) + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test?interests=Coding&interests=Music&interests=Sports') + }) + + it('preloads checked checkbox', function() { + const form = make(` + + Coding + Music + Sports + + `) + const sportsCheckbox = form.querySelector("input[value='Sports']") + + htmx.trigger(sportsCheckbox, 'mouseover') + this.clock.tick(100) + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test?interests=Coding') + }) + + it('preloads label bound to checked checkbox', function() { + const form = make(` + + + Coding + + Music + + Sports + + `) + const sportsCheckboxLabel = form.querySelector("label[for='sports_checkbox']") + + htmx.trigger(sportsCheckboxLabel, 'mouseover') + this.clock.tick(100) + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test?interests=Coding') + }) + + it('preloads unselected select options', function() { + const form = make(` + + + Dog + Cat + Dinosaur + + + `) + const select = form.querySelector("select") + + htmx.trigger(select, 'mousedown') + this.server.respond() + + should.equal(requests.length, 2) + should.equal(requests[0].url, '/test?pet=cat') + should.equal(requests[1].url, '/test?pet=dinosaur') + }) + + it('sends only one preload request when activating input contained in a label', function() { + const form = make(` + + Visa + + `) + const visaRadio = form.querySelector("input[value='Visa']") + + htmx.trigger(visaRadio, 'mouseover') + this.clock.tick(100) + + should.equal(requests.length, 1) + }) + }) + \ No newline at end of file diff --git a/src/preload/test/ext/linked-images.js b/src/preload/test/ext/linked-images.js new file mode 100644 index 0000000..638bbd8 --- /dev/null +++ b/src/preload/test/ext/linked-images.js @@ -0,0 +1,80 @@ +describe('preload extension preloads linked images', function() { + beforeEach(function() { + this.server = makeServer() + clearWorkArea() + getWorkArea().setAttribute('hx-ext', 'preload') + }) + + afterEach(function() { + this.server.restore() + getWorkArea().removeAttribute('hx-ext') + clearWorkArea() + }) + + it('preloads linked image if button has preload-images="true" attribute', function(done) { + let imageLoaded = false + const button = make('Button') + this.server.respondWith('GET', '/test', ``) + const handler = htmx.on('imageLoaded', function() { + htmx.off('imageLoaded', handler) + imageLoaded = true + done() + }) + try { + htmx.trigger(button, 'mousedown') + this.server.respond() + } finally { + setTimeout(function() { + htmx.off('imageLoaded', handler) + if (!imageLoaded) { + done(new Error("Image was not preloaded")) + } + }, 100) + } + }) + + it('preloads linked image if button inherits preload-images="true" attribute from parent div', function(done) { + let imageLoaded = false + make('Button') + const button = byId("button") + this.server.respondWith('GET', '/test', ``) + const handler = htmx.on('imageLoaded', function() { + htmx.off('imageLoaded', handler) + imageLoaded = true + done() + }) + try { + htmx.trigger(button, 'mousedown') + this.server.respond() + } finally { + setTimeout(function() { + htmx.off('imageLoaded', handler) + if (!imageLoaded) { + done(new Error("Image was not preloaded")) + } + }, 100) + } + }) + + it('does not preload linked image if button does not have preload-images attribute', function(done) { + let imageLoaded = false + const button = make('Button') + this.server.respondWith('GET', '/test', ``) + const handler = htmx.on('imageLoaded', function() { + htmx.off('imageLoaded', handler) + imageLoaded = true + done(new Error("Image was preloaded")) + }) + try { + htmx.trigger(button, 'mousedown') + this.server.respond() + } finally { + setTimeout(function() { + htmx.off('imageLoaded', handler) + if (!imageLoaded) { + done() + } + }, 100) + } + }) +}) \ No newline at end of file diff --git a/src/preload/test/ext/repeated-interaction.js b/src/preload/test/ext/repeated-interaction.js new file mode 100644 index 0000000..e41c24e --- /dev/null +++ b/src/preload/test/ext/repeated-interaction.js @@ -0,0 +1,85 @@ +describe('preload extension handles repeated interaction', function() { + let requests = []; + + beforeEach(function() { + this.server = makeServer() + const defaultOnCreateFunction = this.server.xhr.onCreate + this.server.xhr.onCreate = function(xhr) { + defaultOnCreateFunction(xhr) + requests.push(xhr) + } + this.clock = sinon.useFakeTimers() + clearWorkArea() + getWorkArea().setAttribute('hx-ext', 'preload') + }) + + afterEach(function() { + this.server.restore() + requests = [] + this.clock.restore() + getWorkArea().removeAttribute('hx-ext') + clearWorkArea() + }) + + it('preloads hyperlink with preload attribute once despite two mousedowns', function() { + const hyperlink = make('Link') + + htmx.trigger(hyperlink, 'mousedown') + this.server.respond() + htmx.trigger(hyperlink, 'mousedown') + + should.equal(requests.length, 1) + should.equal(requests[0].url, '/test') + }) + + it('preloads hyperlink with preload="always" attribute three times', function() { + const hyperlink = make('Link') + + htmx.trigger(hyperlink, 'mousedown') + this.server.respond() + htmx.trigger(hyperlink, 'mousedown') + this.server.respond() + htmx.trigger(hyperlink, 'mousedown') + + should.equal(requests.length, 3) + }) + + it('preloads hyperlink with preload="mousedown always" attribute three times', function() { + const hyperlink = make('Link') + + htmx.trigger(hyperlink, 'mousedown') + this.server.respond() + htmx.trigger(hyperlink, 'mousedown') + this.server.respond() + htmx.trigger(hyperlink, 'mousedown') + + should.equal(requests.length, 3) + }) + + it('preloads hyperlink with preload="always mousedown" attribute three times', function() { + const hyperlink = make('Link') + + htmx.trigger(hyperlink, 'mousedown') + this.server.respond() + htmx.trigger(hyperlink, 'mousedown') + this.server.respond() + htmx.trigger(hyperlink, 'mousedown') + + should.equal(requests.length, 3) + }) + + it('preloads hyperlink with preload="mouseover always" attribute three times', function() { + const hyperlink = make('Link') + + htmx.trigger(hyperlink, 'mouseover') + this.clock.tick(100) + this.server.respond() + htmx.trigger(hyperlink, 'mouseover') + this.clock.tick(100) + this.server.respond() + htmx.trigger(hyperlink, 'mouseover') + this.clock.tick(100) + + should.equal(requests.length, 3) + }) +}) diff --git a/src/preload/test/ext/requests.js b/src/preload/test/ext/requests.js new file mode 100644 index 0000000..427d1f9 --- /dev/null +++ b/src/preload/test/ext/requests.js @@ -0,0 +1,157 @@ +describe('preload extension sends requests which match element requests', function() { + let requests = []; + + beforeEach(function() { + this.server = makeServer() + const defaultOnCreateFunction = this.server.xhr.onCreate + this.server.xhr.onCreate = function(xhr) { + defaultOnCreateFunction(xhr) + requests.push(xhr) + } + this.clock = sinon.useFakeTimers() + clearWorkArea() + getWorkArea().setAttribute('hx-ext', 'preload') + }) + + afterEach(function() { + this.server.restore() + requests = [] + this.clock.restore() + getWorkArea().removeAttribute('hx-ext') + clearWorkArea() + }) + + it('includes HX-Preloaded header when preloading hyperlink', function() { + const hyperlink = make('Link') + + htmx.trigger(hyperlink, 'mousedown') + + should.equal(requests.length, 1) + requests[0].requestHeaders.should.deep.contain({"HX-Preloaded": "true"}) + }) + + it('includes HX-Preloaded header when preloading xh-boosted hyperlink', function() { + const hyperlink = make('Link') + + htmx.trigger(hyperlink, 'mousedown') + + should.equal(requests.length, 1) + requests[0].requestHeaders.should.deep.contain({"HX-Preloaded": "true"}) + }) + + it('includes HX-Preloaded header when preloading button with hx-get attribute', function() { + const button = make('Button') + + htmx.trigger(button, 'mousedown') + + should.equal(requests.length, 1) + requests[0].requestHeaders.should.deep.contain({"HX-Preloaded": "true"}) + }) + + it('matches url and includes headers for hx-boosted hyperlink', function() { + const hyperlink = make('Link') + + htmx.trigger(hyperlink, 'mousedown') + this.server.respond() + hyperlink.click() + + should.equal(requests.length, 2) + should.equal(requests[0].url, requests[1].url) + should.equal(requests[0].method, requests[1].method) + requests[0].requestHeaders.should.deep.contain(requests[1].requestHeaders) + }) + + it('matches url and includes headers for hx-boosted form', function(){ + const form = make(` + + + + + `) + const submitButton = form.querySelector("input[type='submit']") + + htmx.trigger(submitButton, 'mousedown') + this.server.respond() + submitButton.click() + + should.equal(requests.length, 2) + should.equal(requests[0].url, requests[1].url) + should.equal(requests[0].method, requests[1].method) + requests[0].requestHeaders.should.deep.contain(requests[1].requestHeaders) + }) + + it('matches url and includes headers for hx-get button', function() { + const button = make('Button') + + htmx.trigger(button, 'mousedown') + this.server.respond() + button.click() + + should.equal(requests.length, 2) + should.equal(requests[0].url, requests[1].url) + should.equal(requests[0].method, requests[1].method) + requests[0].requestHeaders.should.deep.contain(requests[1].requestHeaders) + }) + + it('matches url and includes headers for hx-get form', function(){ + const form = make(` + + + + + `) + const submitButton = form.querySelector("input[type='submit']") + + htmx.trigger(submitButton, 'mousedown') + this.server.respond() + submitButton.click() + + should.equal(requests.length, 2) + should.equal(requests[0].url, requests[1].url) + should.equal(requests[0].method, requests[1].method) + requests[0].requestHeaders.should.deep.contain(requests[1].requestHeaders) + }) + + it('matches url and includes headers for checkbox label in a form with multiple fields', function(){ + const form = make(` + + + + + + + Coding + + Music + + Sports + + + Visa + Mastercard + + + `) + const sportsCheckboxLabel = form.querySelector("label[for='sports_checkbox']") + + htmx.trigger(sportsCheckboxLabel, "mouseover") + this.clock.tick(100) + this.server.respond() + sportsCheckboxLabel.click() + + should.equal(requests.length, 2) + should.equal(requests[0].url, requests[1].url) + should.equal(requests[0].method, requests[1].method) + requests[0].requestHeaders.should.deep.contain(requests[1].requestHeaders) + }) + + it('does not include HX-Preloaded header when clicking hx-boosted and preloaded hyperlink', function() { + const hyperlink = make('Link') + + hyperlink.click() + + should.equal(requests.length, 1) + requests[0].requestHeaders.should.not.deep.contain({"HX-Preloaded": "true"}) + }) + }) + \ No newline at end of file diff --git a/src/preload/test/ext/side-effects.js b/src/preload/test/ext/side-effects.js new file mode 100644 index 0000000..1fdd6ec --- /dev/null +++ b/src/preload/test/ext/side-effects.js @@ -0,0 +1,30 @@ +describe('preload extension does not cause the side-effects of HTMX requests', function() { + beforeEach(function() { + this.server = makeServer() + clearWorkArea() + getWorkArea().setAttribute('hx-ext', 'preload') + }) + + afterEach(function() { + this.server.restore() + getWorkArea().removeAttribute('hx-ext') + clearWorkArea() + }) + + it('does not add .htmx-request class to source node', function() { + const button = make('Button') + + htmx.trigger(button, 'mousedown') + + button.should.not.have.class("htmx-request") + }) + + it('does not add .htmx-request class to hx-indicator', function() { + const button = make('Button') + const indicator = make('Loading...') + + htmx.trigger(button, 'mousedown') + + indicator.should.not.have.class("htmx-request") + }) +}) \ No newline at end of file diff --git a/src/preload/test/image.jpeg b/src/preload/test/image.jpeg new file mode 100644 index 0000000..1cda9a5 Binary files /dev/null and b/src/preload/test/image.jpeg differ diff --git a/src/preload/test/index.html b/src/preload/test/index.html new file mode 100644 index 0000000..b494ff2 --- /dev/null +++ b/src/preload/test/index.html @@ -0,0 +1,77 @@ + + + + + Mocha Tests + + + + + + + + + + + +htmx.js test suite +Version: + +Scratch Page + + + Scratch Page + + + +Manual Tests +Here + +Mocha Test Suite +[ALL] + + + + + + + + + + + + + + + + + + + + + + + + +Work Area + + + + + diff --git a/src/preload/test/util.js b/src/preload/test/util.js new file mode 100644 index 0000000..77c0c28 --- /dev/null +++ b/src/preload/test/util.js @@ -0,0 +1,114 @@ +/* Test Utilities */ + +function byId(id) { + return document.getElementById(id) +} + +function make(htmlStr) { + htmlStr = htmlStr.trim() + var makeFn = function() { + var range = document.createRange() + var fragment = range.createContextualFragment(htmlStr) + var wa = getWorkArea() + var child = null + var children = fragment.children || fragment.childNodes // IE + var appendedChildren = [] + while (children.length > 0) { + child = children[0] + wa.appendChild(child) + appendedChildren.push(child) + } + for (var i = 0; i < appendedChildren.length; i++) { + htmx.process(appendedChildren[i]) + } + return child // return last added element + } + if (getWorkArea()) { + return makeFn() + } else { + ready(makeFn) + } +} + +function ready(fn) { + if (document.readyState !== 'loading') { + fn() + } else { + document.addEventListener('DOMContentLoaded', fn) + } +} + +function getWorkArea() { + return byId('work-area') +} + +function clearWorkArea() { + var workArea = getWorkArea() + if (workArea) workArea.innerHTML = '' +} + +function removeWhiteSpace(str) { + return str.replace(/\s/g, '') +} + +function getHTTPMethod(xhr) { + return xhr.requestHeaders['X-HTTP-Method-Override'] || xhr.method +} + +function makeServer() { + var server = sinon.fakeServer.create() + server.fakeHTTPMethods = true + server.getHTTPMethod = function(xhr) { + return getHTTPMethod(xhr) + } + return server +} + +function parseParams(str) { + var re = /([^&=]+)=?([^&]*)/g + var decode = function(str) { + return decodeURIComponent(str.replace(/\+/g, ' ')) + } + var params = {}; var e + if (str) { + if (str.substr(0, 1) == '?') { + str = str.substr(1) + } + while (e = re.exec(str)) { + var k = decode(e[1]) + var v = decode(e[2]) + if (params[k] !== undefined) { + if (!Array.isArray(params[k])) { + params[k] = [params[k]] + } + params[k].push(v) + } else { + params[k] = v + } + } + } + return params +} + +function getQuery(url) { + var question = url.indexOf('?') + var hash = url.indexOf('#') + if (hash == -1 && question == -1) return '' + if (hash == -1) hash = url.length + return question == -1 || hash == question + 1 + ? url.substring(hash) + : url.substring(question + 1, hash) +} + +function getParameters(xhr) { + if (getHTTPMethod(xhr) == 'GET') { + return parseParams(getQuery(xhr.url)) + } else { + return parseParams(xhr.requestBody) + } +} + +function log(val) { + console.log(val) + return val +}
Version: