From 7079233e15a6683363033bacc0f54b89a84d7c5d Mon Sep 17 00:00:00 2001 From: Ankit Verma Date: Sun, 27 Oct 2024 11:08:22 +0530 Subject: [PATCH 1/2] :hammer:[refractor][Connverted Vanilla.js app to be a PWA.] --- .../dwa-starter-vanillajs-vite/index.html | 8 +- javascript/dwa-starter-vanillajs-vite/main.js | 90 +- .../dwa-starter-vanillajs-vite/manifest.json | 25 + .../package-lock.json | 3623 +++++++++++++++++ .../dwa-starter-vanillajs-vite/package.json | 6 +- .../playwright.config.js | 42 +- .../public/apple-touch-icon-180x180.png | Bin 0 -> 2833 bytes .../public/favicon.ico | Bin 0 -> 1564 bytes .../public/favicon.svg | 130 + .../public/maskable-icon-512x512.png | Bin 0 -> 11375 bytes .../public/pwa-192x192.png | Bin 0 -> 4298 bytes .../public/pwa-512x512.png | Bin 0 -> 16976 bytes .../public/pwa-64x64.png | Bin 0 -> 1575 bytes javascript/dwa-starter-vanillajs-vite/sw.js | 53 + .../tests/addToHomeScreen.spec.js | 29 + .../tests/main.spec.js | 38 +- .../tests/offline.spec.js | 18 + .../tests/sw.spec.js | 22 + 18 files changed, 4025 insertions(+), 59 deletions(-) create mode 100644 javascript/dwa-starter-vanillajs-vite/manifest.json create mode 100644 javascript/dwa-starter-vanillajs-vite/package-lock.json create mode 100644 javascript/dwa-starter-vanillajs-vite/public/apple-touch-icon-180x180.png create mode 100644 javascript/dwa-starter-vanillajs-vite/public/favicon.ico create mode 100644 javascript/dwa-starter-vanillajs-vite/public/favicon.svg create mode 100644 javascript/dwa-starter-vanillajs-vite/public/maskable-icon-512x512.png create mode 100644 javascript/dwa-starter-vanillajs-vite/public/pwa-192x192.png create mode 100644 javascript/dwa-starter-vanillajs-vite/public/pwa-512x512.png create mode 100644 javascript/dwa-starter-vanillajs-vite/public/pwa-64x64.png create mode 100644 javascript/dwa-starter-vanillajs-vite/sw.js create mode 100644 javascript/dwa-starter-vanillajs-vite/tests/addToHomeScreen.spec.js create mode 100644 javascript/dwa-starter-vanillajs-vite/tests/offline.spec.js create mode 100644 javascript/dwa-starter-vanillajs-vite/tests/sw.spec.js diff --git a/javascript/dwa-starter-vanillajs-vite/index.html b/javascript/dwa-starter-vanillajs-vite/index.html index 3902b2d8..908528a7 100644 --- a/javascript/dwa-starter-vanillajs-vite/index.html +++ b/javascript/dwa-starter-vanillajs-vite/index.html @@ -1,6 +1,6 @@ - + @@ -11,7 +11,10 @@ name="description" content="A Decentralized Web Application template" /> - + + + + +
diff --git a/javascript/dwa-starter-vanillajs-vite/main.js b/javascript/dwa-starter-vanillajs-vite/main.js index acaf8102..5c6f4c7e 100644 --- a/javascript/dwa-starter-vanillajs-vite/main.js +++ b/javascript/dwa-starter-vanillajs-vite/main.js @@ -1,37 +1,95 @@ // main.js -import { Home, About, Settings, NotFound } from './components.js'; +import { Home, About, Settings, NotFound } from "./components.js"; // Define routes and their corresponding components const routes = { - '/': Home, - '/about': About, - '/settings': Settings, + "/": Home, + "/about": About, + "/settings": Settings, }; // Function to handle navigation function navigateTo(url) { - history.pushState(null, null, url); - router(); + history.pushState(null, null, url); + router(); } // Router function to render components based on the current URL function router() { - const path = window.location.pathname; - const route = routes[path] || NotFound; - route(); + const path = window.location.pathname; + const route = routes[path] || NotFound; + route(); } // Event delegation for link clicks -document.addEventListener('click', (e) => { - if (e.target.matches('[data-link]')) { - e.preventDefault(); - navigateTo(e.target.href); - } +document.addEventListener("click", (e) => { + if (e.target.matches("[data-link]")) { + e.preventDefault(); + navigateTo(e.target.href); + } }); // Listen to popstate event (back/forward navigation) -window.addEventListener('popstate', router); +window.addEventListener("popstate", router); // Initial call to router to render the correct component on page load -document.addEventListener('DOMContentLoaded', router); +document.addEventListener("DOMContentLoaded", router); + +if ("serviceWorker" in navigator) { + window.addEventListener("load", () => { + navigator.serviceWorker + .register("sw.js") + .then((reg) => { + console.log("Service Worker: Registered"); + + // Check if a new SW is waiting to activate + reg.onupdatefound = () => { + const newWorker = reg.installing; + newWorker.onstatechange = () => { + if ( + newWorker.state === "installed" && + navigator.serviceWorker.controller + ) { + // Notify user about new version availability + if ( + confirm( + "A new version of the app is available. Would you like to update?" + ) + ) { + newWorker.postMessage({ action: "skipWaiting" }); + } + } + }; + }; + }) + .catch((err) => console.log(`Service Worker Error: ${err}`)); + + // Listen for `controllerchange` to reload the page when the new SW takes control + navigator.serviceWorker.addEventListener("controllerchange", () => { + window.location.reload(); + }); + }); +} + +let deferredPrompt; + +window.addEventListener("beforeinstallprompt", (e) => { + e.preventDefault(); + deferredPrompt = e; + + // Show custom install button or UI (ensure an element with id="install-button" exists in your HTML) + const addToHomeScreen = document.querySelector("#install-button"); + addToHomeScreen.style.display = "block"; + + addToHomeScreen.addEventListener("click", () => { + // Show the install prompt + deferredPrompt.prompt(); + deferredPrompt.userChoice.then((choiceResult) => { + if (choiceResult.outcome === "accepted") { + console.log("User accepted the install prompt"); + } + deferredPrompt = null; + }); + }); +}); diff --git a/javascript/dwa-starter-vanillajs-vite/manifest.json b/javascript/dwa-starter-vanillajs-vite/manifest.json new file mode 100644 index 00000000..a9fa1bfb --- /dev/null +++ b/javascript/dwa-starter-vanillajs-vite/manifest.json @@ -0,0 +1,25 @@ +{ + "name": "dwa-starter-vanillajs-vite", + "display": "standalone", + "scope": "/", + "start_url": "/index.html", + "theme_color": "#ffffff", + "background_color": "#ffffff", + "icons": [ + { + "purpose": "maskable", + "sizes": "512x512", + "src": "./public/maskable-icon-512x512.png", + "type": "image/png" + }, + { + "purpose": "any", + "sizes": "512x512", + "src": "./public/pwa-512x512.png", + "type": "image/png" + } + ], + "orientation": "any", + "dir": "auto", + "lang": "en-US" +} diff --git a/javascript/dwa-starter-vanillajs-vite/package-lock.json b/javascript/dwa-starter-vanillajs-vite/package-lock.json new file mode 100644 index 00000000..366cc0ef --- /dev/null +++ b/javascript/dwa-starter-vanillajs-vite/package-lock.json @@ -0,0 +1,3623 @@ +{ + "name": "dwa-starter-vanillajs-vite", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "dwa-starter-vanillajs-vite", + "version": "0.0.0", + "dependencies": { + "@serwist/next": "^9.0.9" + }, + "devDependencies": { + "@playwright/test": "^1.47.2", + "autoprefixer": "^10.4.20", + "jsdom": "^25.0.1", + "playwright": "^1.47.2", + "postcss": "^8.4.47", + "serwist": "^9.0.9", + "tailwindcss": "^3.4.13", + "vite": "^5.4.1", + "vitest": "^2.1.2" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@next/env": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.15.tgz", + "integrity": "sha512-S1qaj25Wru2dUpcIZMjxeMVSwkt8BK4dmWHHiBuRstcIyOsMapqT4A4jSB6onvqeygkSSmOkyny9VVx8JIGamQ==", + "peer": true + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.15.tgz", + "integrity": "sha512-Rvh7KU9hOUBnZ9TJ28n2Oa7dD9cvDBKua9IKx7cfQQ0GoYUwg9ig31O2oMwH3wm+pE3IkAQ67ZobPfEgurPZIA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.15.tgz", + "integrity": "sha512-5TGyjFcf8ampZP3e+FyCax5zFVHi+Oe7sZyaKOngsqyaNEpOgkKB3sqmymkZfowy3ufGA/tUgDPPxpQx931lHg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.15.tgz", + "integrity": "sha512-3Bwv4oc08ONiQ3FiOLKT72Q+ndEMyLNsc/D3qnLMbtUYTQAmkx9E/JRu0DBpHxNddBmNT5hxz1mYBphJ3mfrrw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.15.tgz", + "integrity": "sha512-k5xf/tg1FBv/M4CMd8S+JL3uV9BnnRmoe7F+GWC3DxkTCD9aewFRH1s5rJ1zkzDa+Do4zyN8qD0N8c84Hu96FQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.15.tgz", + "integrity": "sha512-kE6q38hbrRbKEkkVn62reLXhThLRh6/TvgSP56GkFNhU22TbIrQDEMrO7j0IcQHcew2wfykq8lZyHFabz0oBrA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.15.tgz", + "integrity": "sha512-PZ5YE9ouy/IdO7QVJeIcyLn/Rc4ml9M2G4y3kCM9MNf1YKvFY4heg3pVa/jQbMro+tP6yc4G2o9LjAz1zxD7tQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.15.tgz", + "integrity": "sha512-2raR16703kBvYEQD9HNLyb0/394yfqzmIeyp2nDzcPV4yPjqNUG3ohX6jX00WryXz6s1FXpVhsCo3i+g4RUX+g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.15.tgz", + "integrity": "sha512-fyTE8cklgkyR1p03kJa5zXEaZ9El+kDNM5A+66+8evQS5e/6v0Gk28LqA0Jet8gKSOyP+OTm/tJHzMlGdQerdQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.15.tgz", + "integrity": "sha512-SzqGbsLsP9OwKNUG9nekShTwhj6JSB9ZLMWQ8g1gG6hdE5gQLncbnbymrwy2yVmH9nikSLYRYxYMFu78Ggp7/g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@playwright/test": { + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.1.tgz", + "integrity": "sha512-s9RtWoxkOLmRJdw3oFvhFbs9OJS0BzrLUc8Hf6l2UdCNd1rqeEyD4BhCJkvzeEoD1FsK4mirsWwGerhVmYKtZg==", + "devOptional": true, + "dependencies": { + "playwright": "1.48.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", + "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", + "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", + "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", + "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", + "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", + "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", + "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", + "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", + "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", + "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", + "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", + "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", + "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", + "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@serwist/build": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/@serwist/build/-/build-9.0.9.tgz", + "integrity": "sha512-HhuRDt/c4vLGZ6k3ExCdZFRLub+ydw3R+rRz2dh9+/SUuGmvR8aFz44Ufuerh6V2rG/DuvjN0HJlOrb4OUOo5Q==", + "dependencies": { + "common-tags": "1.8.2", + "glob": "10.4.5", + "pretty-bytes": "6.1.1", + "source-map": "0.8.0-beta.0", + "zod": "3.23.8" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@serwist/next": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/@serwist/next/-/next-9.0.9.tgz", + "integrity": "sha512-mLUn/cwh1Icwi6IFRUBy3xflnrUhycthiCji2Y4wEpxmRKmrVA5aqwbHRNdWJwbSdO1JSpkpGryn6MCInd2D3w==", + "dependencies": { + "@serwist/build": "9.0.9", + "@serwist/webpack-plugin": "9.0.9", + "@serwist/window": "9.0.9", + "chalk": "5.3.0", + "glob": "10.4.5", + "serwist": "9.0.9", + "zod": "3.23.8" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "next": ">=14.0.0", + "typescript": ">=5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@serwist/webpack-plugin": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/@serwist/webpack-plugin/-/webpack-plugin-9.0.9.tgz", + "integrity": "sha512-Yytizgxcc4577ViUuJEej6OlJlcQHUIUCTsGCrdIqKJxSsbz0yDv4Xx+Yria2UDFAu8nmTqA2PSgI/gg0OYZ0A==", + "dependencies": { + "@serwist/build": "9.0.9", + "pretty-bytes": "6.1.1", + "zod": "3.23.8" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "typescript": ">=5.0.0", + "webpack": "4.4.0 || ^5.9.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@serwist/window": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/@serwist/window/-/window-9.0.9.tgz", + "integrity": "sha512-KfyiBz4BKKs7AxB76NOKnYqNktr1KFaC121xxM0BAusJaqkaG9eAzAGMKeeRxU5S0uA/gm3pQKhf8FnLiliqig==", + "dependencies": { + "@types/trusted-types": "2.0.7", + "serwist": "9.0.9" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "peer": true + }, + "node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "peer": true, + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" + }, + "node_modules/@vitest/expect": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.3.tgz", + "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "2.1.3", + "@vitest/utils": "2.1.3", + "chai": "^5.1.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.3.tgz", + "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "2.1.3", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.11" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/spy": "2.1.3", + "msw": "^2.3.5", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.3.tgz", + "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==", + "dev": true, + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.3.tgz", + "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==", + "dev": true, + "dependencies": { + "@vitest/utils": "2.1.3", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.3.tgz", + "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==", + "dev": true, + "dependencies": { + "@vitest/pretty-format": "2.1.3", + "magic-string": "^0.30.11", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.3.tgz", + "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==", + "dev": true, + "dependencies": { + "tinyspy": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.3.tgz", + "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==", + "dev": true, + "dependencies": { + "@vitest/pretty-format": "2.1.3", + "loupe": "^3.1.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "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, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001663", + "electron-to-chromium": "^1.5.28", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "peer": true, + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001669", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz", + "integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chai": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", + "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", + "dev": true, + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "engines": { + "node": ">= 16" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "peer": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssstyle": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", + "dev": true, + "dependencies": { + "rrweb-cssom": "^0.7.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.40", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.40.tgz", + "integrity": "sha512-LYm78o6if4zTasnYclgQzxEcgMoIcybWOhkATWepN95uwVVWV0/IW10v+2sIeHE+bIYWipLneTftVyQm45UY7g==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "peer": true + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/idb": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/idb/-/idb-8.0.0.tgz", + "integrity": "sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw==" + }, + "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, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "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, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "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==", + "peer": true + }, + "node_modules/jsdom": { + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", + "dev": true, + "dependencies": { + "cssstyle": "^4.1.0", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "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 + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/loupe": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", + "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/magic-string": { + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.15.tgz", + "integrity": "sha512-h9ctmOokpoDphRvMGnwOJAedT6zKhwqyZML9mDtspgf4Rh3Pn7UTYKqePNoDvhsWBAO5GoPNYshnAUGIazVGmw==", + "peer": true, + "dependencies": { + "@next/env": "14.2.15", + "@swc/helpers": "0.5.5", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.2.15", + "@next/swc-darwin-x64": "14.2.15", + "@next/swc-linux-arm64-gnu": "14.2.15", + "@next/swc-linux-arm64-musl": "14.2.15", + "@next/swc-linux-x64-gnu": "14.2.15", + "@next/swc-linux-x64-musl": "14.2.15", + "@next/swc-win32-arm64-msvc": "14.2.15", + "@next/swc-win32-ia32-msvc": "14.2.15", + "@next/swc-win32-x64-msvc": "14.2.15" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true, + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nwsapi": { + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", + "dev": true + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, + "node_modules/parse5": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.0.tgz", + "integrity": "sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==", + "dev": true, + "dependencies": { + "entities": "^4.5.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "dev": true, + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/playwright": { + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.1.tgz", + "integrity": "sha512-j8CiHW/V6HxmbntOfyB4+T/uk08tBy6ph0MpBXwuoofkSnLmlfdYNNkFTYD6ofzzlSqLA1fwH4vwvVFvJgLN0w==", + "devOptional": true, + "dependencies": { + "playwright-core": "1.48.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.1.tgz", + "integrity": "sha512-Yw/t4VAFX/bBr1OzwCuOMZkY1Cnb4z/doAFSwf4huqAGWmf9eMNjmK7NiOljCdLmxeRYcGPPmcDgU0zOlzP0YA==", + "devOptional": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/pretty-bytes": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", + "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==", + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", + "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.24.0", + "@rollup/rollup-android-arm64": "4.24.0", + "@rollup/rollup-darwin-arm64": "4.24.0", + "@rollup/rollup-darwin-x64": "4.24.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", + "@rollup/rollup-linux-arm-musleabihf": "4.24.0", + "@rollup/rollup-linux-arm64-gnu": "4.24.0", + "@rollup/rollup-linux-arm64-musl": "4.24.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", + "@rollup/rollup-linux-riscv64-gnu": "4.24.0", + "@rollup/rollup-linux-s390x-gnu": "4.24.0", + "@rollup/rollup-linux-x64-gnu": "4.24.0", + "@rollup/rollup-linux-x64-musl": "4.24.0", + "@rollup/rollup-win32-arm64-msvc": "4.24.0", + "@rollup/rollup-win32-ia32-msvc": "4.24.0", + "@rollup/rollup-win32-x64-msvc": "4.24.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/serwist": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/serwist/-/serwist-9.0.9.tgz", + "integrity": "sha512-T3WzdvUjvK1AzNSTSuZkHWWKm0X5UuUaD3jvukHDFaJDmsLZBq0HGlrZ+bpOHoRFwhJSXwuH/V5ksE0I78wwvQ==", + "dependencies": { + "idb": "8.0.0" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/source-map/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "node_modules/source-map/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "peer": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "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==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "peer": true, + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "node_modules/tailwindcss": { + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", + "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true + }, + "node_modules/tinyexec": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", + "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", + "dev": true + }, + "node_modules/tinypool": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", + "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "6.1.52", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.52.tgz", + "integrity": "sha512-fgrDJXDjbAverY6XnIt0lNfv8A0cf7maTEaZxNykLGsLG7XP+5xhjBTrt/ieAsFjAlZ+G5nmXomLcZDkxXnDzw==", + "dev": true, + "dependencies": { + "tldts-core": "^6.1.52" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.52", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.52.tgz", + "integrity": "sha512-j4OxQI5rc1Ve/4m/9o2WhWSC4jGc4uVbCINdOEJRAraCi0YqTqgMcxUx7DbmuP0G3PCixoof/RZB0Q5Kh9tagw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", + "dev": true, + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, + "node_modules/tslib": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", + "peer": true + }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/vite": { + "version": "5.4.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.9.tgz", + "integrity": "sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==", + "dev": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.3.tgz", + "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.6", + "pathe": "^1.1.2", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/vitest": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.3.tgz", + "integrity": "sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==", + "dev": true, + "dependencies": { + "@vitest/expect": "2.1.3", + "@vitest/mocker": "2.1.3", + "@vitest/pretty-format": "^2.1.3", + "@vitest/runner": "2.1.3", + "@vitest/snapshot": "2.1.3", + "@vitest/spy": "2.1.3", + "@vitest/utils": "2.1.3", + "chai": "^5.1.1", + "debug": "^4.3.6", + "magic-string": "^0.30.11", + "pathe": "^1.1.2", + "std-env": "^3.7.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.0", + "tinypool": "^1.0.0", + "tinyrainbow": "^1.2.0", + "vite": "^5.0.0", + "vite-node": "2.1.3", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "2.1.3", + "@vitest/ui": "2.1.3", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "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==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wrap-ansi-cjs/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==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/javascript/dwa-starter-vanillajs-vite/package.json b/javascript/dwa-starter-vanillajs-vite/package.json index 6d2bc431..7f36f063 100644 --- a/javascript/dwa-starter-vanillajs-vite/package.json +++ b/javascript/dwa-starter-vanillajs-vite/package.json @@ -16,9 +16,13 @@ "jsdom": "^25.0.1", "playwright": "^1.47.2", "postcss": "^8.4.47", + "serwist": "^9.0.9", "tailwindcss": "^3.4.13", "vite": "^5.4.1", "vitest": "^2.1.2" }, - "packageManager": "pnpm@9.12.2+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228" + "packageManager": "pnpm@9.12.2+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228", + "dependencies": { + "@serwist/next": "^9.0.9" + } } diff --git a/javascript/dwa-starter-vanillajs-vite/playwright.config.js b/javascript/dwa-starter-vanillajs-vite/playwright.config.js index 18188058..ab1c5fba 100644 --- a/javascript/dwa-starter-vanillajs-vite/playwright.config.js +++ b/javascript/dwa-starter-vanillajs-vite/playwright.config.js @@ -1,4 +1,4 @@ -import { defineConfig, devices } from '@playwright/test'; +import { defineConfig, devices } from "@playwright/test"; /** * Read environment variables from file. * https://github.com/motdotla/dotenv @@ -9,7 +9,7 @@ import { defineConfig, devices } from '@playwright/test'; * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ - testDir: './tests', + testDir: "./tests", /* Maximum time one test can run for. */ timeout: 30 * 1000, expect: { @@ -17,7 +17,7 @@ export default defineConfig({ * Maximum time expect() should wait for the condition to be met. * For example in `await expect(locator).toHaveText();` */ - timeout: 5000 + timeout: 5000, }, /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, @@ -26,41 +26,41 @@ export default defineConfig({ /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 1 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'html', + reporter: "html", /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ actionTimeout: 0, /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: 'http://localhost:5173', + baseURL: "http://localhost:5173", /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', + trace: "on-first-retry", /* Only on CI systems run the tests headless */ - headless: !!process.env.CI + headless: !!process.env.CI, }, /* Configure projects for major browsers */ projects: [ { - name: 'chromium', + name: "chromium", use: { - ...devices['Desktop Chrome'] - } + ...devices["Desktop Chrome"], + }, }, { - name: 'firefox', + name: "firefox", use: { - ...devices['Desktop Firefox'] - } + ...devices["Desktop Firefox"], + }, }, { - name: 'webkit', + name: "webkit", use: { - ...devices['Desktop Safari'] - } - } + ...devices["Desktop Safari"], + }, + }, /* Test against mobile viewports. */ // { @@ -101,9 +101,9 @@ export default defineConfig({ * Use the preview server on CI for more realistic testing. * Playwright will re-use the local server if there is already a dev-server running. */ - command: 'pnpm run dev', - url: 'http://localhost:5173', // Adjust this if your dev server uses a different port + command: "npm run dev", + url: "http://localhost:5173", // Adjust this if your dev server uses a different port reuseExistingServer: !process.env.CI, timeout: 120 * 1000, // 120 seconds - } -}) \ No newline at end of file + }, +}); diff --git a/javascript/dwa-starter-vanillajs-vite/public/apple-touch-icon-180x180.png b/javascript/dwa-starter-vanillajs-vite/public/apple-touch-icon-180x180.png new file mode 100644 index 0000000000000000000000000000000000000000..9d7789fd5837767dc0ee6607392f717857c80529 GIT binary patch literal 2833 zcmV+s3-0uZP)DoJ_sFz2w&asivyAYsJvH|5;gC%jN%VXUmwFn5~Dv|LTgH zg!bOGUjOp8o5atsr~b^1{=%e<|M}jGQ{Po`xUzHod&&QCbaJHC|A&cr?!ZAzma0E~ zsCKWuVxzRsj(>@;|Bjp6!d(4tio&Cajcz1P-2eap32;bRa{vGX=l}o%=mE8RQfmMJ z3Cc-CK~#9!?V1Z$+DaFOBfS7p5wu=F1*(G(xu`{`g7pTr)wcit@0_{Mp2-CLKFNfx zHE*m3=_==0kMG{W#31nT@$vET@$vET@$vET@$vET@$s?e`rEgEjQ8T=80X?2<30XI zpf%p3~VRZEWKr_;fcY=E( z4tI5Rb%ka4Cg?AE4i1QP^h#)97FxzRw)2v#2x_z_=mX5mVwHaJBCXjDio1y;kVP^p zZ!-O$BXjJXgB_f^2Mzr~qqXzWTti-kEH!5`nX3g1B4-w+88gl2&(C5=FXqU7_g)=G zXIED>62ZKw6$5L|WY8Noo37xJEEQiI5<8mmHcCewfGp1$J~Xk#V^ z%li8IC|)rOe>~7M>($6m&u`p#Of{&+j)a!HpVtYp2`yk@F<3Oso0?|k`R$^q>H{De zdRCfoW*V;gWMmYpnbjGKUch-A$*o~)Gba|%z^yQCfOm}v)CQ2Ivxs*e4?y#QQRa0~ zj`elfThU;9e%I_1D7sO&TF6@_q%)#V_YYipI03l|!3APF=>( z^LX>(LDtt>dEzsPp zLeJw!7URY~u@Bv|nUU^!p`y9!=yI0Gz_f{I zVP*M%MGIhxykOCI7I$JMP+(60WGtt|B?lG_G!yLcqJJvC`)s^Hg2-Ftt%*^FSXO?J z40O*0v}ouv%hnKmO(}=4az(Yf&^7Zk*Vm~D`+A3sGxZ+qU4}a*-{ORyubhZ1za-&jk(kh63j!{ zoWOlr4hTJ;mL=3Qmy#4sRdZ_1^Zx$em9&~@j$BGsG@iw1GibWD;zqMZj49qCbdrWXD_cC*YTeh+(uW_JXoXxF2Z`qyEN6*bo6N#CX<=rR!a!0;Y4&0Tn6jk886@cPK8!4A$ZkLgwx5e&8g1Ai7rDx807I*m*zUgNZH)=G(wgo+HTS zEtHWB_Y-{(Le0)ZOMvp8&3g-Gj^( zr=s!NiEASo{Etziv z=edf%@%m)avV)4=mdurod+1Ir_Qq?dwTq#pC&Em*L!dcj(PZsO=0b$I6z(1J^dR#%W#*t`Sk|t1VOpa3kc;NbRg^Y# zFcg|I5#}PZyvIZfL)sbr8^h7yA#avH!-O06=$z&|mz;8pJK%<4`dcD64(8#VC zp8!KCS|Qh$LNs1`R?Rq4G+?efUU%rLp6lm5l6$y_+6nR3w*xpIE~_mYPFqIffT z=w>dO(=Og$9kUweS(YgfUB@5d`D~Wro_tLQI+tso5Y>7$esHvVAevM|JfHnZU-14k zE$CeCYtYdrupos3(e-NmyL`UIU$2!KG^QSFTSK)Vl~e!YTX89- z1emiwcs1a@lViw+*fn%3r@qADkFSG-3^BUyS)Rf*TF`oHMI^ z2gZ*-_+F)pT=4Y~#qYBWnjOYo}Tj?KqdpziXm@2F8+4cvUxJ z-gmHeP}O6FDo-Zo82ZK-L#-dD&Y@*HC=ilL)oJ@jqfw2Fq4shu*U;>H+oD8R^AgLQqvoZV{zl2;uU)tLd=|@X{dj~Uh-|0sk z?k{IH`oYGqbqdl>d{xIo8>MdjY1sO48GT9l{v)wf9S?1^8g&}BexP})|K2@x6T*>q zdmQ>aGKNO(lU~(xptV`VH9#D?9~naf6-~utNKL5_LnUYb~^=)|BO52%7RGDPHV~+b#Md5$H&LV$H&LV$H&LV j$H&LV$H&LVXIb(eQB_jpur00000NkvXXu0mjfQSq?P literal 0 HcmV?d00001 diff --git a/javascript/dwa-starter-vanillajs-vite/public/favicon.ico b/javascript/dwa-starter-vanillajs-vite/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..07f419ee47e8d9ae78bc11ec2ee7d0f758939c95 GIT binary patch literal 1564 zcmV+%2IKhv0096205C8B0096900ssC02TlM0EtjeM-2)Z3IG5A4M|8uQUCw|FaQ7m zFbD7L_t(|oaLBrNL^(d$9)q- z1VJy#MFdeVgfXKOT5zAcz|myfdZDyj8ak@ASvS{~8DUv=-9YdrBV^4x8gz$Vm8qp{ zV}odAksve_VbN`*17R41urTI5Pkhfk&+&Jj^PF>@`^Vhq#TWHlz0c?Sdw##~^IS_J z2j3~VlU1@Ai>4Bn?&1rLWqe^z6JM>tl(Tw1&h3g$?}erW!DT{UH7HYsJ}o*DacXwYkcrK+vmCs!a|J{c(PkgbDHwf6yk1~ICw;Egs z;L!0m4Sw?F)j^j5ynzf(RX?__rlG80?CleL3dZ~(U7Fo$YwGN$e*?C&!{E@-53-WM z1v~^+c$_BPOs4o(`|40SuHmu$u6;0YBK8 z$CX-}t6YMK8{<12&y%fb7d#{fhvzwfl%eom;4OVwjSLNVLTc&fM{UiYe%Aqha-YE= zBveiZ8DdojUfTeH^i#4m?Se=CdtEg=4Irv?;NSa9GN1`+>ZeB>LiJ_%Qw;{kVV2ib z0cz_Gp1_B@*`t|`^qWS_{NarFMXaK?xdBF<< z$Z~weK_m_&8PrR|&1naGvew|EJNbt?Y+42&?1Bt0E?}zbfN4MjJ{>>cfR{)bk<1|ZxBgFbX15@lFfsD6@wLprfp zumQv>?k0Zsc5{F&P_)v@z+(=0?9Sxgv;!UrI<$&n0Kzu=eds`I{MdPd4>a8{69(V& z(YtMl>JJfk-PkOO0SLQ5KkBJ2VIm#@Obwv=6#h*0%@y7MeiY3Bwp;$dp@N6Z79!QB z@Z(kaSHBp`r_ z@EFkD?~n2Fu7s(P#IttwY30kU*CCj&*6ay|LZ$zS0SG&Sfu`^)G$(8SXG5+iCjlJGTCaeUCqVlv#W|DLzK0&O~>e8J6G~lrls^N`f*NYMZ z%R2Fz_Yl+e!4N`-RSFGQ`ZJQ}xwerRd3Yo1tywCqQN57{?DnC + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/javascript/dwa-starter-vanillajs-vite/public/maskable-icon-512x512.png b/javascript/dwa-starter-vanillajs-vite/public/maskable-icon-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..f9b949c2291c2a9e7b74db5492cf8df89cbae21a GIT binary patch literal 11375 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 literal 0 HcmV?d00001 diff --git a/javascript/dwa-starter-vanillajs-vite/public/pwa-512x512.png b/javascript/dwa-starter-vanillajs-vite/public/pwa-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..aeff825645e27cd16ee725e0411834009dc14e83 GIT binary patch literal 16976 zcmaI8c|27A7e9XQEXF>PELlb&NoA{SF{6!A*?LEb(Oae7DrDd0UL@L3DlM2P6-6PG zvdl=K5K5V>V~NQ+7>rr&{rY@=kKdoa-#i}kxOZOXo^#LZdCu$H*Lj`SovW^g9TjBP z$^rnOu-|EqI{;u-PBDNqcI8n2T)%1M5bJvI$linJLLO2Pt0Ue+6-Q&Cg~uoPTa&ZT zN2S@@+uPaMc^9K7$KCSEy_Lq57P>cbHvmDq&0ics&>zNVtNzUp1pTOiHj>cytCC}p zbGc}xEpjOn{Wl*y_6ChhLD3Rv7uJf9J?OAk^PR*OX?0$~)$nolp1Ayq{cjm7Y8ZvN zANBxl{RVE-P6BT?N` zJ~FXG9~3Xh$>&UMz__rvuyuXd-yVH2_8J-yBJDEh-X}g%5Y&kYtiu#x7;^}Il z3~a8Jhy@VOk!wncYdNzYYgHGcjdiOpxLlWX*eBtlj!u$Y(uXaa;Qad9#9D!B|EI>l zDX)ZLj>(o&Z~#lEA#M=+Gm8TdZ`x_jvp;$Z;aA$REqZc$IsPY!AgYJ2dE?duq$f)9 zKh{1Gk+)7>cif1Xss5D2=qb%@6(Q9pv1)h4?61w9$0#|#1t{mUmiK9;UNJz4q&#SZzXER z3qxN#q1K}s`mEM}(Q_Cy|7c5KH5nYI>)n^Ww4&LoyGwK_p=?<3{l>NF)eL=8*_Adw zbpP>pYbR~Yig%v~sg+0mdN%=ex zWzp~`oB{f7eVa3onb_~vslkRGK0!RLJnDeNWc6#Tt%Cs@cEEp8f#tMW0X^bo;~jLp z@#Xa;f#QUwdS2H=FZ6vIa<2NVwEgd0Qe4v|I;YXt8Zj%zOAJ?q(sj=D4-gWuVNSsD zZZza1dQS1e**(yQy?p^WY~o(OuEqRc$G@d2{yjw@Cu;>?NnT&Fd;aGleM1p_Tc5=% z$@mkEjfxPgM0Ojf%RuXfznD)(yY=2wa+DZWXS>o@fE>|HM}t zcUzr;uUoP5PwyQ&&Qfc0#YLRAbIcjo(!`CO{Sb9lt#U@b9i0t%Ln71oL2U5#D!#g8 z)(LdU8Ct7oI?1e6{Ju@QdPmYLG+~m9f0xx}Z_+xcCp)jcUQvS)bwaRZVkwk+S7B`> zE1mf5Vv9n9+M#i&xnbFGiGl@XX6U5LRE3ZDu3E3t;YyXC9^A&e&Nm#D;*vm`uij+B zXGi6;Bvf;Kk{pA)K?6F7Tr~^9BqR816r;)Q;;~Bjb7`t}n>`XnV@ zPb(13Hc5M4XVM-pOtqlI36D|?zg|*=DQQAx-*4i@@taL#Auetz zv#!l1ns$CP`do(Lx>i1@#PjE37c5vZqR$@z$Stv08u*IhJw$3Qc<4A8FBY5~!gy!M zy@jP^Exq14Ns+a=&OX(p$5^Fd1np+vA5G zob$AXcWx3mZ#a8Xo_5^!-6gd)^RHRPRo_!oY7_aM{id(C%pDSVXo;_PK0%#Zz{O{T zPXXJK+U`MXX7pA8gI)Hn84k?kaMV2+LS|tW+fKRn^FtGtIYi?z0$S+!`esNnW~wv&ZIH^PTiWx)9!#^Mv|)bhEjs<+g@61(S`nr4PCXvm@n= za@@qOl66E4?`xDBlC6+AC;!B9z;#4@6uc{O`85-!mHLy^ELlTL<>qCZ7BPvter)ro zZ+?&?a%{lGtX+P%C?nb}#ktc@ycsi_v5RW$aBV;9`_d~F04Aff(F0Cc4e5@or~yA% zd@M`e>1?{=_7741z5{!v%rRf*9X3T_F(FF$ZxXi zWv_EhSC;}Vx?YwXPALAD{yE1V4l4~-q^%L?O9Dw&OiiD>d1kUU<)MVUc|Wkno(B&d z6S6w=&DGz?>z<7XK3;!*AnpEJMWH0>JmrEpApR$PS8*Bgx)Z#i`4kZ1kDxC&II|Oy zb$CAuOo21Fb4jGcIwQACtpXx2Y4TT6!G^fip0d#x(^m1zIXzyF2BnH}^l^Iq03A#f zzNo!fAoXg&5u zW3LI(RvuBj6L$@Bs$F3r=#fZ$&c%Yl{G7Rt=EM3R@5dvu|A2u&yw^Hf1i)z zqo{pz1m8qK-`1r9;s_L-2-R_z^EYT75|hoJ$@{1t6g^B-^lux7f!mJ<2rtC;r+Aj$ zuFK~}Jq7dfa4%=9se*2?_Q&Fs^c$P~$gtUu&SWFnsRohs2DuBzbR>JkQ(?TB&4WRc z@tZ%5(x(wON!AWSz!-o2!B$gm;e|i@fS-~KaECiDsd3a)S$1bRy>5H(`>?i;J8!dd zhiQ6P*I6dd3AK`APoP$7dZ0sV7~X`rI${}9PaM7qE@W=G3n?Mv-bhOmhN>~Iw}E?% zb8J@pV5#$3}(?@PIe@#{hD;|C5sz_~6u%CqX3 zn^{yMj^@W}&T$a?OVM?HOdg+?WIH1>Y<99xr_rzR>&-ufHmFFO$A#xeV1?u~M)1+}eUT zZda~io-PMn&EV6>quYPmKE{lvT!&I=-Z+*k>)v@}{WpSerd|hONc>&lI}%Xb{3EOX zepslZI5*7zxo|Z;?5(F((`3*XSMYsu##h8>&lDEhVRUVRoi{+<=AsT^kayuyzJ_0* zGoUMWvFGjg-1hCqq~4jgKW-?g(lm6}DAL%L=+DXYG_;gh9wG04b^}U`Ah39t$FoTz zY!MwDxtezoSeEqZQ4m8245;CSO0IBdNPbm(sCdO*A_j zs!-UZSG0d8$-N4I?y?VWm}im+Sl=412cnXSLki?HSY^xf?kki_%BdZr%-?8W7I4H! zT84FBoRmZ&T@nstd?o!v7x~O>gJc_^>}GNvZE{L=$_99~9QiuOL~YWKpMN+$VTkFB z*%-$8#YRpo(a61@>DI#4dDJy13<8L=&5(xN#9E&{@3&w#xAUPfby2CXZHLgm0lEW7 znY`-0=MGyhqro3w*X0YAnuSPD!AS8>XnBbBPsGLefs94NA^P~OEhn5wMh}*sm<+w3 zZbE+Ce~cV;rtAX6b;NDUYS-YKooGh|y+v|GXd>emsxDWrouIIK`( zGz9eUkkA*DE?@1{3 z&HGF`#}A6275ycv3TyuwNb8#5_s@9RFP?jZv^UT%EaWBXyaqO}!=G22mWdD8;Wq7O zN@)w6HTx&QOVhpW+A za{|YOxssC22)71`ne6f(sxPN`O$^0sIE*~bBd67&X9AC)zrN7diV}DOenj@E95w#7 zQA1U->%H!7q&J!T-%R9SH=3Y9KCQ{pUPW;LQ0p%0IGS8)@XCSI}sCN()dhFSmi2y>NUpS9_>`?L4=` z+v_Ogff|!}+_v9Bqk8gm8jz;qca2QUe2e@Rk_sR%N$Ko>GWOt0nquSZHew}duT;sT z#j0Y^qpt6iiT1%wYc18PH`3G= zGwC6lCneMZ!sU&?g4n*d#pPCH1#s^<;{EGiz0~o`Pnid z1}+Eh%nc4~2eq6Xj)>wbi$%Z9FOZub5JTrf%TCO7Krz2=L_eye-;gKNs*9s7{gjZe(yk~#XB&mHe0}Tcq=vL4(|_3SQR*Iy1oFwle`K|2nv-h4g&{! zA2}4C?2e=QP<)15@Nd>LKZmw~KB zp8X3n7u++N*y*1O1SQalYVV-I={_R8kEqkKy6B^#7-LmE=X^sVz!)&L;+M4mN60&U z-u~&*^>hjQC91bLk&Q85;=H}}QFHg@{q2vSEbsJZwAA?Y`dUHc`#|!)nV|eE)tnOd zqV2qR@IB&x1o-un{6S!_8vcrT;5wSq^T|R_=czn4W*6|M8813XHdtI;RmTr{!}P)F zpeIs+!!{+qN=Z&4@8|sCc-BEoAn#cef3sa}cUW;pR~`9^V7;U6cNg@2hfAzgciqkS zKY*DL;@>&HP99CQw_Cp{!0YRgabuMQw=cb{P;>T}?1KrZ&Pd*p>9hE$B42rENk6-U2T7y%n@l}UjVOtl8 zaGq$leWoNentT62MmYO4a(lZMz}!g|Q^-0Pj1_ z)g7>0=sT_$$9^4uY^#qvV8Qwj45XjyyMJzAJ>fAPt=!Hz*QqIQ`a`~5Z@jHvd|hQh zjeH^-*oHq}IXch~Kh}8rJgsSt^aoK!hOV2wD*H9BTs^#_zMmn|h5olkdVQCk?{i51Y{%uD ztX7zu-{3bHI&PA zz}~@eGM8@h(w`KrV%@^Dh-h|O#UtP1f0tPPrdj|~J%={j)<1i9=I?~YX<)go@>7vo zY%-*h$tKqgNZgdv@aI3d2v6-Gvyx2|rMwD3(@)d{=#9?L$cC3^s&;E0{gz4V-;)}G zxY-kFA4q{LOYkjHD|@F%TRYae_ir`V(O zG2vpDXAA|zKuwZsOpOu*no}Ot#NGorO@{+w4S%=sEj6)sB7(Q0d0xQ@!=X{}gpEhw zaHP!>y;nmmLj5{T9$5k2KU>esn-*qGY`0@4>Ug`1Akv5956v-GVXW>ZzOK^Ya#QXC zfuW+vLq}M`6H@m(7B{aRy#pRho+;#cv9~YYmAk{V_WBN~%-g#Tk}GAz={CW`m2;4P zjt)cW?{@B?{MiS-LH>noT=XU_Z20i+^H+l^}cBY&JdU8gTd-L-dVk#_KvL zQ=kTQnd7x84Gwlzoi6ZQhVO7cAO3d!N)stS_&_0g`CSb=dOTeYO~hPzHw;MOOCo8h zU9?xfD@eyA#S7b_cAWeqxuMxQel(3L`ljB^?e5na-9WKrvuiQX}67gJSL-Seg!HJrmXi1_7?=o`b~>7 zUdQ1ck*q*UU)vAJOd;1njipR!4}W{De;On8yUa9p*NiK$jUTcQ>2IL>1Q;FGDe|n{ zn*6=(Gir_JZ{WjyxPU&_CE-EpX%+=aSw9npYuoj@RZ1 z;3X3(ruC<&geaSu!BV;sKS4kyM&$zQ2Z4>5NYHISR@UnhX|aAB-CnbB(_3=Pna{*d z0P?@-xBetE=-JLQ0jmJJ`TD1*V8a^S&G`5w`?^C-~#d4KaIKCMzr-=Q<)kb z-Ii|?s94GjgwgDOise7BC6B0by4k{nY-af<^mW|fxO)~G!f<*YXVwk&jKD1wGdJIm zolr|>;H64fuJG88@AMYvUZAb`nOvvw-`;WB$F8|87R*cl23#4dr7GRT#|i&d5AuV$Kxw?!^h#{eV5lN*cb0ghi<=X0Wm~|OqMEAxk=%Ml z3R(X0AF>DLD6cV+0_3~9j!6`t$?G49FUhf^`4@xl?+=)&z8xiZmG)okS_dN3batLz zjC5qh>cV-7{0U@^&n)kPHX`e=?M-ykL7zs;;~}!fSo!P}#6L|OIHcz``h&`BZ0IH`T=Z3S+fdl^$rQP9b(fiTujQ2pp z=h~ytGr3ckqUTR$T>H%2wwklbONL#r^PR*V$w_t2FB!^HV6Z(uXtwx0sxC?*!=zO#9rxSsX=;5iu_yIXg@Q*sTquUiwq4iGCtnQ)yrQCH{Lj zZ7d@|!_Ve3drYt!?{}3Jp}<*`VK9Kk#v1h$rnWpIp}1BXHcgcAd;j(@8hK*QMB1+_q{UkU-kn=V5{HiG zgW{sL`*sUza`vXxngsRl=`qh+siMcleQUR)rt_<%xJ3-Q?1i|ioT~(i9YAx(QJ$lh z2BCBuu+eXe&r(g;B<;;ObBh$uhw%&*w8%Q}p|nPhLmsn&W>Hkp|-Gm73r3?wySFfHAh*tG!2~Uunt1M7D`5 zNTCbNW}yIF@Dm_Zd^3NZU{m>eS+l^Xt}4+tNpJkQgpG z0oHhF(!%gK5}HY30k$o`+s)}$N-txSuwFJxm!|@%KV%uP^npe58uB%ayE(a_^o^68~%&e1WWR3hnwm!^|oPf*7nGWcY%|} zt}MlQ<{3bJz8f!J7x1R0?6JSp;*GDiE}ZS)p3*R0{S$Qh4lw7Q(X)J_`x=^KjW+(I zUxIUQHRoI06J8%UIHAfv?-F#TE9x-DkIys^W{yvA{@72YtOc#h$kW0{dE`tmX012x z>r>MsfW~zDHjBc&{rYJSigABzpUToZVu@W1>yR+>6qZH zl1muQMH!Bl?8kn(<7}H7a~IvJPQINvml!H1)F@s$p6F`~r)pr1UtSj4#hd3Q0i4+}5FUtJ~}byAi4LSzcUINdb@$8h+yFnAMdAG_a>8?aA< z{3rtZ9#b2oDyuu^E1~S-{i$uG^=tl;>>JA>)Ru>B3az=Z^ZVk|SoDpZV(aVc^Q1~H zLwhleV-q>H6zT}7{Z8z76gp*S#lB?c(Vp4WhexVE(iF$8zIpin?gcRN0~#gvvW!cK zbx9#7x-`I%YlNXf z;+gW9<~BHN$VDe*#a-Idg{^;?p9$u#6M8;=8tuJLpI}>-ePqQpncnpLv|yBal}hK767BS2eFSL%NF zz^5d3TSzpq!%)%8^N5+LCGEmE)%K&m65tHF0@HC{$V7DS>`il6Q+&+CR_o1<&vv|P z(RZ<?!t95_3L>A>0ABf*pfn@?(8+ub_kvZ9C} z&$oOq(H^u{^oM>8xLw!Woae?;l$`WLyKEn=z9Y*Mv>ImwtQBJqABYESJ^pU-d$#efy7guGY9}8bAF*?oA0mIRxW*bTJfdW zX>uaq?}i6?3)qrId7cx_mCNdjY4u$kJOfQh-6gWMfkdX))A7JG=%Gw*T%qYjrDf<$A^Xx2} zZIXDceqGxK;;xZO2&_c<9;rn~?tE5pdNOoOc6xIX*$~_uwyM&qB5})c(t{_EF}7v@ zYx?jI>FKriN^_z2SA`LEBk1DGVyfL0;wWIKUFrW?{Lho1EiK4PURPVMf~uY7gx<(@ z{^zpBU^IKjoKm&v&)s2Tm_^~O=*hU35~u(m-2|?=2M73yrHOIxV<;IQOlYyK*!hQ=9$%(WS?S=WTC>C&nT7+X&NG&Ne>D6-;ywCd`NyxX6osG9TXi4RgJI_IxT! z_|F_+En^RKOXvP``?Gz+JH8#+)#J2yLfmHIDZmaAXQ6F)uX~AMgV4>xaYfqW)M09T zsD=a63HVz#InrW;Z8;=}uD%&`AC%GwK-Hz9oG?w{3@>p{Cs_uO73C-_&s}}b}$=iluK?fYMLaS2Yquh4;l zrTi0|1-Ds9W4e6EdnWrYouRO-16e$!9(c)26o=YoB-Cu>E>EUqCs178*oR$<{*6uT zYe{F35rfimvuH#_ICF{+SxfY7Cq2YKPW##!1>Us5>V zQNr>eB(B#@7Sr7otPG8{)T090)m{cER?z2C5(58pHAz0xk=?ee=Iy}FCZW~;}|D&2k{&aCDscS zzAJi#7a0jZXkfmSl;iHV-HcLGt~oK}&`KQgt=S>1TldcX7A^z8^W+7d&lvH1$2{s$ z(5OqC)C!$_@GSSyE?mCTZ;du1IPO}X!$z>FgVZEBfZs^~Rh}_WE-@nh#51zT(tbt1 z#Y+$F2Mp5NR`vKRZ#*asy#|WDqL~W0STq|mnYR)&t)AEJn@JB()cMgktfKQPS~^-@ z9Cla^ya(L>P&^c$ffKq60ntWWM=*6MG8aSH0EZoRj0*h<+~MYjZWtY;9zG<+@njw| zgx9djlqlQR@HHe;s&9W2rO`RIS|)0(kh)!TX*rMRUz+j!!TRyPOk8*a zQ57~{JV{6LzlrH9)xIgNDcvwO349*fzxw%3(CYvskCttu901>T41D{&c)F`rHAWC< z1FR4F3Os$7^*A?13GNq`Z9_Nl^YXdi7Zu$b$cex7tw_%k^0)1}k7G~#Iux=!s6=uE zr*kj4x8KAVH5Sm*fwX%c9HFC9P6^W%K7Q*eS=l9aqay1UqjtM#UzI8UekGUj3dfoG ze?ggNoLyST@5Ol4NuFVa5-UO4ep0TyXelE$dlr{*{}Jid8Fb7YW~da|Ku?7!9`u|O zi+^oNs=6~KIDR_S{NS($_QEIZTbRBUtGfr_JvTWsWovHa$2%{ehjB12aC{2#5Nvq{ zJ&=NNjJ|B6uJ$F}SQ1955Hcl19l!uK?Ua@60ApBwCB0P8=s@yRW}QX$Z>P_8o2Z>C z9}eUrtEStWfxSjex#BlwWFHi`PBswA{U!`qpTkIIR3zD_q z+$-R4NAWh@|0Z{QSzHftG|`dK^tXedHWVlzdydZ*pL`vc@djFjge*K6+f(f@xf_!~ zM7S70$jVe+G4*$(?c&J=Flur2e`II55?;bCOl5t|Eh2*-bPn;CRo`ih>@_-j7VZ03 zAxQbj+`If)HtrAL;nr=bu#yzDmr~1?lNOnqCdjX_*Su%<7MRX- zH|3Ce#|f>7%OSu~)|3mq3-(!1DtTxHiy!_h9&ghFa>X~loBVH~buD|Q`kVN# z2lL)y&`-Sm5NTA)C~0$eqdxO|#!^LPyg+XSE73hb|k-YiuGmm}pWm)Dl8;aFoza)j3f0wONB zGvV7KU-{q6lI`(+Vl2kW5j)*M(w>ZMSZzN1)i7e-;tq_#vm==ALkGO1OV%*HBJb5c z9ZJ*zYQ|`NX zT{LqUKJ-VsaBfV1z0gg%fou~RVENf*#ow2GnflBQ2WDe5 z+#@RKq&+5_8mBnV2DM03zjaXMnWHXd+~sz9DD;l7A3OlZtA43jNewYzrL#lj(iW#C`+A~wJ!+8GvAze6hBWycoP)r;C#r%c7KfTh)f0yhqG@^dL&fg?El|>kL<$~ z+G!IYk35OLhE0v=!S`J`-!fykzRX7m~3Y(r4WzF*r>Zu!&69;sPnJ3x-DH%BEO#0 zcxx%)@Hf|(`FS)&e<%Z!*D_pnHTQJogX~QheIUfcJ zM5N_%I1!@~?)NoU9IApEZ4t@KHjV06S!}71#C>}cKl>6#E4E|s5;r?k(0^RQNE!0GlRD2Q_r$#|fK>{FDI#`*nBcoF>@{b(jAd&zXi9(XzJ^;!D> zZ$3Rrt3`(05IBO3g%GO2HDH&_StEQ-1vzwFEep+7<8{~WB1@5Y58Uns2w1g4QU?H4 zHLp6g$GCDg%6R0sTr6gd#EgzvESUFHf=<*?X_`t8@@Ea#W+=m_mmXzMbb&x4uGQRw zhx^IN*U2~bQgBD3nUSgOhNAIw0sdB72L&IG7=$*`)*!}ru^5mY&hQs%W_pu*JE(4O znj~A`&rg*nz^OAb*dqfsYl32By^@U>E=EobG`abYZR|Pe5rhzyw5z|@xmE%|v*t~e6diPZErCs*~X*2-4;*(j4akHe* zpUh3D_9jX+MnQDnW>VbE-gbGEl5}PBRct7z_iD4>t_Ff5`ggu z3i1KfIu|mPxe8t73SJfur~U*rP68Mkzr+@7+#%%85_}=YJ!2m16{TzI0V6VdkQX+l z4T?ZQV-B?i=UYgEfn7xI3E5OPiOX^L?GW_~l!OdBnHPW#m2K;=N|;owPNr-iu!T#R zZh_X?hB9AB9t#6@f>|+Fh-X7dVy^_x!glOSAKCA_(UBHri)58DEfw61CLkjZ ztep;c3T?K5@exFf7pUl!a9{-xg)qi@;qcF8e|6ScBpJu)pbtM}1&m|MATO*{vC6iO zq#HDM`uKn=dQU#%&RW-9bS28j4=hjvQ-BI1-7|;d^QXU3_XB1E0~063SaRqB&C^Dv zKwe47Za3k!#Xtm4uP5&S`j%I$4{(G+1He7Oc#9Mk%=VPM7C3M&N05?3cEjoaqscvi zampC2S2n!^kGTVDCC9Hr5u?`~YfGi$pLA11^9O*PLTA6_cPqf%+=q#pHK}lnzbhxe z`Bi-C0^{B@;I51(_S5=F46iEFY>N9h2o%t&{G z51su4crT^oE`H00x~E##DzUDehQG@tV$QqD4s}4AmXKCeivCvGDz39KH|G^_8_X^-xER(WKgL3(o6jl~j&FGB* zM;`(0?3De;V?t-5B3~D%1ybu4Q+mO}cP#X4_Ia!z@grABnqiG+cS5Jm)BgKRa$Mv! z(&sgD@&OJf%YVf-H;q_%f7{le_vWe34Yf!~F*u4Qvj`#E?~-BfGU9GUPR|B7YRB1T z|G-k-q|Ya;Xkvo*`At_tr@xUWamx$fR1ej7D;6jIz<`_H@Ym$ckr!RjKZDFE3*QrgolTyqimPSBdDx!u7^>J zf$t}EP`RK_B4+&t{+H==J7o1P;DO~21(u{rj|{{OS0q~Is5=n1j>td6AO0Bays5k#n%hQ?EmyR zW6wnK4Ed6BS!rDRKSt^@*U5|1q=(3!UP=G48aw!Ir^t9RdI_$zEPa=!@amav4X^bD z^0ES2vpn0?)y4cVPe&r+W)~(-?Z8lOl20yX#Tki~4!yDLuOfW{`_aJjGmb9m#}7D6 ze|Kq?y03$d4Aj!RH_uOiPFT**fdQQcTb9Vw3RuK^lkt5l%_@XSPmf{$L!lk#X~)*E zWOGHMolFVYR}xe*)6)Y5)qw?O_NJ!)G1&oQE)%uvv@|Ec*a4@zFtZmJ5OgjNEOCG$ zqWUwx%R=Pvv|%gV#MZ{HM}^fPa5+k~S7doeX3+^#D>y|?{zei>#}EbNtek}Or@)Cv z(EHWdE7ZE#K{~0!JHKT`HF+_5;;8tx?o+AQ79o9gGTsF{#=$lPfplJnot zYR|!*C93baWs97YVJwp4jyz=Jw%G!H2z}cvsxZG@LD2eG^nY{!8Budbla0&uLDD)x*fcP%a9a&JH|-KP z20T@2sT4FWK+VcL@Hm)b3p|vas|$LLK0Peux}KGfv`q~xEAtL5t|+uv8vGa=GEB8v z$b{w_nJwV4k2<1%IE7tqfh)|XIHG6f@K*fl6OuA(-50mOms%OYH6+2CH^qzkxK7 ztW^(q*q&E&RBEGh-Q`$@zN;-Z`x5*NsZZm*`$r~f$(nH$tL4L~*(cThj1e+QYM`A& z$E_(Q{+47vY>A#s)XXdRj3TRWz4Lkb%Lq9vp&&xaN;NS?_PieaG=7Dw(%uP9>i8+0 zBVS{`EmlOkeHgoN?XRG3c(Dwe1)J3FSvsQVCo(Y&YJn#tFQ%zsXQTuY+v8@#qI<@*{v*X5Gu-lSlSc_lvLHUdaQ$Fur-e;wiv| z4{`0quOhCvOaTj@W{tH04PMt;+$}BO15@T1dPSKhVWK*wgz`b4KIWuZ!G~Io+}mOc zEsh*3S80kKW(>}JSkrz5D~+!Dd+6_vU(lW!&JB6jKk(&ru?yZqAC;G8~W!jainn^3^kVDSO6 zvI}@cH8aFch5`9XRrVaE1gvjgrIe(9u0m>KD4a^$EyJw?A`gH**08b86?cqPp+bS2 z!|#Vq6p})4zIll;A*27MB?B8Rim&~0ol%S9#d^h#M6a0fwM~M%{)@;cc8t`8kR(B%jF7|i^Ok5E;0(``SujN_plxeB0Hxxx>msrfB z(j2o;3YHL67<*jU6(ol*+W8+071lE?Wb2q0oLG(*@Y!QPV{GE)cQ|Vc;3?d-2^-Z3 zKz6KyHn&$6bU9PAS{&PorTNS4miK~ED0uO_71o!E)1Pvp^x(nB&Da6knzgQ9fyNlfHH%{~hrwQ42yhO$Hp=D>4!N4?G8G(hL|in^cWVOels zEz7VJedP!+|EuvQ-oy5rc;IaOXI>q?Fy>=gz7@1vVJx$uw61s)$2(^_Ey#lBP0-+U zTw;l~uOw{qDGOJsbFDd^6UyzDggD5ZQ1A%stU`|leH_lhepm++0`b+LwRp5Xc~^Iqci-ut^w)KPo*Jx~ zLz?z^*lI7uWN#ymci$nGbS+bH-&I^(`O3wA{s{Q&!!%&R&xD*nuG zR&%0vvry+fu-~TWDyaqRPd7~N?=K1)li6!Xuy4Bq&-k4AR22$8K1;jy!t4Ol#+)DA ziBXSud6mS=r4+^o-f&L}q<^~u=lu61AQYx*`-r|@!B&TFy3xP#-fb4x{RQmX&#JnW zuu=ea)L`7z;=TGIA55}lgc7)$u;sU~AMU_Q>#{_FGLR!R7}1K{qnQ5vid;5m(*oRll;Gpc5@jT4+fq_A7$J(>7lJ{wBD2IHh+R8`ad2ZN!u|IaV3FQz|Pe)1P+(+ad|ag>#LI+rN#6nTX! zJ83r(PVB<;C;g8q%sB&ZXk}4N)V=`k=-7)@vVwp{ro)P`#m_Guujxu6XdJ^hLjj%v+3Ba24E2RfAfo=oHYpwmsp?mIaAH7NBuIB zRoa~YdAk)ctY7A_W*gXN%PMhrvDodVc=r0;foZB##0)St!5Y?F32smK%CK9FI##Yy z3x-c7xwjqy(brBu?df{ndu`4M*`~YQj3g~yVa>Z4B$Q>K#W|>be|0!>r77ZX+1;78 zmD?-a>1If@+BfJ8#4A>&Vzck!4m{C$>nlwQoR`E_MQTK85Y%^Mj2Btd3t zu-Uso+5CHV+r$>1q_=zfIaZ4 z{}1D@@5w8bkV&}Fu#(+~@ke(~JzxB}Z$48F6$N?U+z~JfX=d#Wzp$Pz2T}Pk* literal 0 HcmV?d00001 diff --git a/javascript/dwa-starter-vanillajs-vite/public/pwa-64x64.png b/javascript/dwa-starter-vanillajs-vite/public/pwa-64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..287a1722de84e8a59e74d45bb297e4a5826bb736 GIT binary patch literal 1575 zcmV+?2H5$DP)qE`K!S@k&M z5}IND|JE*|SN{LM7XQg0|J^sRME#9${%N28igf;}O#W?||5~yCrc(Z7r2k;5|AB!2 z|F#WslmEIm{(Fc2RJi~DuLgFF|HgNqzKx~zx-+?+oAsh3bYahgS=-K$dEL2T?y4!8 zm&%=c-{GECqJPzamg>%@dsB&ql$TLblYoH$00264QchC^Rc1 zUtq__i^byPPqKg(Gw^xy1NihC3IduTe>0h#A24`Ubd|9+sD`pE^!)EN3sNOLZwNe3 zpAuuB?UjVgmgsdieQxZlZvLpnkh@q(&+@9e6lQz+ zner4rIZ3)CRV$afH@~)$9m3~%&#qYUEPnz9yIy5?v&k%yg>f|>^KLxhrCmM3U$CoZ zS(${-cW>SVyZp(;MK77n{tL1Q-W>q6@|B1GuZN^E37_gcJu-v41}^y#%Od=~*yl{H zGJN&6o1`)^zQ56LGzku0tzv_ZUVQ*rdCc!ieaFIzy?nKLdE1Q=nS@{JKUV~M`Re6m zy^AEWFkUF|113|#;VA!-!oW!?Q@&ij{aU|= zqtiKLWn%nP95Rd7C~u#9lfge(gij5-T?8**YGRVAhWS%z=yedoxHCEKFi9-h7(exl zfj%KH%fsZbKDnx4UYC4sB$4GiE`Hu7{Ic(ry2uPZ6OmLkgzGx*dnroH;A@^cY7;&- z!nL|)UmL1=ciwK+nsxxd>%s^Iyfe4+oqO1OHNdZ~F|Lav-Rv>SlcT?XcLl0perB{^ zC_;(B3x#XouMw_k(uhAUM3$ei1JE>|J;bzfL(SWKp+*DHG|i`lkq}k{@|0{ml}a^n z0D#Xd2LeNzFp;L3T@NqO<>QK?w6Cr;#KWU9#c>P%2I=$!Pxu0YzF*al!3}yAxKKJW zfkVQM*9^lh;UoHzPXr;3dn@TW$v{!S zAWlliEx=2glS2$bq4`;qWk3;@bzDODGz?84B}CytiT%3pj^n13DIR4IM~#RZ&q)dG zQu`S|m0m!=h-#qZ9~*O|grIfwLd0h$q70y9b2xoe{^zuW!DtkbTq z7{(2Kgc3%WC5ChX=>>%vw1K3A3v80389)PZ4y1&$j==*zg8*H1*|2kf5{AinpBS_i zSOe|}rrz>k@Q*@ENVPs_D|ie9S~m!RpQF3b9z5v*TOkw-2Hge+kl;v2y#44Xh{XLl Z`X2-%6G=v*4m { + console.log("Service Worker installed"); + + e.waitUntil( + caches + .open(cacheName) + .then((cache) => { + console.log("Service Worker: Caching files"); + cache.addAll(cacheAssets); + }) + .then(() => self.skipWaiting()) + ); +}); + +// Activation +self.addEventListener("activate", (e) => { + console.log("Service Worker activated"); + + e.waitUntil( + caches.keys().then((cacheNames) => { + return Promise.all( + cacheNames.map((cache) => { + if (cache !== cacheName) { + console.log("Service Worker: Clearing old cache"); + return caches.delete(cache); + } + }) + ); + }) + ); + + // Claim control immediately after activation + return self.clients.claim(); +}); + +// Fetch event to serve cached assets when offline +self.addEventListener("fetch", (e) => { + console.log("Service Worker: Fetching"); + e.respondWith(fetch(e.request).catch(() => caches.match(e.request))); +}); + +// Listen for message from main.js to skip waiting and activate new SW immediately +self.addEventListener("message", (event) => { + if (event.data.action === "skipWaiting") { + self.skipWaiting(); + } +}); diff --git a/javascript/dwa-starter-vanillajs-vite/tests/addToHomeScreen.spec.js b/javascript/dwa-starter-vanillajs-vite/tests/addToHomeScreen.spec.js new file mode 100644 index 00000000..eafe8193 --- /dev/null +++ b/javascript/dwa-starter-vanillajs-vite/tests/addToHomeScreen.spec.js @@ -0,0 +1,29 @@ +import { test, expect } from "@playwright/test"; + +test("Add To Home Screen prompt should appear when eligible", async ({ + page, +}) => { + // Ensure the app is loaded + await page.goto("http://localhost:5173"); + + // Check if the manifest is available (this ensures the app is PWA-ready) + const manifest = await page.evaluate(() => { + return !!document.querySelector('link[rel="manifest"]'); + }); + expect(manifest).toBeTruthy(); // Make sure the manifest is present + + // Mock the beforeinstallprompt event + await page.evaluate(() => { + window.addEventListener("beforeinstallprompt", (e) => { + e.preventDefault(); // Prevents the default install prompt from appearing + window.deferredPrompt = e; // Save the event for later use + }); + // Dispatch the event manually + const event = new Event("beforeinstallprompt"); + window.dispatchEvent(event); + }); + + // Verify the mocked event was handled + const promptHandled = await page.evaluate(() => !!window.deferredPrompt); + expect(promptHandled).toBeTruthy(); +}); diff --git a/javascript/dwa-starter-vanillajs-vite/tests/main.spec.js b/javascript/dwa-starter-vanillajs-vite/tests/main.spec.js index 97b26262..db80c4a7 100644 --- a/javascript/dwa-starter-vanillajs-vite/tests/main.spec.js +++ b/javascript/dwa-starter-vanillajs-vite/tests/main.spec.js @@ -1,26 +1,26 @@ // tests/router.spec.js -import { test, expect } from '@playwright/test'; +import { test, expect } from "@playwright/test"; -test.describe('Vanilla Router', () => { - // Before all tests, start a local server if necessary +test.describe("Vanilla Router", () => { + // Before all tests, start a local server if necessary - test('should navigate to Home', async ({ page }) => { - await page.goto('/'); - expect(await page.textContent('h1')).toBe('Home'); - }); + test("should navigate to Home", async ({ page }) => { + await page.goto("http://localhost:5173"); + expect(await page.textContent("h1")).toBe("Home"); + }); - test('should navigate to About', async ({ page }) => { - await page.goto('/about'); - expect(await page.textContent('h1')).toBe('DWA Starter Vanilla'); - }); + test("should navigate to About", async ({ page }) => { + await page.goto("/about"); + expect(await page.textContent("h1")).toBe("DWA Starter Vanilla"); + }); - test('should navigate to Settings', async ({ page }) => { - await page.goto('/settings'); - expect(await page.textContent('h1')).toBe('Settings'); - }); + test("should navigate to Settings", async ({ page }) => { + await page.goto("/settings"); + expect(await page.textContent("h1")).toBe("Settings"); + }); - test('should show Not Found for undefined routes', async ({ page }) => { - await page.goto('/undefined-route'); - expect(await page.textContent('h1')).toBe('404 - Page Not Found'); - }); + test("should show Not Found for undefined routes", async ({ page }) => { + await page.goto("/undefined-route"); + expect(await page.textContent("h1")).toBe("404 - Page Not Found"); + }); }); diff --git a/javascript/dwa-starter-vanillajs-vite/tests/offline.spec.js b/javascript/dwa-starter-vanillajs-vite/tests/offline.spec.js new file mode 100644 index 00000000..63c9bdab --- /dev/null +++ b/javascript/dwa-starter-vanillajs-vite/tests/offline.spec.js @@ -0,0 +1,18 @@ +// // tests/offline.spec.js +import { test, expect } from "@playwright/test"; + +test("App should load and function offline", async ({ page, context }) => { + // Load the app online to cache assets + await page.goto("http://localhost:5173"); + await expect(page.locator("body")).toBeVisible(); + + // Enable offline mode + await context.setOffline(true); + + // Confirm that offline content is accessible + const pageContent = await page.evaluate(() => document.body.innerText); + expect(pageContent).toContain("Home"); // Check content that’s expected offline + + // Disable offline mode to reset conditions + await context.setOffline(false); +}); diff --git a/javascript/dwa-starter-vanillajs-vite/tests/sw.spec.js b/javascript/dwa-starter-vanillajs-vite/tests/sw.spec.js new file mode 100644 index 00000000..cc4910fe --- /dev/null +++ b/javascript/dwa-starter-vanillajs-vite/tests/sw.spec.js @@ -0,0 +1,22 @@ +// tests/sw.spec.js + +import { test, expect } from "@playwright/test"; + +test("Service worker should be registered and ready on page load", async ({ + page, +}) => { + // Go to the app's base URL + await page.goto("http://localhost:5173"); + + // Wait for the service worker to register and become active + const swRegisteredAndActive = await page.evaluate(() => { + return new Promise((resolve) => { + navigator.serviceWorker.ready.then((registration) => { + resolve(!!registration.active); + }); + }); + }); + + // Assert that the service worker is both registered and active + expect(swRegisteredAndActive).toBeTruthy(); +}); From dfcacc3a417d44bb38607894e79b5f448d18caea Mon Sep 17 00:00:00 2001 From: Ankit Verma Date: Wed, 30 Oct 2024 20:31:47 +0530 Subject: [PATCH 2/2] :hammer:[refractor][made changes.] --- .../dwa-starter-vanillajs-vite/index.html | 9 + javascript/dwa-starter-vanillajs-vite/main.js | 199 ++++++++++++------ .../dwa-starter-vanillajs-vite/manifest.json | 25 +++ .../dwa-starter-vanillajs-vite/package.json | 6 +- .../playwright.config.js | 42 ++-- .../public/apple-touch-icon-180x180.png | Bin 0 -> 2833 bytes .../public/favicon.ico | Bin 0 -> 1564 bytes .../public/favicon.svg | 130 ++++++++++++ .../public/maskable-icon-512x512.png | Bin 0 -> 11375 bytes .../public/pwa-192x192.png | Bin 0 -> 4298 bytes .../public/pwa-512x512.png | Bin 0 -> 16976 bytes .../public/pwa-64x64.png | Bin 0 -> 1575 bytes javascript/dwa-starter-vanillajs-vite/sw.js | 53 +++++ .../tests/addToHomeScreen.spec.js | 29 +++ .../tests/main.spec.js | 74 ++----- .../tests/offline.spec.js | 18 ++ .../tests/sw.spec.js | 22 ++ 17 files changed, 458 insertions(+), 149 deletions(-) create mode 100644 javascript/dwa-starter-vanillajs-vite/manifest.json create mode 100644 javascript/dwa-starter-vanillajs-vite/public/apple-touch-icon-180x180.png create mode 100644 javascript/dwa-starter-vanillajs-vite/public/favicon.ico create mode 100644 javascript/dwa-starter-vanillajs-vite/public/favicon.svg create mode 100644 javascript/dwa-starter-vanillajs-vite/public/maskable-icon-512x512.png create mode 100644 javascript/dwa-starter-vanillajs-vite/public/pwa-192x192.png create mode 100644 javascript/dwa-starter-vanillajs-vite/public/pwa-512x512.png create mode 100644 javascript/dwa-starter-vanillajs-vite/public/pwa-64x64.png create mode 100644 javascript/dwa-starter-vanillajs-vite/sw.js create mode 100644 javascript/dwa-starter-vanillajs-vite/tests/addToHomeScreen.spec.js create mode 100644 javascript/dwa-starter-vanillajs-vite/tests/offline.spec.js create mode 100644 javascript/dwa-starter-vanillajs-vite/tests/sw.spec.js diff --git a/javascript/dwa-starter-vanillajs-vite/index.html b/javascript/dwa-starter-vanillajs-vite/index.html index ba1ea68f..312cec62 100644 --- a/javascript/dwa-starter-vanillajs-vite/index.html +++ b/javascript/dwa-starter-vanillajs-vite/index.html @@ -4,7 +4,15 @@ DWA Starter + + + + + +
diff --git a/javascript/dwa-starter-vanillajs-vite/main.js b/javascript/dwa-starter-vanillajs-vite/main.js index 16c6f756..2f0f1188 100644 --- a/javascript/dwa-starter-vanillajs-vite/main.js +++ b/javascript/dwa-starter-vanillajs-vite/main.js @@ -1,101 +1,164 @@ // Function to create and render the toggle button function createThemeToggleButton() { - console.log('Creating theme toggle button'); - const nav = document.querySelector('nav'); - const button = document.createElement('button'); - button.id = 'theme-toggle'; - button.textContent = 'Toggle Theme'; - button.setAttribute('aria-label', 'Toggle Dark Mode'); - button.classList.add('theme-toggle-btn'); - nav.appendChild(button); - button.addEventListener('click', toggleTheme); - console.log('Theme toggle button created and added to nav'); + console.log("Creating theme toggle button"); + const nav = document.querySelector("nav"); + const button = document.createElement("button"); + button.id = "theme-toggle"; + button.textContent = "Toggle Theme"; + button.setAttribute("aria-label", "Toggle Dark Mode"); + button.classList.add("theme-toggle-btn"); + nav.appendChild(button); + button.addEventListener("click", toggleTheme); + console.log("Theme toggle button created and added to nav"); } function toggleTheme() { - console.log('Toggle theme function called'); - const body = document.body; - const isDarkMode = body.classList.contains('dark-mode'); - console.log('Current mode is dark:', isDarkMode); - - if (isDarkMode) { - body.classList.remove('dark-mode'); - body.classList.add('light-mode'); - console.log('Switched to light mode:', body.classList); // Log class list - } else { - body.classList.remove('light-mode'); - body.classList.add('dark-mode'); - console.log('Switched to dark mode:', body.classList); // Log class list - } - localStorage.setItem('theme', isDarkMode ? 'light' : 'dark'); -} + console.log("Toggle theme function called"); + const body = document.body; + const isDarkMode = body.classList.contains("dark-mode"); + console.log("Current mode is dark:", isDarkMode); + if (isDarkMode) { + body.classList.remove("dark-mode"); + body.classList.add("light-mode"); + console.log("Switched to light mode:", body.classList); // Log class list + } else { + body.classList.remove("light-mode"); + body.classList.add("dark-mode"); + console.log("Switched to dark mode:", body.classList); // Log class list + } + localStorage.setItem("theme", isDarkMode ? "light" : "dark"); +} // Apply stored theme preference or system preference on load function applyStoredTheme() { - console.log('Applying stored theme'); - const storedTheme = localStorage.getItem('theme'); - const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)'); - const body = document.body; - - console.log('Stored theme:', storedTheme); - console.log('System prefers dark scheme:', prefersDarkScheme.matches); - - if (storedTheme === 'dark' || (storedTheme === null && prefersDarkScheme.matches)) { - body.classList.add('dark-mode'); - console.log('Applied dark mode'); - } else { - body.classList.add('light-mode'); - console.log('Applied light mode'); - } + console.log("Applying stored theme"); + const storedTheme = localStorage.getItem("theme"); + const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)"); + const body = document.body; + + console.log("Stored theme:", storedTheme); + console.log("System prefers dark scheme:", prefersDarkScheme.matches); + + if ( + storedTheme === "dark" || + (storedTheme === null && prefersDarkScheme.matches) + ) { + body.classList.add("dark-mode"); + console.log("Applied dark mode"); + } else { + body.classList.add("light-mode"); + console.log("Applied light mode"); + } } // Initial setup on DOM content loaded -document.addEventListener('DOMContentLoaded', () => { - console.log('DOM content loaded'); - applyStoredTheme(); // Apply the stored theme or system preference - createThemeToggleButton(); // Create the theme toggle button and attach to nav - // Initial routing setup (if using navigation in your app) - router(); - console.log('Initial setup completed'); +document.addEventListener("DOMContentLoaded", () => { + console.log("DOM content loaded"); + applyStoredTheme(); // Apply the stored theme or system preference + createThemeToggleButton(); // Create the theme toggle button and attach to nav + // Initial routing setup (if using navigation in your app) + router(); + console.log("Initial setup completed"); }); // Import your components for routing (if necessary) -import { Home, About, Settings, NotFound } from './components.js'; +import { Home, About, Settings, NotFound } from "./components.js"; // Define routes and their corresponding components (if necessary) const routes = { - '/': Home, - '/about': About, - '/settings': Settings, + "/": Home, + "/about": About, + "/settings": Settings, }; // Function to handle navigation (if necessary) function navigateTo(url) { - console.log('Navigating to:', url); - history.pushState(null, null, url); - router(); + console.log("Navigating to:", url); + history.pushState(null, null, url); + router(); } // Router function to render components based on the current URL function router() { - console.log('Router function called'); - const path = window.location.pathname; - console.log('Current path:', path); - const route = routes[path] || NotFound; - route(); + console.log("Router function called"); + const path = window.location.pathname; + console.log("Current path:", path); + const route = routes[path] || NotFound; + route(); } // Event delegation for link clicks (if necessary) -document.addEventListener('click', (e) => { - if (e.target.matches('[data-link]')) { - console.log('Link clicked:', e.target.href); - e.preventDefault(); - navigateTo(e.target.href); - } +document.addEventListener("click", (e) => { + if (e.target.matches("[data-link]")) { + console.log("Link clicked:", e.target.href); + e.preventDefault(); + navigateTo(e.target.href); + } }); // Listen to popstate event (back/forward navigation) (if necessary) -window.addEventListener('popstate', router); +window.addEventListener("popstate", router); + +// Initial call to router to render the correct component on page load +document.addEventListener("DOMContentLoaded", router); + +if ("serviceWorker" in navigator) { + window.addEventListener("load", () => { + navigator.serviceWorker + .register("sw.js") + .then((reg) => { + console.log("Service Worker: Registered"); + + // Check if a new SW is waiting to activate + reg.onupdatefound = () => { + const newWorker = reg.installing; + newWorker.onstatechange = () => { + if ( + newWorker.state === "installed" && + navigator.serviceWorker.controller + ) { + // Notify user about new version availability + if ( + confirm( + "A new version of the app is available. Would you like to update?" + ) + ) { + newWorker.postMessage({ action: "skipWaiting" }); + } + } + }; + }; + }) + .catch((err) => console.log(`Service Worker Error: ${err}`)); + + // Listen for `controllerchange` to reload the page when the new SW takes control + navigator.serviceWorker.addEventListener("controllerchange", () => { + window.location.reload(); + }); + }); +} + +let deferredPrompt; + +window.addEventListener("beforeinstallprompt", (e) => { + e.preventDefault(); + deferredPrompt = e; + + // Show custom install button or UI (ensure an element with id="install-button" exists in your HTML) + const addToHomeScreen = document.querySelector("#install-button"); + addToHomeScreen.style.display = "block"; + + addToHomeScreen.addEventListener("click", () => { + // Show the install prompt + deferredPrompt.prompt(); + deferredPrompt.userChoice.then((choiceResult) => { + if (choiceResult.outcome === "accepted") { + console.log("User accepted the install prompt"); + } + deferredPrompt = null; + }); + }); +}); -console.log('Script loaded'); \ No newline at end of file +console.log("Script loaded"); diff --git a/javascript/dwa-starter-vanillajs-vite/manifest.json b/javascript/dwa-starter-vanillajs-vite/manifest.json new file mode 100644 index 00000000..a9fa1bfb --- /dev/null +++ b/javascript/dwa-starter-vanillajs-vite/manifest.json @@ -0,0 +1,25 @@ +{ + "name": "dwa-starter-vanillajs-vite", + "display": "standalone", + "scope": "/", + "start_url": "/index.html", + "theme_color": "#ffffff", + "background_color": "#ffffff", + "icons": [ + { + "purpose": "maskable", + "sizes": "512x512", + "src": "./public/maskable-icon-512x512.png", + "type": "image/png" + }, + { + "purpose": "any", + "sizes": "512x512", + "src": "./public/pwa-512x512.png", + "type": "image/png" + } + ], + "orientation": "any", + "dir": "auto", + "lang": "en-US" +} diff --git a/javascript/dwa-starter-vanillajs-vite/package.json b/javascript/dwa-starter-vanillajs-vite/package.json index 6d2bc431..7f36f063 100644 --- a/javascript/dwa-starter-vanillajs-vite/package.json +++ b/javascript/dwa-starter-vanillajs-vite/package.json @@ -16,9 +16,13 @@ "jsdom": "^25.0.1", "playwright": "^1.47.2", "postcss": "^8.4.47", + "serwist": "^9.0.9", "tailwindcss": "^3.4.13", "vite": "^5.4.1", "vitest": "^2.1.2" }, - "packageManager": "pnpm@9.12.2+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228" + "packageManager": "pnpm@9.12.2+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228", + "dependencies": { + "@serwist/next": "^9.0.9" + } } diff --git a/javascript/dwa-starter-vanillajs-vite/playwright.config.js b/javascript/dwa-starter-vanillajs-vite/playwright.config.js index 18188058..ab1c5fba 100644 --- a/javascript/dwa-starter-vanillajs-vite/playwright.config.js +++ b/javascript/dwa-starter-vanillajs-vite/playwright.config.js @@ -1,4 +1,4 @@ -import { defineConfig, devices } from '@playwright/test'; +import { defineConfig, devices } from "@playwright/test"; /** * Read environment variables from file. * https://github.com/motdotla/dotenv @@ -9,7 +9,7 @@ import { defineConfig, devices } from '@playwright/test'; * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ - testDir: './tests', + testDir: "./tests", /* Maximum time one test can run for. */ timeout: 30 * 1000, expect: { @@ -17,7 +17,7 @@ export default defineConfig({ * Maximum time expect() should wait for the condition to be met. * For example in `await expect(locator).toHaveText();` */ - timeout: 5000 + timeout: 5000, }, /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, @@ -26,41 +26,41 @@ export default defineConfig({ /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 1 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'html', + reporter: "html", /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ actionTimeout: 0, /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: 'http://localhost:5173', + baseURL: "http://localhost:5173", /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', + trace: "on-first-retry", /* Only on CI systems run the tests headless */ - headless: !!process.env.CI + headless: !!process.env.CI, }, /* Configure projects for major browsers */ projects: [ { - name: 'chromium', + name: "chromium", use: { - ...devices['Desktop Chrome'] - } + ...devices["Desktop Chrome"], + }, }, { - name: 'firefox', + name: "firefox", use: { - ...devices['Desktop Firefox'] - } + ...devices["Desktop Firefox"], + }, }, { - name: 'webkit', + name: "webkit", use: { - ...devices['Desktop Safari'] - } - } + ...devices["Desktop Safari"], + }, + }, /* Test against mobile viewports. */ // { @@ -101,9 +101,9 @@ export default defineConfig({ * Use the preview server on CI for more realistic testing. * Playwright will re-use the local server if there is already a dev-server running. */ - command: 'pnpm run dev', - url: 'http://localhost:5173', // Adjust this if your dev server uses a different port + command: "npm run dev", + url: "http://localhost:5173", // Adjust this if your dev server uses a different port reuseExistingServer: !process.env.CI, timeout: 120 * 1000, // 120 seconds - } -}) \ No newline at end of file + }, +}); diff --git a/javascript/dwa-starter-vanillajs-vite/public/apple-touch-icon-180x180.png b/javascript/dwa-starter-vanillajs-vite/public/apple-touch-icon-180x180.png new file mode 100644 index 0000000000000000000000000000000000000000..9d7789fd5837767dc0ee6607392f717857c80529 GIT binary patch literal 2833 zcmV+s3-0uZP)DoJ_sFz2w&asivyAYsJvH|5;gC%jN%VXUmwFn5~Dv|LTgH zg!bOGUjOp8o5atsr~b^1{=%e<|M}jGQ{Po`xUzHod&&QCbaJHC|A&cr?!ZAzma0E~ zsCKWuVxzRsj(>@;|Bjp6!d(4tio&Cajcz1P-2eap32;bRa{vGX=l}o%=mE8RQfmMJ z3Cc-CK~#9!?V1Z$+DaFOBfS7p5wu=F1*(G(xu`{`g7pTr)wcit@0_{Mp2-CLKFNfx zHE*m3=_==0kMG{W#31nT@$vET@$vET@$vET@$vET@$s?e`rEgEjQ8T=80X?2<30XI zpf%p3~VRZEWKr_;fcY=E( z4tI5Rb%ka4Cg?AE4i1QP^h#)97FxzRw)2v#2x_z_=mX5mVwHaJBCXjDio1y;kVP^p zZ!-O$BXjJXgB_f^2Mzr~qqXzWTti-kEH!5`nX3g1B4-w+88gl2&(C5=FXqU7_g)=G zXIED>62ZKw6$5L|WY8Noo37xJEEQiI5<8mmHcCewfGp1$J~Xk#V^ z%li8IC|)rOe>~7M>($6m&u`p#Of{&+j)a!HpVtYp2`yk@F<3Oso0?|k`R$^q>H{De zdRCfoW*V;gWMmYpnbjGKUch-A$*o~)Gba|%z^yQCfOm}v)CQ2Ivxs*e4?y#QQRa0~ zj`elfThU;9e%I_1D7sO&TF6@_q%)#V_YYipI03l|!3APF=>( z^LX>(LDtt>dEzsPp zLeJw!7URY~u@Bv|nUU^!p`y9!=yI0Gz_f{I zVP*M%MGIhxykOCI7I$JMP+(60WGtt|B?lG_G!yLcqJJvC`)s^Hg2-Ftt%*^FSXO?J z40O*0v}ouv%hnKmO(}=4az(Yf&^7Zk*Vm~D`+A3sGxZ+qU4}a*-{ORyubhZ1za-&jk(kh63j!{ zoWOlr4hTJ;mL=3Qmy#4sRdZ_1^Zx$em9&~@j$BGsG@iw1GibWD;zqMZj49qCbdrWXD_cC*YTeh+(uW_JXoXxF2Z`qyEN6*bo6N#CX<=rR!a!0;Y4&0Tn6jk886@cPK8!4A$ZkLgwx5e&8g1Ai7rDx807I*m*zUgNZH)=G(wgo+HTS zEtHWB_Y-{(Le0)ZOMvp8&3g-Gj^( zr=s!NiEASo{Etziv z=edf%@%m)avV)4=mdurod+1Ir_Qq?dwTq#pC&Em*L!dcj(PZsO=0b$I6z(1J^dR#%W#*t`Sk|t1VOpa3kc;NbRg^Y# zFcg|I5#}PZyvIZfL)sbr8^h7yA#avH!-O06=$z&|mz;8pJK%<4`dcD64(8#VC zp8!KCS|Qh$LNs1`R?Rq4G+?efUU%rLp6lm5l6$y_+6nR3w*xpIE~_mYPFqIffT z=w>dO(=Og$9kUweS(YgfUB@5d`D~Wro_tLQI+tso5Y>7$esHvVAevM|JfHnZU-14k zE$CeCYtYdrupos3(e-NmyL`UIU$2!KG^QSFTSK)Vl~e!YTX89- z1emiwcs1a@lViw+*fn%3r@qADkFSG-3^BUyS)Rf*TF`oHMI^ z2gZ*-_+F)pT=4Y~#qYBWnjOYo}Tj?KqdpziXm@2F8+4cvUxJ z-gmHeP}O6FDo-Zo82ZK-L#-dD&Y@*HC=ilL)oJ@jqfw2Fq4shu*U;>H+oD8R^AgLQqvoZV{zl2;uU)tLd=|@X{dj~Uh-|0sk z?k{IH`oYGqbqdl>d{xIo8>MdjY1sO48GT9l{v)wf9S?1^8g&}BexP})|K2@x6T*>q zdmQ>aGKNO(lU~(xptV`VH9#D?9~naf6-~utNKL5_LnUYb~^=)|BO52%7RGDPHV~+b#Md5$H&LV$H&LV$H&LV j$H&LV$H&LVXIb(eQB_jpur00000NkvXXu0mjfQSq?P literal 0 HcmV?d00001 diff --git a/javascript/dwa-starter-vanillajs-vite/public/favicon.ico b/javascript/dwa-starter-vanillajs-vite/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..07f419ee47e8d9ae78bc11ec2ee7d0f758939c95 GIT binary patch literal 1564 zcmV+%2IKhv0096205C8B0096900ssC02TlM0EtjeM-2)Z3IG5A4M|8uQUCw|FaQ7m zFbD7L_t(|oaLBrNL^(d$9)q- z1VJy#MFdeVgfXKOT5zAcz|myfdZDyj8ak@ASvS{~8DUv=-9YdrBV^4x8gz$Vm8qp{ zV}odAksve_VbN`*17R41urTI5Pkhfk&+&Jj^PF>@`^Vhq#TWHlz0c?Sdw##~^IS_J z2j3~VlU1@Ai>4Bn?&1rLWqe^z6JM>tl(Tw1&h3g$?}erW!DT{UH7HYsJ}o*DacXwYkcrK+vmCs!a|J{c(PkgbDHwf6yk1~ICw;Egs z;L!0m4Sw?F)j^j5ynzf(RX?__rlG80?CleL3dZ~(U7Fo$YwGN$e*?C&!{E@-53-WM z1v~^+c$_BPOs4o(`|40SuHmu$u6;0YBK8 z$CX-}t6YMK8{<12&y%fb7d#{fhvzwfl%eom;4OVwjSLNVLTc&fM{UiYe%Aqha-YE= zBveiZ8DdojUfTeH^i#4m?Se=CdtEg=4Irv?;NSa9GN1`+>ZeB>LiJ_%Qw;{kVV2ib z0cz_Gp1_B@*`t|`^qWS_{NarFMXaK?xdBF<< z$Z~weK_m_&8PrR|&1naGvew|EJNbt?Y+42&?1Bt0E?}zbfN4MjJ{>>cfR{)bk<1|ZxBgFbX15@lFfsD6@wLprfp zumQv>?k0Zsc5{F&P_)v@z+(=0?9Sxgv;!UrI<$&n0Kzu=eds`I{MdPd4>a8{69(V& z(YtMl>JJfk-PkOO0SLQ5KkBJ2VIm#@Obwv=6#h*0%@y7MeiY3Bwp;$dp@N6Z79!QB z@Z(kaSHBp`r_ z@EFkD?~n2Fu7s(P#IttwY30kU*CCj&*6ay|LZ$zS0SG&Sfu`^)G$(8SXG5+iCjlJGTCaeUCqVlv#W|DLzK0&O~>e8J6G~lrls^N`f*NYMZ z%R2Fz_Yl+e!4N`-RSFGQ`ZJQ}xwerRd3Yo1tywCqQN57{?DnC + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/javascript/dwa-starter-vanillajs-vite/public/maskable-icon-512x512.png b/javascript/dwa-starter-vanillajs-vite/public/maskable-icon-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..f9b949c2291c2a9e7b74db5492cf8df89cbae21a GIT binary patch literal 11375 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 literal 0 HcmV?d00001 diff --git a/javascript/dwa-starter-vanillajs-vite/public/pwa-512x512.png b/javascript/dwa-starter-vanillajs-vite/public/pwa-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..aeff825645e27cd16ee725e0411834009dc14e83 GIT binary patch literal 16976 zcmaI8c|27A7e9XQEXF>PELlb&NoA{SF{6!A*?LEb(Oae7DrDd0UL@L3DlM2P6-6PG zvdl=K5K5V>V~NQ+7>rr&{rY@=kKdoa-#i}kxOZOXo^#LZdCu$H*Lj`SovW^g9TjBP z$^rnOu-|EqI{;u-PBDNqcI8n2T)%1M5bJvI$linJLLO2Pt0Ue+6-Q&Cg~uoPTa&ZT zN2S@@+uPaMc^9K7$KCSEy_Lq57P>cbHvmDq&0ics&>zNVtNzUp1pTOiHj>cytCC}p zbGc}xEpjOn{Wl*y_6ChhLD3Rv7uJf9J?OAk^PR*OX?0$~)$nolp1Ayq{cjm7Y8ZvN zANBxl{RVE-P6BT?N` zJ~FXG9~3Xh$>&UMz__rvuyuXd-yVH2_8J-yBJDEh-X}g%5Y&kYtiu#x7;^}Il z3~a8Jhy@VOk!wncYdNzYYgHGcjdiOpxLlWX*eBtlj!u$Y(uXaa;Qad9#9D!B|EI>l zDX)ZLj>(o&Z~#lEA#M=+Gm8TdZ`x_jvp;$Z;aA$REqZc$IsPY!AgYJ2dE?duq$f)9 zKh{1Gk+)7>cif1Xss5D2=qb%@6(Q9pv1)h4?61w9$0#|#1t{mUmiK9;UNJz4q&#SZzXER z3qxN#q1K}s`mEM}(Q_Cy|7c5KH5nYI>)n^Ww4&LoyGwK_p=?<3{l>NF)eL=8*_Adw zbpP>pYbR~Yig%v~sg+0mdN%=ex zWzp~`oB{f7eVa3onb_~vslkRGK0!RLJnDeNWc6#Tt%Cs@cEEp8f#tMW0X^bo;~jLp z@#Xa;f#QUwdS2H=FZ6vIa<2NVwEgd0Qe4v|I;YXt8Zj%zOAJ?q(sj=D4-gWuVNSsD zZZza1dQS1e**(yQy?p^WY~o(OuEqRc$G@d2{yjw@Cu;>?NnT&Fd;aGleM1p_Tc5=% z$@mkEjfxPgM0Ojf%RuXfznD)(yY=2wa+DZWXS>o@fE>|HM}t zcUzr;uUoP5PwyQ&&Qfc0#YLRAbIcjo(!`CO{Sb9lt#U@b9i0t%Ln71oL2U5#D!#g8 z)(LdU8Ct7oI?1e6{Ju@QdPmYLG+~m9f0xx}Z_+xcCp)jcUQvS)bwaRZVkwk+S7B`> zE1mf5Vv9n9+M#i&xnbFGiGl@XX6U5LRE3ZDu3E3t;YyXC9^A&e&Nm#D;*vm`uij+B zXGi6;Bvf;Kk{pA)K?6F7Tr~^9BqR816r;)Q;;~Bjb7`t}n>`XnV@ zPb(13Hc5M4XVM-pOtqlI36D|?zg|*=DQQAx-*4i@@taL#Auetz zv#!l1ns$CP`do(Lx>i1@#PjE37c5vZqR$@z$Stv08u*IhJw$3Qc<4A8FBY5~!gy!M zy@jP^Exq14Ns+a=&OX(p$5^Fd1np+vA5G zob$AXcWx3mZ#a8Xo_5^!-6gd)^RHRPRo_!oY7_aM{id(C%pDSVXo;_PK0%#Zz{O{T zPXXJK+U`MXX7pA8gI)Hn84k?kaMV2+LS|tW+fKRn^FtGtIYi?z0$S+!`esNnW~wv&ZIH^PTiWx)9!#^Mv|)bhEjs<+g@61(S`nr4PCXvm@n= za@@qOl66E4?`xDBlC6+AC;!B9z;#4@6uc{O`85-!mHLy^ELlTL<>qCZ7BPvter)ro zZ+?&?a%{lGtX+P%C?nb}#ktc@ycsi_v5RW$aBV;9`_d~F04Aff(F0Cc4e5@or~yA% zd@M`e>1?{=_7741z5{!v%rRf*9X3T_F(FF$ZxXi zWv_EhSC;}Vx?YwXPALAD{yE1V4l4~-q^%L?O9Dw&OiiD>d1kUU<)MVUc|Wkno(B&d z6S6w=&DGz?>z<7XK3;!*AnpEJMWH0>JmrEpApR$PS8*Bgx)Z#i`4kZ1kDxC&II|Oy zb$CAuOo21Fb4jGcIwQACtpXx2Y4TT6!G^fip0d#x(^m1zIXzyF2BnH}^l^Iq03A#f zzNo!fAoXg&5u zW3LI(RvuBj6L$@Bs$F3r=#fZ$&c%Yl{G7Rt=EM3R@5dvu|A2u&yw^Hf1i)z zqo{pz1m8qK-`1r9;s_L-2-R_z^EYT75|hoJ$@{1t6g^B-^lux7f!mJ<2rtC;r+Aj$ zuFK~}Jq7dfa4%=9se*2?_Q&Fs^c$P~$gtUu&SWFnsRohs2DuBzbR>JkQ(?TB&4WRc z@tZ%5(x(wON!AWSz!-o2!B$gm;e|i@fS-~KaECiDsd3a)S$1bRy>5H(`>?i;J8!dd zhiQ6P*I6dd3AK`APoP$7dZ0sV7~X`rI${}9PaM7qE@W=G3n?Mv-bhOmhN>~Iw}E?% zb8J@pV5#$3}(?@PIe@#{hD;|C5sz_~6u%CqX3 zn^{yMj^@W}&T$a?OVM?HOdg+?WIH1>Y<99xr_rzR>&-ufHmFFO$A#xeV1?u~M)1+}eUT zZda~io-PMn&EV6>quYPmKE{lvT!&I=-Z+*k>)v@}{WpSerd|hONc>&lI}%Xb{3EOX zepslZI5*7zxo|Z;?5(F((`3*XSMYsu##h8>&lDEhVRUVRoi{+<=AsT^kayuyzJ_0* zGoUMWvFGjg-1hCqq~4jgKW-?g(lm6}DAL%L=+DXYG_;gh9wG04b^}U`Ah39t$FoTz zY!MwDxtezoSeEqZQ4m8245;CSO0IBdNPbm(sCdO*A_j zs!-UZSG0d8$-N4I?y?VWm}im+Sl=412cnXSLki?HSY^xf?kki_%BdZr%-?8W7I4H! zT84FBoRmZ&T@nstd?o!v7x~O>gJc_^>}GNvZE{L=$_99~9QiuOL~YWKpMN+$VTkFB z*%-$8#YRpo(a61@>DI#4dDJy13<8L=&5(xN#9E&{@3&w#xAUPfby2CXZHLgm0lEW7 znY`-0=MGyhqro3w*X0YAnuSPD!AS8>XnBbBPsGLefs94NA^P~OEhn5wMh}*sm<+w3 zZbE+Ce~cV;rtAX6b;NDUYS-YKooGh|y+v|GXd>emsxDWrouIIK`( zGz9eUkkA*DE?@1{3 z&HGF`#}A6275ycv3TyuwNb8#5_s@9RFP?jZv^UT%EaWBXyaqO}!=G22mWdD8;Wq7O zN@)w6HTx&QOVhpW+A za{|YOxssC22)71`ne6f(sxPN`O$^0sIE*~bBd67&X9AC)zrN7diV}DOenj@E95w#7 zQA1U->%H!7q&J!T-%R9SH=3Y9KCQ{pUPW;LQ0p%0IGS8)@XCSI}sCN()dhFSmi2y>NUpS9_>`?L4=` z+v_Ogff|!}+_v9Bqk8gm8jz;qca2QUe2e@Rk_sR%N$Ko>GWOt0nquSZHew}duT;sT z#j0Y^qpt6iiT1%wYc18PH`3G= zGwC6lCneMZ!sU&?g4n*d#pPCH1#s^<;{EGiz0~o`Pnid z1}+Eh%nc4~2eq6Xj)>wbi$%Z9FOZub5JTrf%TCO7Krz2=L_eye-;gKNs*9s7{gjZe(yk~#XB&mHe0}Tcq=vL4(|_3SQR*Iy1oFwle`K|2nv-h4g&{! zA2}4C?2e=QP<)15@Nd>LKZmw~KB zp8X3n7u++N*y*1O1SQalYVV-I={_R8kEqkKy6B^#7-LmE=X^sVz!)&L;+M4mN60&U z-u~&*^>hjQC91bLk&Q85;=H}}QFHg@{q2vSEbsJZwAA?Y`dUHc`#|!)nV|eE)tnOd zqV2qR@IB&x1o-un{6S!_8vcrT;5wSq^T|R_=czn4W*6|M8813XHdtI;RmTr{!}P)F zpeIs+!!{+qN=Z&4@8|sCc-BEoAn#cef3sa}cUW;pR~`9^V7;U6cNg@2hfAzgciqkS zKY*DL;@>&HP99CQw_Cp{!0YRgabuMQw=cb{P;>T}?1KrZ&Pd*p>9hE$B42rENk6-U2T7y%n@l}UjVOtl8 zaGq$leWoNentT62MmYO4a(lZMz}!g|Q^-0Pj1_ z)g7>0=sT_$$9^4uY^#qvV8Qwj45XjyyMJzAJ>fAPt=!Hz*QqIQ`a`~5Z@jHvd|hQh zjeH^-*oHq}IXch~Kh}8rJgsSt^aoK!hOV2wD*H9BTs^#_zMmn|h5olkdVQCk?{i51Y{%uD ztX7zu-{3bHI&PA zz}~@eGM8@h(w`KrV%@^Dh-h|O#UtP1f0tPPrdj|~J%={j)<1i9=I?~YX<)go@>7vo zY%-*h$tKqgNZgdv@aI3d2v6-Gvyx2|rMwD3(@)d{=#9?L$cC3^s&;E0{gz4V-;)}G zxY-kFA4q{LOYkjHD|@F%TRYae_ir`V(O zG2vpDXAA|zKuwZsOpOu*no}Ot#NGorO@{+w4S%=sEj6)sB7(Q0d0xQ@!=X{}gpEhw zaHP!>y;nmmLj5{T9$5k2KU>esn-*qGY`0@4>Ug`1Akv5956v-GVXW>ZzOK^Ya#QXC zfuW+vLq}M`6H@m(7B{aRy#pRho+;#cv9~YYmAk{V_WBN~%-g#Tk}GAz={CW`m2;4P zjt)cW?{@B?{MiS-LH>noT=XU_Z20i+^H+l^}cBY&JdU8gTd-L-dVk#_KvL zQ=kTQnd7x84Gwlzoi6ZQhVO7cAO3d!N)stS_&_0g`CSb=dOTeYO~hPzHw;MOOCo8h zU9?xfD@eyA#S7b_cAWeqxuMxQel(3L`ljB^?e5na-9WKrvuiQX}67gJSL-Seg!HJrmXi1_7?=o`b~>7 zUdQ1ck*q*UU)vAJOd;1njipR!4}W{De;On8yUa9p*NiK$jUTcQ>2IL>1Q;FGDe|n{ zn*6=(Gir_JZ{WjyxPU&_CE-EpX%+=aSw9npYuoj@RZ1 z;3X3(ruC<&geaSu!BV;sKS4kyM&$zQ2Z4>5NYHISR@UnhX|aAB-CnbB(_3=Pna{*d z0P?@-xBetE=-JLQ0jmJJ`TD1*V8a^S&G`5w`?^C-~#d4KaIKCMzr-=Q<)kb z-Ii|?s94GjgwgDOise7BC6B0by4k{nY-af<^mW|fxO)~G!f<*YXVwk&jKD1wGdJIm zolr|>;H64fuJG88@AMYvUZAb`nOvvw-`;WB$F8|87R*cl23#4dr7GRT#|i&d5AuV$Kxw?!^h#{eV5lN*cb0ghi<=X0Wm~|OqMEAxk=%Ml z3R(X0AF>DLD6cV+0_3~9j!6`t$?G49FUhf^`4@xl?+=)&z8xiZmG)okS_dN3batLz zjC5qh>cV-7{0U@^&n)kPHX`e=?M-ykL7zs;;~}!fSo!P}#6L|OIHcz``h&`BZ0IH`T=Z3S+fdl^$rQP9b(fiTujQ2pp z=h~ytGr3ckqUTR$T>H%2wwklbONL#r^PR*V$w_t2FB!^HV6Z(uXtwx0sxC?*!=zO#9rxSsX=;5iu_yIXg@Q*sTquUiwq4iGCtnQ)yrQCH{Lj zZ7d@|!_Ve3drYt!?{}3Jp}<*`VK9Kk#v1h$rnWpIp}1BXHcgcAd;j(@8hK*QMB1+_q{UkU-kn=V5{HiG zgW{sL`*sUza`vXxngsRl=`qh+siMcleQUR)rt_<%xJ3-Q?1i|ioT~(i9YAx(QJ$lh z2BCBuu+eXe&r(g;B<;;ObBh$uhw%&*w8%Q}p|nPhLmsn&W>Hkp|-Gm73r3?wySFfHAh*tG!2~Uunt1M7D`5 zNTCbNW}yIF@Dm_Zd^3NZU{m>eS+l^Xt}4+tNpJkQgpG z0oHhF(!%gK5}HY30k$o`+s)}$N-txSuwFJxm!|@%KV%uP^npe58uB%ayE(a_^o^68~%&e1WWR3hnwm!^|oPf*7nGWcY%|} zt}MlQ<{3bJz8f!J7x1R0?6JSp;*GDiE}ZS)p3*R0{S$Qh4lw7Q(X)J_`x=^KjW+(I zUxIUQHRoI06J8%UIHAfv?-F#TE9x-DkIys^W{yvA{@72YtOc#h$kW0{dE`tmX012x z>r>MsfW~zDHjBc&{rYJSigABzpUToZVu@W1>yR+>6qZH zl1muQMH!Bl?8kn(<7}H7a~IvJPQINvml!H1)F@s$p6F`~r)pr1UtSj4#hd3Q0i4+}5FUtJ~}byAi4LSzcUINdb@$8h+yFnAMdAG_a>8?aA< z{3rtZ9#b2oDyuu^E1~S-{i$uG^=tl;>>JA>)Ru>B3az=Z^ZVk|SoDpZV(aVc^Q1~H zLwhleV-q>H6zT}7{Z8z76gp*S#lB?c(Vp4WhexVE(iF$8zIpin?gcRN0~#gvvW!cK zbx9#7x-`I%YlNXf z;+gW9<~BHN$VDe*#a-Idg{^;?p9$u#6M8;=8tuJLpI}>-ePqQpncnpLv|yBal}hK767BS2eFSL%NF zz^5d3TSzpq!%)%8^N5+LCGEmE)%K&m65tHF0@HC{$V7DS>`il6Q+&+CR_o1<&vv|P z(RZ<?!t95_3L>A>0ABf*pfn@?(8+ub_kvZ9C} z&$oOq(H^u{^oM>8xLw!Woae?;l$`WLyKEn=z9Y*Mv>ImwtQBJqABYESJ^pU-d$#efy7guGY9}8bAF*?oA0mIRxW*bTJfdW zX>uaq?}i6?3)qrId7cx_mCNdjY4u$kJOfQh-6gWMfkdX))A7JG=%Gw*T%qYjrDf<$A^Xx2} zZIXDceqGxK;;xZO2&_c<9;rn~?tE5pdNOoOc6xIX*$~_uwyM&qB5})c(t{_EF}7v@ zYx?jI>FKriN^_z2SA`LEBk1DGVyfL0;wWIKUFrW?{Lho1EiK4PURPVMf~uY7gx<(@ z{^zpBU^IKjoKm&v&)s2Tm_^~O=*hU35~u(m-2|?=2M73yrHOIxV<;IQOlYyK*!hQ=9$%(WS?S=WTC>C&nT7+X&NG&Ne>D6-;ywCd`NyxX6osG9TXi4RgJI_IxT! z_|F_+En^RKOXvP``?Gz+JH8#+)#J2yLfmHIDZmaAXQ6F)uX~AMgV4>xaYfqW)M09T zsD=a63HVz#InrW;Z8;=}uD%&`AC%GwK-Hz9oG?w{3@>p{Cs_uO73C-_&s}}b}$=iluK?fYMLaS2Yquh4;l zrTi0|1-Ds9W4e6EdnWrYouRO-16e$!9(c)26o=YoB-Cu>E>EUqCs178*oR$<{*6uT zYe{F35rfimvuH#_ICF{+SxfY7Cq2YKPW##!1>Us5>V zQNr>eB(B#@7Sr7otPG8{)T090)m{cER?z2C5(58pHAz0xk=?ee=Iy}FCZW~;}|D&2k{&aCDscS zzAJi#7a0jZXkfmSl;iHV-HcLGt~oK}&`KQgt=S>1TldcX7A^z8^W+7d&lvH1$2{s$ z(5OqC)C!$_@GSSyE?mCTZ;du1IPO}X!$z>FgVZEBfZs^~Rh}_WE-@nh#51zT(tbt1 z#Y+$F2Mp5NR`vKRZ#*asy#|WDqL~W0STq|mnYR)&t)AEJn@JB()cMgktfKQPS~^-@ z9Cla^ya(L>P&^c$ffKq60ntWWM=*6MG8aSH0EZoRj0*h<+~MYjZWtY;9zG<+@njw| zgx9djlqlQR@HHe;s&9W2rO`RIS|)0(kh)!TX*rMRUz+j!!TRyPOk8*a zQ57~{JV{6LzlrH9)xIgNDcvwO349*fzxw%3(CYvskCttu901>T41D{&c)F`rHAWC< z1FR4F3Os$7^*A?13GNq`Z9_Nl^YXdi7Zu$b$cex7tw_%k^0)1}k7G~#Iux=!s6=uE zr*kj4x8KAVH5Sm*fwX%c9HFC9P6^W%K7Q*eS=l9aqay1UqjtM#UzI8UekGUj3dfoG ze?ggNoLyST@5Ol4NuFVa5-UO4ep0TyXelE$dlr{*{}Jid8Fb7YW~da|Ku?7!9`u|O zi+^oNs=6~KIDR_S{NS($_QEIZTbRBUtGfr_JvTWsWovHa$2%{ehjB12aC{2#5Nvq{ zJ&=NNjJ|B6uJ$F}SQ1955Hcl19l!uK?Ua@60ApBwCB0P8=s@yRW}QX$Z>P_8o2Z>C z9}eUrtEStWfxSjex#BlwWFHi`PBswA{U!`qpTkIIR3zD_q z+$-R4NAWh@|0Z{QSzHftG|`dK^tXedHWVlzdydZ*pL`vc@djFjge*K6+f(f@xf_!~ zM7S70$jVe+G4*$(?c&J=Flur2e`II55?;bCOl5t|Eh2*-bPn;CRo`ih>@_-j7VZ03 zAxQbj+`If)HtrAL;nr=bu#yzDmr~1?lNOnqCdjX_*Su%<7MRX- zH|3Ce#|f>7%OSu~)|3mq3-(!1DtTxHiy!_h9&ghFa>X~loBVH~buD|Q`kVN# z2lL)y&`-Sm5NTA)C~0$eqdxO|#!^LPyg+XSE73hb|k-YiuGmm}pWm)Dl8;aFoza)j3f0wONB zGvV7KU-{q6lI`(+Vl2kW5j)*M(w>ZMSZzN1)i7e-;tq_#vm==ALkGO1OV%*HBJb5c z9ZJ*zYQ|`NX zT{LqUKJ-VsaBfV1z0gg%fou~RVENf*#ow2GnflBQ2WDe5 z+#@RKq&+5_8mBnV2DM03zjaXMnWHXd+~sz9DD;l7A3OlZtA43jNewYzrL#lj(iW#C`+A~wJ!+8GvAze6hBWycoP)r;C#r%c7KfTh)f0yhqG@^dL&fg?El|>kL<$~ z+G!IYk35OLhE0v=!S`J`-!fykzRX7m~3Y(r4WzF*r>Zu!&69;sPnJ3x-DH%BEO#0 zcxx%)@Hf|(`FS)&e<%Z!*D_pnHTQJogX~QheIUfcJ zM5N_%I1!@~?)NoU9IApEZ4t@KHjV06S!}71#C>}cKl>6#E4E|s5;r?k(0^RQNE!0GlRD2Q_r$#|fK>{FDI#`*nBcoF>@{b(jAd&zXi9(XzJ^;!D> zZ$3Rrt3`(05IBO3g%GO2HDH&_StEQ-1vzwFEep+7<8{~WB1@5Y58Uns2w1g4QU?H4 zHLp6g$GCDg%6R0sTr6gd#EgzvESUFHf=<*?X_`t8@@Ea#W+=m_mmXzMbb&x4uGQRw zhx^IN*U2~bQgBD3nUSgOhNAIw0sdB72L&IG7=$*`)*!}ru^5mY&hQs%W_pu*JE(4O znj~A`&rg*nz^OAb*dqfsYl32By^@U>E=EobG`abYZR|Pe5rhzyw5z|@xmE%|v*t~e6diPZErCs*~X*2-4;*(j4akHe* zpUh3D_9jX+MnQDnW>VbE-gbGEl5}PBRct7z_iD4>t_Ff5`ggu z3i1KfIu|mPxe8t73SJfur~U*rP68Mkzr+@7+#%%85_}=YJ!2m16{TzI0V6VdkQX+l z4T?ZQV-B?i=UYgEfn7xI3E5OPiOX^L?GW_~l!OdBnHPW#m2K;=N|;owPNr-iu!T#R zZh_X?hB9AB9t#6@f>|+Fh-X7dVy^_x!glOSAKCA_(UBHri)58DEfw61CLkjZ ztep;c3T?K5@exFf7pUl!a9{-xg)qi@;qcF8e|6ScBpJu)pbtM}1&m|MATO*{vC6iO zq#HDM`uKn=dQU#%&RW-9bS28j4=hjvQ-BI1-7|;d^QXU3_XB1E0~063SaRqB&C^Dv zKwe47Za3k!#Xtm4uP5&S`j%I$4{(G+1He7Oc#9Mk%=VPM7C3M&N05?3cEjoaqscvi zampC2S2n!^kGTVDCC9Hr5u?`~YfGi$pLA11^9O*PLTA6_cPqf%+=q#pHK}lnzbhxe z`Bi-C0^{B@;I51(_S5=F46iEFY>N9h2o%t&{G z51su4crT^oE`H00x~E##DzUDehQG@tV$QqD4s}4AmXKCeivCvGDz39KH|G^_8_X^-xER(WKgL3(o6jl~j&FGB* zM;`(0?3De;V?t-5B3~D%1ybu4Q+mO}cP#X4_Ia!z@grABnqiG+cS5Jm)BgKRa$Mv! z(&sgD@&OJf%YVf-H;q_%f7{le_vWe34Yf!~F*u4Qvj`#E?~-BfGU9GUPR|B7YRB1T z|G-k-q|Ya;Xkvo*`At_tr@xUWamx$fR1ej7D;6jIz<`_H@Ym$ckr!RjKZDFE3*QrgolTyqimPSBdDx!u7^>J zf$t}EP`RK_B4+&t{+H==J7o1P;DO~21(u{rj|{{OS0q~Is5=n1j>td6AO0Bays5k#n%hQ?EmyR zW6wnK4Ed6BS!rDRKSt^@*U5|1q=(3!UP=G48aw!Ir^t9RdI_$zEPa=!@amav4X^bD z^0ES2vpn0?)y4cVPe&r+W)~(-?Z8lOl20yX#Tki~4!yDLuOfW{`_aJjGmb9m#}7D6 ze|Kq?y03$d4Aj!RH_uOiPFT**fdQQcTb9Vw3RuK^lkt5l%_@XSPmf{$L!lk#X~)*E zWOGHMolFVYR}xe*)6)Y5)qw?O_NJ!)G1&oQE)%uvv@|Ec*a4@zFtZmJ5OgjNEOCG$ zqWUwx%R=Pvv|%gV#MZ{HM}^fPa5+k~S7doeX3+^#D>y|?{zei>#}EbNtek}Or@)Cv z(EHWdE7ZE#K{~0!JHKT`HF+_5;;8tx?o+AQ79o9gGTsF{#=$lPfplJnot zYR|!*C93baWs97YVJwp4jyz=Jw%G!H2z}cvsxZG@LD2eG^nY{!8Budbla0&uLDD)x*fcP%a9a&JH|-KP z20T@2sT4FWK+VcL@Hm)b3p|vas|$LLK0Peux}KGfv`q~xEAtL5t|+uv8vGa=GEB8v z$b{w_nJwV4k2<1%IE7tqfh)|XIHG6f@K*fl6OuA(-50mOms%OYH6+2CH^qzkxK7 ztW^(q*q&E&RBEGh-Q`$@zN;-Z`x5*NsZZm*`$r~f$(nH$tL4L~*(cThj1e+QYM`A& z$E_(Q{+47vY>A#s)XXdRj3TRWz4Lkb%Lq9vp&&xaN;NS?_PieaG=7Dw(%uP9>i8+0 zBVS{`EmlOkeHgoN?XRG3c(Dwe1)J3FSvsQVCo(Y&YJn#tFQ%zsXQTuY+v8@#qI<@*{v*X5Gu-lSlSc_lvLHUdaQ$Fur-e;wiv| z4{`0quOhCvOaTj@W{tH04PMt;+$}BO15@T1dPSKhVWK*wgz`b4KIWuZ!G~Io+}mOc zEsh*3S80kKW(>}JSkrz5D~+!Dd+6_vU(lW!&JB6jKk(&ru?yZqAC;G8~W!jainn^3^kVDSO6 zvI}@cH8aFch5`9XRrVaE1gvjgrIe(9u0m>KD4a^$EyJw?A`gH**08b86?cqPp+bS2 z!|#Vq6p})4zIll;A*27MB?B8Rim&~0ol%S9#d^h#M6a0fwM~M%{)@;cc8t`8kR(B%jF7|i^Ok5E;0(``SujN_plxeB0Hxxx>msrfB z(j2o;3YHL67<*jU6(ol*+W8+071lE?Wb2q0oLG(*@Y!QPV{GE)cQ|Vc;3?d-2^-Z3 zKz6KyHn&$6bU9PAS{&PorTNS4miK~ED0uO_71o!E)1Pvp^x(nB&Da6knzgQ9fyNlfHH%{~hrwQ42yhO$Hp=D>4!N4?G8G(hL|in^cWVOels zEz7VJedP!+|EuvQ-oy5rc;IaOXI>q?Fy>=gz7@1vVJx$uw61s)$2(^_Ey#lBP0-+U zTw;l~uOw{qDGOJsbFDd^6UyzDggD5ZQ1A%stU`|leH_lhepm++0`b+LwRp5Xc~^Iqci-ut^w)KPo*Jx~ zLz?z^*lI7uWN#ymci$nGbS+bH-&I^(`O3wA{s{Q&!!%&R&xD*nuG zR&%0vvry+fu-~TWDyaqRPd7~N?=K1)li6!Xuy4Bq&-k4AR22$8K1;jy!t4Ol#+)DA ziBXSud6mS=r4+^o-f&L}q<^~u=lu61AQYx*`-r|@!B&TFy3xP#-fb4x{RQmX&#JnW zuu=ea)L`7z;=TGIA55}lgc7)$u;sU~AMU_Q>#{_FGLR!R7}1K{qnQ5vid;5m(*oRll;Gpc5@jT4+fq_A7$J(>7lJ{wBD2IHh+R8`ad2ZN!u|IaV3FQz|Pe)1P+(+ad|ag>#LI+rN#6nTX! zJ83r(PVB<;C;g8q%sB&ZXk}4N)V=`k=-7)@vVwp{ro)P`#m_Guujxu6XdJ^hLjj%v+3Ba24E2RfAfo=oHYpwmsp?mIaAH7NBuIB zRoa~YdAk)ctY7A_W*gXN%PMhrvDodVc=r0;foZB##0)St!5Y?F32smK%CK9FI##Yy z3x-c7xwjqy(brBu?df{ndu`4M*`~YQj3g~yVa>Z4B$Q>K#W|>be|0!>r77ZX+1;78 zmD?-a>1If@+BfJ8#4A>&Vzck!4m{C$>nlwQoR`E_MQTK85Y%^Mj2Btd3t zu-Uso+5CHV+r$>1q_=zfIaZ4 z{}1D@@5w8bkV&}Fu#(+~@ke(~JzxB}Z$48F6$N?U+z~JfX=d#Wzp$Pz2T}Pk* literal 0 HcmV?d00001 diff --git a/javascript/dwa-starter-vanillajs-vite/public/pwa-64x64.png b/javascript/dwa-starter-vanillajs-vite/public/pwa-64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..287a1722de84e8a59e74d45bb297e4a5826bb736 GIT binary patch literal 1575 zcmV+?2H5$DP)qE`K!S@k&M z5}IND|JE*|SN{LM7XQg0|J^sRME#9${%N28igf;}O#W?||5~yCrc(Z7r2k;5|AB!2 z|F#WslmEIm{(Fc2RJi~DuLgFF|HgNqzKx~zx-+?+oAsh3bYahgS=-K$dEL2T?y4!8 zm&%=c-{GECqJPzamg>%@dsB&ql$TLblYoH$00264QchC^Rc1 zUtq__i^byPPqKg(Gw^xy1NihC3IduTe>0h#A24`Ubd|9+sD`pE^!)EN3sNOLZwNe3 zpAuuB?UjVgmgsdieQxZlZvLpnkh@q(&+@9e6lQz+ zner4rIZ3)CRV$afH@~)$9m3~%&#qYUEPnz9yIy5?v&k%yg>f|>^KLxhrCmM3U$CoZ zS(${-cW>SVyZp(;MK77n{tL1Q-W>q6@|B1GuZN^E37_gcJu-v41}^y#%Od=~*yl{H zGJN&6o1`)^zQ56LGzku0tzv_ZUVQ*rdCc!ieaFIzy?nKLdE1Q=nS@{JKUV~M`Re6m zy^AEWFkUF|113|#;VA!-!oW!?Q@&ij{aU|= zqtiKLWn%nP95Rd7C~u#9lfge(gij5-T?8**YGRVAhWS%z=yedoxHCEKFi9-h7(exl zfj%KH%fsZbKDnx4UYC4sB$4GiE`Hu7{Ic(ry2uPZ6OmLkgzGx*dnroH;A@^cY7;&- z!nL|)UmL1=ciwK+nsxxd>%s^Iyfe4+oqO1OHNdZ~F|Lav-Rv>SlcT?XcLl0perB{^ zC_;(B3x#XouMw_k(uhAUM3$ei1JE>|J;bzfL(SWKp+*DHG|i`lkq}k{@|0{ml}a^n z0D#Xd2LeNzFp;L3T@NqO<>QK?w6Cr;#KWU9#c>P%2I=$!Pxu0YzF*al!3}yAxKKJW zfkVQM*9^lh;UoHzPXr;3dn@TW$v{!S zAWlliEx=2glS2$bq4`;qWk3;@bzDODGz?84B}CytiT%3pj^n13DIR4IM~#RZ&q)dG zQu`S|m0m!=h-#qZ9~*O|grIfwLd0h$q70y9b2xoe{^zuW!DtkbTq z7{(2Kgc3%WC5ChX=>>%vw1K3A3v80389)PZ4y1&$j==*zg8*H1*|2kf5{AinpBS_i zSOe|}rrz>k@Q*@ENVPs_D|ie9S~m!RpQF3b9z5v*TOkw-2Hge+kl;v2y#44Xh{XLl Z`X2-%6G=v*4m { + console.log("Service Worker installed"); + + e.waitUntil( + caches + .open(cacheName) + .then((cache) => { + console.log("Service Worker: Caching files"); + cache.addAll(cacheAssets); + }) + .then(() => self.skipWaiting()) + ); +}); + +// Activation +self.addEventListener("activate", (e) => { + console.log("Service Worker activated"); + + e.waitUntil( + caches.keys().then((cacheNames) => { + return Promise.all( + cacheNames.map((cache) => { + if (cache !== cacheName) { + console.log("Service Worker: Clearing old cache"); + return caches.delete(cache); + } + }) + ); + }) + ); + + // Claim control immediately after activation + return self.clients.claim(); +}); + +// Fetch event to serve cached assets when offline +self.addEventListener("fetch", (e) => { + console.log("Service Worker: Fetching"); + e.respondWith(fetch(e.request).catch(() => caches.match(e.request))); +}); + +// Listen for message from main.js to skip waiting and activate new SW immediately +self.addEventListener("message", (event) => { + if (event.data.action === "skipWaiting") { + self.skipWaiting(); + } +}); diff --git a/javascript/dwa-starter-vanillajs-vite/tests/addToHomeScreen.spec.js b/javascript/dwa-starter-vanillajs-vite/tests/addToHomeScreen.spec.js new file mode 100644 index 00000000..eafe8193 --- /dev/null +++ b/javascript/dwa-starter-vanillajs-vite/tests/addToHomeScreen.spec.js @@ -0,0 +1,29 @@ +import { test, expect } from "@playwright/test"; + +test("Add To Home Screen prompt should appear when eligible", async ({ + page, +}) => { + // Ensure the app is loaded + await page.goto("http://localhost:5173"); + + // Check if the manifest is available (this ensures the app is PWA-ready) + const manifest = await page.evaluate(() => { + return !!document.querySelector('link[rel="manifest"]'); + }); + expect(manifest).toBeTruthy(); // Make sure the manifest is present + + // Mock the beforeinstallprompt event + await page.evaluate(() => { + window.addEventListener("beforeinstallprompt", (e) => { + e.preventDefault(); // Prevents the default install prompt from appearing + window.deferredPrompt = e; // Save the event for later use + }); + // Dispatch the event manually + const event = new Event("beforeinstallprompt"); + window.dispatchEvent(event); + }); + + // Verify the mocked event was handled + const promptHandled = await page.evaluate(() => !!window.deferredPrompt); + expect(promptHandled).toBeTruthy(); +}); diff --git a/javascript/dwa-starter-vanillajs-vite/tests/main.spec.js b/javascript/dwa-starter-vanillajs-vite/tests/main.spec.js index 13858656..35bd46ad 100644 --- a/javascript/dwa-starter-vanillajs-vite/tests/main.spec.js +++ b/javascript/dwa-starter-vanillajs-vite/tests/main.spec.js @@ -1,70 +1,26 @@ // tests/main.spec.js -import { test, expect } from '@playwright/test'; +import { test, expect } from "@playwright/test"; -test.describe('Vanilla Router with Theme Toggle', () => { - test.beforeEach(async ({ page }) => { - // Clear localStorage before each test to ensure isolation - await page.goto('/'); // Make sure you start from your app's root - await page.evaluate(() => localStorage.clear()); - }); - - test('should navigate to Home and toggle theme', async ({ page }) => { - await page.goto('/'); - - // Check the initial theme based on the system preference - const systemPrefersDark = await page.evaluate(() => window.matchMedia('(prefers-color-scheme: dark)').matches); - const appliedTheme = await page.evaluate(() => document.body.classList.contains('dark-mode')); - expect(appliedTheme).toBe(systemPrefersDark); - - // Click the theme toggle button - await page.click('#theme-toggle'); - - // Check if the theme has changed - const isDarkModeAfterToggle = await page.evaluate(() => document.body.classList.contains('dark-mode')); - expect(isDarkModeAfterToggle).toBe(!systemPrefersDark); - - // Verify localStorage has the correct theme - const storedTheme = await page.evaluate(() => localStorage.getItem('theme')); - expect(storedTheme).toBe(!systemPrefersDark ? 'dark' : 'light'); - }); +test.describe("Vanilla Router", () => { + // Before all tests, start a local server if necessary - test('should navigate to About', async ({ page }) => { - await page.goto('/about'); - expect(await page.textContent('h1')).toBe('DWA Starter Vanilla'); + test("should navigate to Home", async ({ page }) => { + await page.goto("/"); + expect(await page.textContent("h1")).toBe("Home"); }); - test('should navigate to Settings', async ({ page }) => { - await page.goto('/settings'); - expect(await page.textContent('h1')).toBe('Settings'); + test("should navigate to About", async ({ page }) => { + await page.goto("/about"); + expect(await page.textContent("h1")).toBe("DWA Starter Vanilla"); }); - test('should show Not Found for undefined routes', async ({ page }) => { - await page.goto('/undefined-route'); - expect(await page.textContent('h1')).toBe('404 - Page Not Found'); - }); - - test('should load correct theme based on localStorage', async ({ page }) => { - // Set theme to dark mode - await page.evaluate(() => localStorage.setItem('theme', 'dark')); - await page.goto('/'); - - const isDarkMode = await page.evaluate(() => document.body.classList.contains('dark-mode')); - expect(isDarkMode).toBe(true); - - // Set theme to light mode - await page.evaluate(() => localStorage.setItem('theme', 'light')); - await page.goto('/'); - - const isLightMode = await page.evaluate(() => document.body.classList.contains('light-mode')); - expect(isLightMode).toBe(true); + test("should navigate to Settings", async ({ page }) => { + await page.goto("/settings"); + expect(await page.textContent("h1")).toBe("Settings"); }); - test('should respect system theme preference if no stored theme', async ({ page }) => { - await page.goto('/'); // Clear any localStorage state if needed - await page.evaluate(() => localStorage.removeItem('theme')); - - const systemPrefersDark = await page.evaluate(() => window.matchMedia('(prefers-color-scheme: dark)').matches); - const isDarkMode = await page.evaluate(() => document.body.classList.contains('dark-mode')); - expect(isDarkMode).toBe(systemPrefersDark); + test("should show Not Found for undefined routes", async ({ page }) => { + await page.goto("/undefined-route"); + expect(await page.textContent("h1")).toBe("404 - Page Not Found"); }); }); diff --git a/javascript/dwa-starter-vanillajs-vite/tests/offline.spec.js b/javascript/dwa-starter-vanillajs-vite/tests/offline.spec.js new file mode 100644 index 00000000..63c9bdab --- /dev/null +++ b/javascript/dwa-starter-vanillajs-vite/tests/offline.spec.js @@ -0,0 +1,18 @@ +// // tests/offline.spec.js +import { test, expect } from "@playwright/test"; + +test("App should load and function offline", async ({ page, context }) => { + // Load the app online to cache assets + await page.goto("http://localhost:5173"); + await expect(page.locator("body")).toBeVisible(); + + // Enable offline mode + await context.setOffline(true); + + // Confirm that offline content is accessible + const pageContent = await page.evaluate(() => document.body.innerText); + expect(pageContent).toContain("Home"); // Check content that’s expected offline + + // Disable offline mode to reset conditions + await context.setOffline(false); +}); diff --git a/javascript/dwa-starter-vanillajs-vite/tests/sw.spec.js b/javascript/dwa-starter-vanillajs-vite/tests/sw.spec.js new file mode 100644 index 00000000..cc4910fe --- /dev/null +++ b/javascript/dwa-starter-vanillajs-vite/tests/sw.spec.js @@ -0,0 +1,22 @@ +// tests/sw.spec.js + +import { test, expect } from "@playwright/test"; + +test("Service worker should be registered and ready on page load", async ({ + page, +}) => { + // Go to the app's base URL + await page.goto("http://localhost:5173"); + + // Wait for the service worker to register and become active + const swRegisteredAndActive = await page.evaluate(() => { + return new Promise((resolve) => { + navigator.serviceWorker.ready.then((registration) => { + resolve(!!registration.active); + }); + }); + }); + + // Assert that the service worker is both registered and active + expect(swRegisteredAndActive).toBeTruthy(); +});