diff --git a/bun.lock b/bun.lock index 5b24c44..43d8695 100644 --- a/bun.lock +++ b/bun.lock @@ -46,7 +46,7 @@ }, }, "packages": { - "@antfu/eslint-config": ["@antfu/eslint-config@8.0.0", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@clack/prompts": "^1.2.0", "@e18e/eslint-plugin": "^0.3.0", "@eslint-community/eslint-plugin-eslint-comments": "^4.7.1", "@eslint/markdown": "^8.0.1", "@stylistic/eslint-plugin": "^5.10.0", "@typescript-eslint/eslint-plugin": "^8.58.0", "@typescript-eslint/parser": "^8.58.0", "@vitest/eslint-plugin": "^1.6.14", "ansis": "^4.2.0", "cac": "^7.0.0", "eslint-config-flat-gitignore": "^2.3.0", "eslint-flat-config-utils": "^3.1.0", "eslint-merge-processors": "^2.0.0", "eslint-plugin-antfu": "^3.2.2", "eslint-plugin-command": "^3.5.2", "eslint-plugin-import-lite": "^0.6.0", "eslint-plugin-jsdoc": "^62.8.1", "eslint-plugin-jsonc": "^3.1.2", "eslint-plugin-n": "^17.24.0", "eslint-plugin-no-only-tests": "^3.3.0", "eslint-plugin-perfectionist": "^5.7.0", "eslint-plugin-pnpm": "^1.6.0", "eslint-plugin-regexp": "^3.1.0", "eslint-plugin-toml": "^1.3.1", "eslint-plugin-unicorn": "^64.0.0", "eslint-plugin-unused-imports": "^4.4.1", "eslint-plugin-vue": "^10.8.0", "eslint-plugin-yml": "^3.3.1", "eslint-processor-vue-blocks": "^2.0.0", "globals": "^17.4.0", "local-pkg": "^1.1.2", "parse-gitignore": "^2.0.0", "toml-eslint-parser": "^1.0.3", "vue-eslint-parser": "^10.4.0", "yaml-eslint-parser": "^2.0.0" }, "peerDependencies": { "@angular-eslint/eslint-plugin": "^21.1.0", "@angular-eslint/eslint-plugin-template": "^21.1.0", "@angular-eslint/template-parser": "^21.1.0", "@eslint-react/eslint-plugin": "^3.0.0", "@next/eslint-plugin-next": ">=15.0.0", "@prettier/plugin-xml": "^3.4.1", "@unocss/eslint-plugin": ">=0.50.0", "astro-eslint-parser": "^1.0.2", "eslint": "^9.10.0 || ^10.0.0", "eslint-plugin-astro": "^1.2.0", "eslint-plugin-format": ">=0.1.0", "eslint-plugin-jsx-a11y": ">=6.10.2", "eslint-plugin-react-refresh": "^0.5.0", "eslint-plugin-solid": "^0.14.3", "eslint-plugin-svelte": ">=2.35.1", "eslint-plugin-vuejs-accessibility": "^2.4.1", "prettier-plugin-astro": "^0.14.0", "prettier-plugin-slidev": "^1.0.5", "svelte-eslint-parser": ">=0.37.0" }, "optionalPeers": ["@angular-eslint/eslint-plugin", "@angular-eslint/eslint-plugin-template", "@angular-eslint/template-parser", "@eslint-react/eslint-plugin", "@next/eslint-plugin-next", "@prettier/plugin-xml", "@unocss/eslint-plugin", "astro-eslint-parser", "eslint-plugin-astro", "eslint-plugin-format", "eslint-plugin-jsx-a11y", "eslint-plugin-react-refresh", "eslint-plugin-solid", "eslint-plugin-svelte", "eslint-plugin-vuejs-accessibility", "prettier-plugin-astro", "prettier-plugin-slidev", "svelte-eslint-parser"], "bin": { "eslint-config": "bin/index.mjs" } }, "sha512-IKiCfsa1vRgj8srB2azqiN3nOAcVyP/TZ5Ibiz0TDW9NoQPizTvkmRTSi1vo4ax0SL9TH/8uJLK6uCfd6bQzLA=="], + "@antfu/eslint-config": ["@antfu/eslint-config@8.2.0", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@clack/prompts": "^1.2.0", "@e18e/eslint-plugin": "^0.3.0", "@eslint-community/eslint-plugin-eslint-comments": "^4.7.1", "@eslint/markdown": "^8.0.1", "@stylistic/eslint-plugin": "^5.10.0", "@typescript-eslint/eslint-plugin": "^8.58.1", "@typescript-eslint/parser": "^8.58.1", "@vitest/eslint-plugin": "^1.6.15", "ansis": "^4.2.0", "cac": "^7.0.0", "eslint-config-flat-gitignore": "^2.3.0", "eslint-flat-config-utils": "^3.1.0", "eslint-merge-processors": "^2.0.0", "eslint-plugin-antfu": "^3.2.2", "eslint-plugin-command": "^3.5.2", "eslint-plugin-import-lite": "^0.6.0", "eslint-plugin-jsdoc": "^62.9.0", "eslint-plugin-jsonc": "^3.1.2", "eslint-plugin-n": "^17.24.0", "eslint-plugin-no-only-tests": "^3.3.0", "eslint-plugin-perfectionist": "^5.8.0", "eslint-plugin-pnpm": "^1.6.0", "eslint-plugin-regexp": "^3.1.0", "eslint-plugin-toml": "^1.3.1", "eslint-plugin-unicorn": "^64.0.0", "eslint-plugin-unused-imports": "^4.4.1", "eslint-plugin-vue": "^10.8.0", "eslint-plugin-yml": "^3.3.1", "eslint-processor-vue-blocks": "^2.0.0", "globals": "^17.5.0", "local-pkg": "^1.1.2", "parse-gitignore": "^2.0.0", "toml-eslint-parser": "^1.0.3", "vue-eslint-parser": "^10.4.0", "yaml-eslint-parser": "^2.0.0" }, "peerDependencies": { "@angular-eslint/eslint-plugin": "^21.1.0", "@angular-eslint/eslint-plugin-template": "^21.1.0", "@angular-eslint/template-parser": "^21.1.0", "@eslint-react/eslint-plugin": "^3.0.0", "@next/eslint-plugin-next": ">=15.0.0", "@prettier/plugin-xml": "^3.4.1", "@unocss/eslint-plugin": ">=0.50.0", "astro-eslint-parser": "^1.0.2", "eslint": "^9.10.0 || ^10.0.0", "eslint-plugin-astro": "^1.2.0", "eslint-plugin-format": ">=0.1.0", "eslint-plugin-jsx-a11y": ">=6.10.2", "eslint-plugin-react-refresh": "^0.5.0", "eslint-plugin-solid": "^0.14.3", "eslint-plugin-svelte": ">=2.35.1", "eslint-plugin-vuejs-accessibility": "^2.4.1", "prettier-plugin-astro": "^0.14.0", "prettier-plugin-slidev": "^1.0.5", "svelte-eslint-parser": ">=0.37.0" }, "optionalPeers": ["@angular-eslint/eslint-plugin", "@angular-eslint/eslint-plugin-template", "@angular-eslint/template-parser", "@eslint-react/eslint-plugin", "@next/eslint-plugin-next", "@prettier/plugin-xml", "@unocss/eslint-plugin", "astro-eslint-parser", "eslint-plugin-astro", "eslint-plugin-format", "eslint-plugin-jsx-a11y", "eslint-plugin-react-refresh", "eslint-plugin-solid", "eslint-plugin-svelte", "eslint-plugin-vuejs-accessibility", "prettier-plugin-astro", "prettier-plugin-slidev", "svelte-eslint-parser"], "bin": { "eslint-config": "bin/index.mjs" } }, "sha512-spfwYXMNrlkl69riTSBnbC0C2K8EVfVMOK3ceP2EpAAioyfprIW1gTwyLRtd9jZSFeNdX4mFNAIG+o0sOneOfA=="], "@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="], @@ -94,11 +94,11 @@ "@e18e/eslint-plugin": ["@e18e/eslint-plugin@0.3.0", "", { "dependencies": { "eslint-plugin-depend": "^1.5.0" }, "peerDependencies": { "eslint": "^9.0.0 || ^10.0.0", "oxlint": "^1.55.0" }, "optionalPeers": ["eslint", "oxlint"] }, "sha512-hHgfpxsrZ2UYHcicA+tGZnmk19uJTaye9VH79O+XS8R4ona2Hx3xjhXghclNW58uXMk3xXlbYEOMr8thsoBmWg=="], - "@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" } }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="], + "@emnapi/core": ["@emnapi/core@1.9.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA=="], - "@emnapi/runtime": ["@emnapi/runtime@1.9.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA=="], + "@emnapi/runtime": ["@emnapi/runtime@1.9.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw=="], - "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="], + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="], "@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.84.0", "", { "dependencies": { "@types/estree": "^1.0.8", "@typescript-eslint/types": "^8.54.0", "comment-parser": "1.4.5", "esquery": "^1.7.0", "jsdoc-type-pratt-parser": "~7.1.1" } }, "sha512-0xew1CxOam0gV5OMjh2KjFQZsKL2bByX1+q4j3E73MpYIdyUxcZb/xQct9ccUb+ve5KGUYbCUxyPnYB7RbuP+w=="], @@ -164,17 +164,17 @@ "@eslint/compat": ["@eslint/compat@2.0.4", "", { "dependencies": { "@eslint/core": "^1.2.0" }, "peerDependencies": { "eslint": "^8.40 || 9 || 10" }, "optionalPeers": ["eslint"] }, "sha512-o598tCGstJv9Kk4XapwP+oDij9HD9Qr3V37ABzTfdzVvbFciV+sfg9zSW6olj6G/IXj7p89SwSzPnZ+JUEPIPg=="], - "@eslint/config-array": ["@eslint/config-array@0.23.4", "", { "dependencies": { "@eslint/object-schema": "^3.0.4", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-lf19F24LSMfF8weXvW5QEtnLqW70u7kgit5e9PSx0MsHAFclGd1T9ynvWEMDT1w5J4Qt54tomGeAhdoAku1Xow=="], + "@eslint/config-array": ["@eslint/config-array@0.23.5", "", { "dependencies": { "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA=="], - "@eslint/config-helpers": ["@eslint/config-helpers@0.5.4", "", { "dependencies": { "@eslint/core": "^1.2.0" } }, "sha512-jJhqiY3wPMlWWO3370M86CPJ7pt8GmEwSLglMfQhjXal07RCvhmU0as4IuUEW5SJeunfItiEetHmSxCCe9lDBg=="], + "@eslint/config-helpers": ["@eslint/config-helpers@0.5.5", "", { "dependencies": { "@eslint/core": "^1.2.1" } }, "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w=="], - "@eslint/core": ["@eslint/core@1.2.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-8FTGbNzTvmSlc4cZBaShkC6YvFMG0riksYWRFKXztqVdXaQbcZLXlFbSpC05s70sGEsXAw0qwhx69JiW7hQS7A=="], + "@eslint/core": ["@eslint/core@1.2.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ=="], "@eslint/markdown": ["@eslint/markdown@8.0.1", "", { "dependencies": { "@eslint/core": "^1.1.1", "@eslint/plugin-kit": "^0.6.1", "github-slugger": "^2.0.0", "mdast-util-from-markdown": "^2.0.2", "mdast-util-frontmatter": "^2.0.1", "mdast-util-gfm": "^3.1.0", "mdast-util-math": "^3.0.0", "micromark-extension-frontmatter": "^2.0.0", "micromark-extension-gfm": "^3.0.0", "micromark-extension-math": "^3.1.0", "micromark-util-normalize-identifier": "^2.0.1" } }, "sha512-WWKmld/EyNdEB8GMq7JMPX1SDWgyJAM1uhtCi5ySrqYQM4HQjmg11EX/q3ZpnpRXHfdccFtli3NBvvGaYjWyQw=="], - "@eslint/object-schema": ["@eslint/object-schema@3.0.4", "", {}, "sha512-55lO/7+Yp0ISKRP0PsPtNTeNGapXaO085aELZmWCVc5SH3jfrqpuU6YgOdIxMS99ZHkQN1cXKE+cdIqwww9ptw=="], + "@eslint/object-schema": ["@eslint/object-schema@3.0.5", "", {}, "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw=="], - "@eslint/plugin-kit": ["@eslint/plugin-kit@0.7.0", "", { "dependencies": { "@eslint/core": "^1.2.0", "levn": "^0.4.1" } }, "sha512-ejvBr8MQCbVsWNZnCwDXjUKq40MDmHalq7cJ6e9s/qzTUFIIo/afzt1Vui9T97FM/V/pN4YsFVoed5NIa96RDg=="], + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.7.1", "", { "dependencies": { "@eslint/core": "^1.2.1", "levn": "^0.4.1" } }, "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ=="], "@exodus/bytes": ["@exodus/bytes@1.15.0", "", { "peerDependencies": { "@noble/hashes": "^1.8.0 || ^2.0.0" }, "optionalPeers": ["@noble/hashes"] }, "sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ=="], @@ -352,37 +352,37 @@ "@quansync/fs": ["@quansync/fs@1.0.0", "", { "dependencies": { "quansync": "^1.0.0" } }, "sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ=="], - "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.13", "", { "os": "android", "cpu": "arm64" }, "sha512-5ZiiecKH2DXAVJTNN13gNMUcCDg4Jy8ZjbXEsPnqa248wgOVeYRX0iqXXD5Jz4bI9BFHgKsI2qmyJynstbmr+g=="], + "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.15", "", { "os": "android", "cpu": "arm64" }, "sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA=="], - "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.13", "", { "os": "darwin", "cpu": "arm64" }, "sha512-tz/v/8G77seu8zAB3A5sK3UFoOl06zcshEzhUO62sAEtrEuW/H1CcyoupOrD+NbQJytYgA4CppXPzlrmp4JZKA=="], + "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.15", "", { "os": "darwin", "cpu": "arm64" }, "sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg=="], - "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.13", "", { "os": "darwin", "cpu": "x64" }, "sha512-8DakphqOz8JrMYWTJmWA+vDJxut6LijZ8Xcdc4flOlAhU7PNVwo2MaWBF9iXjJAPo5rC/IxEFZDhJ3GC7NHvug=="], + "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.15", "", { "os": "darwin", "cpu": "x64" }, "sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw=="], - "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.13", "", { "os": "freebsd", "cpu": "x64" }, "sha512-4wBQFfjDuXYN/SVI8inBF3Aa+isq40rc6VMFbk5jcpolUBTe5cYnMsHZ51nFWsx3PVyyNN3vgoESki0Hmr/4BA=="], + "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.15", "", { "os": "freebsd", "cpu": "x64" }, "sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw=="], - "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.13", "", { "os": "linux", "cpu": "arm" }, "sha512-JW/e4yPIXLms+jmnbwwy5LA/LxVwZUWLN8xug+V200wzaVi5TEGIWQlh8o91gWYFxW609euI98OCCemmWGuPrw=="], + "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15", "", { "os": "linux", "cpu": "arm" }, "sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA=="], - "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-ZfKWpXiUymDnavepCaM6KG/uGydJ4l2nBmMxg60Ci4CbeefpqjPWpfaZM7PThOhk2dssqBAcwLc6rAyr0uTdXg=="], + "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w=="], - "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-bmRg3O6Z0gq9yodKKWCIpnlH051sEfdVwt+6m5UDffAQMUUqU0xjnQqqAUm+Gu7ofAAly9DqiQDtKu2nPDEABA=="], + "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ=="], - "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "ppc64" }, "sha512-8Wtnbw4k7pMYN9B/mOEAsQ8HOiq7AZ31Ig4M9BKn2So4xRaFEhtCSa4ZJaOutOWq50zpgR4N5+L/opnlaCx8wQ=="], + "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "ppc64" }, "sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ=="], - "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "s390x" }, "sha512-D/0Nlo8mQuxSMohNJUF2lDXWRsFDsHldfRRgD9bRgktj+EndGPj4DOV37LqDKPYS+osdyhZEH7fTakTAEcW7qg=="], + "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "s390x" }, "sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ=="], - "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "x64" }, "sha512-eRrPvat2YaVQcwwKi/JzOP6MKf1WRnOCr+VaI3cTWz3ZoLcP/654z90lVCJ4dAuMEpPdke0n+qyAqXDZdIC4rA=="], + "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "x64" }, "sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA=="], - "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.13", "", { "os": "linux", "cpu": "x64" }, "sha512-PsdONiFRp8hR8KgVjTWjZ9s7uA3uueWL0t74/cKHfM4dR5zXYv4AjB8BvA+QDToqxAFg4ZkcVEqeu5F7inoz5w=="], + "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.15", "", { "os": "linux", "cpu": "x64" }, "sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw=="], - "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.13", "", { "os": "none", "cpu": "arm64" }, "sha512-hCNXgC5dI3TVOLrPT++PKFNZ+1EtS0mLQwfXXXSUD/+rGlB65gZDwN/IDuxLpQP4x8RYYHqGomlUXzpO8aVI2w=="], + "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.15", "", { "os": "none", "cpu": "arm64" }, "sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg=="], - "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.13", "", { "dependencies": { "@emnapi/core": "1.9.1", "@emnapi/runtime": "1.9.1", "@napi-rs/wasm-runtime": "^1.1.2" }, "cpu": "none" }, "sha512-viLS5C5et8NFtLWw9Sw3M/w4vvnVkbWkO7wSNh3C+7G1+uCkGpr6PcjNDSFcNtmXY/4trjPBqUfcOL+P3sWy/g=="], + "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.15", "", { "dependencies": { "@emnapi/core": "1.9.2", "@emnapi/runtime": "1.9.2", "@napi-rs/wasm-runtime": "^1.1.3" }, "cpu": "none" }, "sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q=="], - "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.13", "", { "os": "win32", "cpu": "arm64" }, "sha512-Fqa3Tlt1xL4wzmAYxGNFV36Hb+VfPc9PYU+E25DAnswXv3ODDu/yyWjQDbXMo5AGWkQVjLgQExuVu8I/UaZhPQ=="], + "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15", "", { "os": "win32", "cpu": "arm64" }, "sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA=="], - "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.13", "", { "os": "win32", "cpu": "x64" }, "sha512-/pLI5kPkGEi44TDlnbio3St/5gUFeN51YWNAk/Gnv6mEQBOahRBh52qVFVBpmrnU01n2yysvBML9Ynu7K4kGAQ=="], + "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.15", "", { "os": "win32", "cpu": "x64" }, "sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g=="], - "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.2", "", {}, "sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw=="], + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.13", "", {}, "sha512-3ngTAv6F/Py35BsYbeeLeecvhMKdsKm4AoOETVhAA+Qc8nrA2I0kF7oa93mE9qnIurngOSpMnQ0x2nQY2FPviA=="], "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.60.1", "", { "os": "android", "cpu": "arm" }, "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA=="], @@ -462,7 +462,7 @@ "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], - "@types/node": ["@types/node@25.5.2", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg=="], + "@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="], @@ -470,97 +470,97 @@ "@types/web-bluetooth": ["@types/web-bluetooth@0.0.21", "", {}, "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA=="], - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.58.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.58.0", "@typescript-eslint/type-utils": "8.58.0", "@typescript-eslint/utils": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.58.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-RLkVSiNuUP1C2ROIWfqX+YcUfLaSnxGE/8M+Y57lopVwg9VTYYfhuz15Yf1IzCKgZj6/rIbYTmJCUSqr76r0Wg=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.58.2", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.58.2", "@typescript-eslint/type-utils": "8.58.2", "@typescript-eslint/utils": "8.58.2", "@typescript-eslint/visitor-keys": "8.58.2", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.58.2", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw=="], - "@typescript-eslint/parser": ["@typescript-eslint/parser@8.58.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.58.0", "@typescript-eslint/types": "8.58.0", "@typescript-eslint/typescript-estree": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-rLoGZIf9afaRBYsPUMtvkDWykwXwUPL60HebR4JgTI8mxfFe2cQTu3AGitANp4b9B2QlVru6WzjgB2IzJKiCSA=="], + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.58.2", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.58.2", "@typescript-eslint/types": "8.58.2", "@typescript-eslint/typescript-estree": "8.58.2", "@typescript-eslint/visitor-keys": "8.58.2", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg=="], - "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.58.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.58.0", "@typescript-eslint/types": "^8.58.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-8Q/wBPWLQP1j16NxoPNIKpDZFMaxl7yWIoqXWYeWO+Bbd2mjgvoF0dxP2jKZg5+x49rgKdf7Ck473M8PC3V9lg=="], + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.58.2", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.58.2", "@typescript-eslint/types": "^8.58.2", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg=="], "@typescript-eslint/rule-tester": ["@typescript-eslint/rule-tester@8.58.0", "", { "dependencies": { "@typescript-eslint/parser": "8.58.0", "@typescript-eslint/typescript-estree": "8.58.0", "@typescript-eslint/utils": "8.58.0", "ajv": "^6.12.6", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "4.6.2", "semver": "^7.7.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0" } }, "sha512-a/J72Cxeo5ug5sbey7+Dcna6tMBc4Z4eYwBEKM6MVuBqbxnROpLm8yn/j00lPZc75joPZJVR5oiTZxbK95zp+w=="], - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0" } }, "sha512-W1Lur1oF50FxSnNdGp3Vs6P+yBRSmZiw4IIjEeYxd8UQJwhUF0gDgDD/W/Tgmh73mxgEU3qX0Bzdl/NGuSPEpQ=="], + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.58.2", "", { "dependencies": { "@typescript-eslint/types": "8.58.2", "@typescript-eslint/visitor-keys": "8.58.2" } }, "sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q=="], - "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.58.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-doNSZEVJsWEu4htiVC+PR6NpM+pa+a4ClH9INRWOWCUzMst/VA9c4gXq92F8GUD1rwhNvRLkgjfYtFXegXQF7A=="], + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.58.2", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A=="], - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "@typescript-eslint/typescript-estree": "8.58.0", "@typescript-eslint/utils": "8.58.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-aGsCQImkDIqMyx1u4PrVlbi/krmDsQUs4zAcCV6M7yPcPev+RqVlndsJy9kJ8TLihW9TZ0kbDAzctpLn5o+lOg=="], + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.58.2", "", { "dependencies": { "@typescript-eslint/types": "8.58.2", "@typescript-eslint/typescript-estree": "8.58.2", "@typescript-eslint/utils": "8.58.2", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg=="], "@typescript-eslint/types": ["@typescript-eslint/types@8.58.0", "", {}, "sha512-O9CjxypDT89fbHxRfETNoAnHj/i6IpRK0CvbVN3qibxlLdo5p5hcLmUuCCrHMpxiWSwKyI8mCP7qRNYuOJ0Uww=="], - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.58.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.58.0", "@typescript-eslint/tsconfig-utils": "8.58.0", "@typescript-eslint/types": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-7vv5UWbHqew/dvs+D3e1RvLv1v2eeZ9txRHPnEEBUgSNLx5ghdzjHa0sgLWYVKssH+lYmV0JaWdoubo0ncGYLA=="], + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.58.2", "", { "dependencies": { "@typescript-eslint/project-service": "8.58.2", "@typescript-eslint/tsconfig-utils": "8.58.2", "@typescript-eslint/types": "8.58.2", "@typescript-eslint/visitor-keys": "8.58.2", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw=="], - "@typescript-eslint/utils": ["@typescript-eslint/utils@8.58.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.58.0", "@typescript-eslint/types": "8.58.0", "@typescript-eslint/typescript-estree": "8.58.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-RfeSqcFeHMHlAWzt4TBjWOAtoW9lnsAGiP3GbaX9uVgTYYrMbVnGONEfUCiSss+xMHFl+eHZiipmA8WkQ7FuNA=="], + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.58.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.58.2", "@typescript-eslint/types": "8.58.2", "@typescript-eslint/typescript-estree": "8.58.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA=="], - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="], + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.2", "", { "dependencies": { "@typescript-eslint/types": "8.58.2", "eslint-visitor-keys": "^5.0.0" } }, "sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA=="], "@unhead/vue": ["@unhead/vue@2.1.13", "", { "dependencies": { "hookable": "^6.0.1", "unhead": "2.1.13" }, "peerDependencies": { "vue": ">=3.5.18" } }, "sha512-HYy0shaHRnLNW9r85gppO8IiGz0ONWVV3zGdlT8CQ0tbTwixznJCIiyqV4BSV1aIF1jJIye0pd1p/k6Eab8Z/A=="], - "@unocss/cli": ["@unocss/cli@66.6.7", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "@unocss/config": "66.6.7", "@unocss/core": "66.6.7", "@unocss/preset-wind3": "66.6.7", "@unocss/preset-wind4": "66.6.7", "@unocss/transformer-directives": "66.6.7", "cac": "^6.7.14", "chokidar": "^5.0.0", "colorette": "^2.0.20", "consola": "^3.4.2", "magic-string": "^0.30.21", "pathe": "^2.0.3", "perfect-debounce": "^2.1.0", "tinyglobby": "^0.2.15", "unplugin-utils": "^0.3.1" }, "bin": { "unocss": "bin/unocss.mjs" } }, "sha512-m/yW5HMVyxfAOeyO4OyA4JB9dY+/gTsk25ucI8xVCFVDEENPEGr+vEqTDOA+vfe6pdURtyDYS7OrhikIRU1WNA=="], + "@unocss/cli": ["@unocss/cli@66.6.8", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "@unocss/config": "66.6.8", "@unocss/core": "66.6.8", "@unocss/preset-wind3": "66.6.8", "@unocss/preset-wind4": "66.6.8", "@unocss/transformer-directives": "66.6.8", "cac": "^7.0.0", "chokidar": "^5.0.0", "colorette": "^2.0.20", "consola": "^3.4.2", "magic-string": "^0.30.21", "pathe": "^2.0.3", "perfect-debounce": "^2.1.0", "tinyglobby": "^0.2.16", "unplugin-utils": "^0.3.1" }, "bin": { "unocss": "bin/unocss.mjs" } }, "sha512-dJ4AmrhCtQwEDJtpFG7AgJ4Qi4GWnNgWWlLWq4DhKBOCcvldr9k98mscdhs3MOwph25DIxU5MdLRAg/OS1JryQ=="], - "@unocss/config": ["@unocss/config@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7", "colorette": "^2.0.20", "consola": "^3.4.2", "unconfig": "^7.5.0" } }, "sha512-1uleyRLyJc6PNNc2L3hEaKL89zXwvQAtP36oFySgL47RAxZHPZ4vfqFpbwR0eEN4iSqTS24ZFr7CTRWCaEGjzQ=="], + "@unocss/config": ["@unocss/config@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8", "colorette": "^2.0.20", "consola": "^3.4.2", "unconfig": "^7.5.0" } }, "sha512-f+a8OyhD7ZoK8Pa1b3Cbx1RQc3n5x+Qht/cHg3wh/g4DNQIjBI2EqwSLfBigWhdO96zIqFAdyTlO3onmrJwUOw=="], - "@unocss/core": ["@unocss/core@66.6.7", "", {}, "sha512-Q8456iWFtdwrUNYKVOQY8ygRggjZOVtLc6Jc8KIkxig7OiNlUWOgXJTfCh4I8g6jBYzC5eHaHFDLgJOmOrxBsg=="], + "@unocss/core": ["@unocss/core@66.6.8", "", {}, "sha512-P9IlQfgms+8/nka7fBhiiWU4SPwrTNKbTdK0z1SLnttXMHHjsB2zpG+Vi1JQDpICfY9Y1/2pWtguPE+zeOVu9Q=="], - "@unocss/eslint-config": ["@unocss/eslint-config@66.6.7", "", { "dependencies": { "@unocss/eslint-plugin": "66.6.7" } }, "sha512-l33NbugpKr5twWmRbFwQcvAuD/lWAqT9Nrnguga75geeUBENOVNQialeyEFcZAmR7/eYOeILIrhM8XtFUmtf2g=="], + "@unocss/eslint-config": ["@unocss/eslint-config@66.6.8", "", { "dependencies": { "@unocss/eslint-plugin": "66.6.8" } }, "sha512-ONlFypzot0Cf3FykIVBsj1dL4hC5TGLVAcVbI6jv/KUJDzwhcf+SnVKyxzQH3ZricFG6B0PmU3kf872ZxFUmcg=="], - "@unocss/eslint-plugin": ["@unocss/eslint-plugin@66.6.7", "", { "dependencies": { "@typescript-eslint/utils": "^8.56.1", "@unocss/config": "66.6.7", "@unocss/core": "66.6.7", "@unocss/rule-utils": "66.6.7", "magic-string": "^0.30.21", "synckit": "^0.11.12" } }, "sha512-0pNFT918CUOiWSlr3ZmePL5Bb06/g/mmP8zP+/dpl2+Vc/GuW6wHVsP+qn5hT2c5FwCPRZ3CUm0HprTru2/sGA=="], + "@unocss/eslint-plugin": ["@unocss/eslint-plugin@66.6.8", "", { "dependencies": { "@typescript-eslint/utils": "^8.58.1", "@unocss/config": "66.6.8", "@unocss/core": "66.6.8", "@unocss/rule-utils": "66.6.8", "magic-string": "^0.30.21", "synckit": "^0.11.12" } }, "sha512-w51M8EwQZL7klOX+ZYS2zxxrj4AjfAtVenSCk+fXE+fSkC8aKNCpQpsV61Af/r9rIAy8GnbBL+QkcTOqkoKLrQ=="], - "@unocss/extractor-arbitrary-variants": ["@unocss/extractor-arbitrary-variants@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7" } }, "sha512-PQiBHK0yUJ0BR+3GYnTPU6va6HVSRPV+O+s1zZmt23TWbyIeucoKCNR47TDtv+Z1xuksY8krIjtDYtufdrVWKw=="], + "@unocss/extractor-arbitrary-variants": ["@unocss/extractor-arbitrary-variants@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8" } }, "sha512-cOXstpPTOLt/HYcL0OsqFkNau0e8ktZ5Q8fgnXBZjmLGmi+VzdESNlwxZyCXLuamZGnbrZ8lDsKdsGG7P1pMKQ=="], - "@unocss/inspector": ["@unocss/inspector@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7", "@unocss/rule-utils": "66.6.7", "colorette": "^2.0.20", "gzip-size": "^6.0.0", "sirv": "^3.0.2" } }, "sha512-4lA70A/wy9dfSDm7rJ5Uq5fKz+/Szm2rUcHjdbLCVNEc6vv2YXeI7aFvP5qDjTp4ClBSF2AMPnF1mtoMQOfDvA=="], + "@unocss/inspector": ["@unocss/inspector@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8", "@unocss/rule-utils": "66.6.8", "colorette": "^2.0.20", "gzip-size": "^6.0.0", "sirv": "^3.0.2" } }, "sha512-g8uRzXDdmoNRjXX/mZP7m0rWXLtOimyOW7+VFK6FNxRWBmvIGYgTLHkutF6Wyh9lLPDYx3pkkEmfgL35BDT3Sg=="], - "@unocss/preset-attributify": ["@unocss/preset-attributify@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7" } }, "sha512-thtoLQb53+Acy2QJYT6n+YhgNJ5ilhS8k9bqi+UzflbsuK4TJqOuQQjC9fRkULP5QjtNxgqN3d5Up7ms8tBPDA=="], + "@unocss/preset-attributify": ["@unocss/preset-attributify@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8" } }, "sha512-YxyRSF5rq0WbY8kCG0gpj3DSXPL89QGxZeqABmceCzPJbXJBBHEJz/pgBPmzSa2Ziulgs0AEkHzWFPfpb2uGTA=="], - "@unocss/preset-icons": ["@unocss/preset-icons@66.6.7", "", { "dependencies": { "@iconify/utils": "^3.1.0", "@unocss/core": "66.6.7", "ofetch": "^1.5.1" } }, "sha512-mGAOyI/qz1pZUV1BcOtWAMm5czdFCjhFCYcDk0KY+Jw37pKRVSQRFeh4gpHuYKmehGv36caLyVrWXpTAwRBdFQ=="], + "@unocss/preset-icons": ["@unocss/preset-icons@66.6.8", "", { "dependencies": { "@iconify/utils": "^3.1.0", "@unocss/core": "66.6.8", "ofetch": "^1.5.1" } }, "sha512-+zD5TNGZIXvVOMcvDIYaTXinffpDMERGj6Ch8WTtJluA6qHHBvRuFexoU2bY8nF1r0HZkYzNT9C+RujFSP+6TA=="], - "@unocss/preset-mini": ["@unocss/preset-mini@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7", "@unocss/extractor-arbitrary-variants": "66.6.7", "@unocss/rule-utils": "66.6.7" } }, "sha512-tf0mqiSEhPQ49WZOqjNhxlbZbNakiBLzCoxfLSzqfIGglOPYShP8mxsdp9Jv0n+Ntn0rHcBiX5KTLfax1/Bd9g=="], + "@unocss/preset-mini": ["@unocss/preset-mini@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8", "@unocss/extractor-arbitrary-variants": "66.6.8", "@unocss/rule-utils": "66.6.8" } }, "sha512-vAechrReO7LtWzFAeF54P7CintG2m65SlVlBsi1x2Ru7IdgUNJEHII0MfXUvf9r1x8vsIlhATyaqqtBVT6ps/w=="], - "@unocss/preset-tagify": ["@unocss/preset-tagify@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7" } }, "sha512-0WeQf+Dx9Ztv3aewkBKEnAfOauSjvWBlfkpsgLpXcCkyGMnCqq87UrAq3+b76TDJvQc8i2ADlvVGK7V1z0JZQg=="], + "@unocss/preset-tagify": ["@unocss/preset-tagify@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8" } }, "sha512-cG6zBYswtWTpeQe/Lb1Bh+IzU4Ck+VI8rpYvrnvSGl22rJjAsXd+buB1P0PjyDpoe924rq0bLTayZ8r6Ayyyvw=="], - "@unocss/preset-typography": ["@unocss/preset-typography@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7", "@unocss/rule-utils": "66.6.7" } }, "sha512-RA7MwPDD5N9xGrbWnguVm5tP+F4/n/9X1rJsq2nBjvvK2dbtIRJZjRFM1vBDsR0GIhtvbHMoTchZaSZed5I+Hw=="], + "@unocss/preset-typography": ["@unocss/preset-typography@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8", "@unocss/rule-utils": "66.6.8" } }, "sha512-wOApJpE0QfeOTWN5RuQts8zS6PXhTZIfjpt6cBj8dmv7+GlIQlwopxL7wcDb2wVwdCByuMvUbWl7nC3kz/iFTA=="], - "@unocss/preset-uno": ["@unocss/preset-uno@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7", "@unocss/preset-wind3": "66.6.7" } }, "sha512-imGCe6Yv2XgrJxP77gV8WZCz0xL99MsGov5rYn64lh2/tcsHF2rUIhTj/Urgxt0kwk8rLFtGbR1JuwPMNL5EDw=="], + "@unocss/preset-uno": ["@unocss/preset-uno@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8", "@unocss/preset-wind3": "66.6.8" } }, "sha512-z01Rw/rBuahRulwQRnobUFnGqyU+UenOLz72KGn4p0Yh8gBC44fPlNHsOWA0TNediHRJg33HptX4kx16HCVWDg=="], - "@unocss/preset-web-fonts": ["@unocss/preset-web-fonts@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7", "ofetch": "^1.5.1" } }, "sha512-GLjUoSL/kYt1Yw2zpzixKnxvpHgLHAg0JXiPglct4PZ9YmUzCPbvJ/vVn+0AnB8Fxr29Z8NAFSNoX625ZaRonQ=="], + "@unocss/preset-web-fonts": ["@unocss/preset-web-fonts@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8", "ofetch": "^1.5.1" } }, "sha512-AgEHO8h0AkeOT57AOE9PS7dJOa5Rfr0gIyz/FxA7vJ/FwgQL70uX+bRW8kmoH81zcjo5xBP2IX3Z6A8VAOo3Vw=="], - "@unocss/preset-wind": ["@unocss/preset-wind@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7", "@unocss/preset-wind3": "66.6.7" } }, "sha512-jxtAN96jljd+KglbhPv6Y/ujceI5rVdrLQimj4KUTPoYBPEiWadzsGKN3o8Q07hlPRg+hBlO0r4tGSUWl+/EZQ=="], + "@unocss/preset-wind": ["@unocss/preset-wind@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8", "@unocss/preset-wind3": "66.6.8" } }, "sha512-F0mdmwK/HelYOgBRMHl+Yx/VyARCQJtPlcgPBejI3E9ZWOZlKS7hvPqPrgvS63WTGMHgM3/22cGuYYFjpi/ugA=="], - "@unocss/preset-wind3": ["@unocss/preset-wind3@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7", "@unocss/preset-mini": "66.6.7", "@unocss/rule-utils": "66.6.7" } }, "sha512-PKyqeRzlIMd3Irdt6fCKMm73zgwweiXESk5edUK8dVWndvPIcZCOqrEq7yg6Pr/Q8tHdq26viYSkVY3a3t8RSg=="], + "@unocss/preset-wind3": ["@unocss/preset-wind3@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8", "@unocss/preset-mini": "66.6.8", "@unocss/rule-utils": "66.6.8" } }, "sha512-WNTeDAYCatmEFjBJ4itUmz0TElBvNFqjh5i2/ianDJO/vkd+IYUb03jEPLUppVlvMhy8bN8AunP0AtW3Xf2psA=="], - "@unocss/preset-wind4": ["@unocss/preset-wind4@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7", "@unocss/extractor-arbitrary-variants": "66.6.7", "@unocss/rule-utils": "66.6.7" } }, "sha512-9grhWeBsFzpv8iER9AFATRaxLyXMCwGQ5HzeI4XZh2ZZ9O6vC7nYfGhns4/I+F/RpFglzU1bjqMWRS/DS8OpGQ=="], + "@unocss/preset-wind4": ["@unocss/preset-wind4@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8", "@unocss/extractor-arbitrary-variants": "66.6.8", "@unocss/rule-utils": "66.6.8" } }, "sha512-CheOm7KXOsTI5t4RXgeYz95CO5p589F6jsyYp+inOCk4N0/d+DWiDHrQ+V0x0HWs3JXWlD+/Va/yXjlc3o2sIw=="], - "@unocss/reset": ["@unocss/reset@66.6.7", "", {}, "sha512-+OjpLDEaPmhTQ3Gj7EaKApNM92TM9f9gLgHNa79+66wIll9IfhKfEmJXnF9y1SE725n4PmPIQgC9k313HztMLA=="], + "@unocss/reset": ["@unocss/reset@66.6.8", "", {}, "sha512-H+YP3ltizUiPO9FzFgFhv8WGsefO7fTgT1If1/9ritPDqZlvzTqMmjelhcq8D8MGoQ1RQBUvtkZ5HJoKVY0Tgw=="], - "@unocss/rule-utils": ["@unocss/rule-utils@66.6.7", "", { "dependencies": { "@unocss/core": "^66.6.7", "magic-string": "^0.30.21" } }, "sha512-4PT/s8yKIShSqP9XPSw4EjbZopcu3wlIB9i3kbGbzQwF91H+0Yy10guK3kHDGtkmWVN6Np6VvaGIj2UcbmaivA=="], + "@unocss/rule-utils": ["@unocss/rule-utils@66.6.8", "", { "dependencies": { "@unocss/core": "^66.6.8", "magic-string": "^0.30.21" } }, "sha512-WR35L07mLP6PElD4hlUHo5KbQ48uz2HT/XCuJyAsHP+15Gv6539hPWA5SresPuva9r8rl+PeGIgMSIKf4A5Ihw=="], - "@unocss/transformer-attributify-jsx": ["@unocss/transformer-attributify-jsx@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7", "oxc-parser": "^0.115.0", "oxc-walker": "^0.7.0" } }, "sha512-r5bsnaPVe4iySLK5G5rA/QPSKmpPjYT9lixEv+KElvZcqZ+cPpkGoo+E+rnTcapu9KDMOVJItH/4Zy9m4AQ1ZQ=="], + "@unocss/transformer-attributify-jsx": ["@unocss/transformer-attributify-jsx@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8", "oxc-parser": "^0.124.0", "oxc-walker": "^0.7.0" } }, "sha512-g+7lvm+8V1MnJ21ialTxFBonCTtenn/KcZQbm0JfvQjgG+KuuSnt3BGEcXAHQZu3eBDGuJuasTHiXWwzCYIRBQ=="], - "@unocss/transformer-compile-class": ["@unocss/transformer-compile-class@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7" } }, "sha512-4uz4jCyq8VUaSPveXhelUWUNaTnetPFvEmXzmbYJ5BygAlUlipNynffUlUusDQmBBRrfZhJNB5J1Zif2Q6oUiA=="], + "@unocss/transformer-compile-class": ["@unocss/transformer-compile-class@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8" } }, "sha512-37dFuzgYo8ki033KmuvyZXugQRVH1c3+/z5kcWLPhcMR8UJscAtjgRx80S1UvWup2q6TPxPpmy/rMbqWvs3jfg=="], - "@unocss/transformer-directives": ["@unocss/transformer-directives@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7", "@unocss/rule-utils": "66.6.7", "css-tree": "^3.1.0" } }, "sha512-z3gi8/cD2P0I+c6jOPZUtsPXknHwVNlMIitSh7LhyM6W3EqbqvDcYH2gFeGhdhoYcN2r5OpTBujq34iz4IdUxA=="], + "@unocss/transformer-directives": ["@unocss/transformer-directives@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8", "@unocss/rule-utils": "66.6.8", "css-tree": "^3.2.1" } }, "sha512-9hC3mQ8eycliW/igI9le0LovTIMBKoL6crucTkr4MmWuNqICMvNxTmGj5Xh64olBPnascevFwam6xsy+J1lX4Q=="], - "@unocss/transformer-variant-group": ["@unocss/transformer-variant-group@66.6.7", "", { "dependencies": { "@unocss/core": "66.6.7" } }, "sha512-XouJuQCjYJpvR3sY4QDXnGXxtyJ4qgWFG+S9bAB01TTslhQLvNPE9o2+4gZlltnJLqxiPQWuLeJA1KdPD6ciww=="], + "@unocss/transformer-variant-group": ["@unocss/transformer-variant-group@66.6.8", "", { "dependencies": { "@unocss/core": "66.6.8" } }, "sha512-+t7gJDW3W3z3/f8zBf0DfV2UZyGyFOwG5CIsIj5ofu3VJ91mKD/5ZAH8fD3cryXCBSqslj4yv+8R+BLV07T5AA=="], - "@unocss/vite": ["@unocss/vite@66.6.7", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "@unocss/config": "66.6.7", "@unocss/core": "66.6.7", "@unocss/inspector": "66.6.7", "chokidar": "^5.0.0", "magic-string": "^0.30.21", "pathe": "^2.0.3", "tinyglobby": "^0.2.15", "unplugin-utils": "^0.3.1" }, "peerDependencies": { "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 || ^8.0.0-0" } }, "sha512-8AHrVzAecnQaPLJv3/mpyFt5j2iL3gEwkZcZ8HzjH5ttK2XON1YE9vgujN5NS/yvZwlJxCMNPxn0S410/Ek61A=="], + "@unocss/vite": ["@unocss/vite@66.6.8", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "@unocss/config": "66.6.8", "@unocss/core": "66.6.8", "@unocss/inspector": "66.6.8", "chokidar": "^5.0.0", "magic-string": "^0.30.21", "pathe": "^2.0.3", "tinyglobby": "^0.2.16", "unplugin-utils": "^0.3.1" }, "peerDependencies": { "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 || ^8.0.0-0" } }, "sha512-bXfEnEHdW7zTGLIYU16MsfKSFy3Q47Pevhrt5f9fOGzC4UI1JGkkoQSfoFpXZGliDrhoSFK4Msz9Jt43Ta4j+w=="], - "@vitejs/plugin-vue": ["@vitejs/plugin-vue@6.0.5", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-rc.2" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", "vue": "^3.2.25" } }, "sha512-bL3AxKuQySfk1iGcBsQnoRVexTPJq0Z/ixFVM8OhVJAP6ZXXXLtM7NFKWhLl30Kg7uTBqIaPXbh+nuQCuBDedg=="], + "@vitejs/plugin-vue": ["@vitejs/plugin-vue@6.0.6", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-rc.13" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", "vue": "^3.2.25" } }, "sha512-u9HHgfrq3AjXlysn0eINFnWQOJQLO9WN6VprZ8FXl7A2bYisv3Hui9Ij+7QZ41F/WYWarHjwBbXtD7dKg3uxbg=="], - "@vitest/coverage-v8": ["@vitest/coverage-v8@4.1.3", "", { "dependencies": { "@bcoe/v8-coverage": "^1.0.2", "@vitest/utils": "4.1.3", "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-reports": "^3.2.0", "magicast": "^0.5.2", "obug": "^2.1.1", "std-env": "^4.0.0-rc.1", "tinyrainbow": "^3.1.0" }, "peerDependencies": { "@vitest/browser": "4.1.3", "vitest": "4.1.3" }, "optionalPeers": ["@vitest/browser"] }, "sha512-/MBdrkA8t6hbdCWFKs09dPik774xvs4Z6L4bycdCxYNLHM8oZuRyosumQMG19LUlBsB6GeVpL1q4kFFazvyKGA=="], + "@vitest/coverage-v8": ["@vitest/coverage-v8@4.1.4", "", { "dependencies": { "@bcoe/v8-coverage": "^1.0.2", "@vitest/utils": "4.1.4", "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-reports": "^3.2.0", "magicast": "^0.5.2", "obug": "^2.1.1", "std-env": "^4.0.0-rc.1", "tinyrainbow": "^3.1.0" }, "peerDependencies": { "@vitest/browser": "4.1.4", "vitest": "4.1.4" }, "optionalPeers": ["@vitest/browser"] }, "sha512-x7FptB5oDruxNPDNY2+S8tCh0pcq7ymCe1gTHcsp733jYjrJl8V1gMUlVysuCD9Kz46Xz9t1akkv08dPcYDs1w=="], - "@vitest/eslint-plugin": ["@vitest/eslint-plugin@1.6.14", "", { "dependencies": { "@typescript-eslint/scope-manager": "^8.58.0", "@typescript-eslint/utils": "^8.58.0" }, "peerDependencies": { "@typescript-eslint/eslint-plugin": "*", "eslint": ">=8.57.0", "typescript": ">=5.0.0", "vitest": "*" }, "optionalPeers": ["@typescript-eslint/eslint-plugin", "typescript", "vitest"] }, "sha512-PXZ5ysw4eHU9h8nDtBvVcGC7Z2C/T9CFdheqSw1NNXFYqViojub0V9bgdYI67iBTOcra2mwD0EYldlY9bGPf2Q=="], + "@vitest/eslint-plugin": ["@vitest/eslint-plugin@1.6.16", "", { "dependencies": { "@typescript-eslint/scope-manager": "^8.58.0", "@typescript-eslint/utils": "^8.58.0" }, "peerDependencies": { "@typescript-eslint/eslint-plugin": "*", "eslint": ">=8.57.0", "typescript": ">=5.0.0", "vitest": "*" }, "optionalPeers": ["@typescript-eslint/eslint-plugin", "typescript", "vitest"] }, "sha512-2pBN1F1JXq6zTSaYC58CMJa7pGxXIRsLfOioeZM4cPE3pRdSh1ySTSoHPQlOTEF5WgoVzWZQxhGQ3ygT78hOVg=="], - "@vitest/expect": ["@vitest/expect@4.1.3", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.3", "@vitest/utils": "4.1.3", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-CW8Q9KMtXDGHj0vCsqui0M5KqRsu0zm0GNDW7Gd3U7nZ2RFpPKSCpeCXoT+/+5zr1TNlsoQRDEz+LzZUyq6gnQ=="], + "@vitest/expect": ["@vitest/expect@4.1.4", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.4", "@vitest/utils": "4.1.4", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-iPBpra+VDuXmBFI3FMKHSFXp3Gx5HfmSCE8X67Dn+bwephCnQCaB7qWK2ldHa+8ncN8hJU8VTMcxjPpyMkUjww=="], - "@vitest/mocker": ["@vitest/mocker@4.1.3", "", { "dependencies": { "@vitest/spy": "4.1.3", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-XN3TrycitDQSzGRnec/YWgoofkYRhouyVQj4YNsJ5r/STCUFqMrP4+oxEv3e7ZbLi4og5kIHrZwekDJgw6hcjw=="], + "@vitest/mocker": ["@vitest/mocker@4.1.4", "", { "dependencies": { "@vitest/spy": "4.1.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-R9HTZBhW6yCSGbGQnDnH3QHfJxokKN4KB+Yvk9Q1le7eQNYwiCyKxmLmurSpFy6BzJanSLuEUDrD+j97Q+ZLPg=="], - "@vitest/pretty-format": ["@vitest/pretty-format@4.1.3", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-hYqqwuMbpkkBodpRh4k4cQSOELxXky1NfMmQvOfKvV8zQHz8x8Dla+2wzElkMkBvSAJX5TRGHJAQvK0TcOafwg=="], + "@vitest/pretty-format": ["@vitest/pretty-format@4.1.4", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-ddmDHU0gjEUyEVLxtZa7xamrpIefdEETu3nZjWtHeZX4QxqJ7tRxSteHVXJOcr8jhiLoGAhkK4WJ3WqBpjx42A=="], - "@vitest/runner": ["@vitest/runner@4.1.3", "", { "dependencies": { "@vitest/utils": "4.1.3", "pathe": "^2.0.3" } }, "sha512-VwgOz5MmT0KhlUj40h02LWDpUBVpflZ/b7xZFA25F29AJzIrE+SMuwzFf0b7t4EXdwRNX61C3B6auIXQTR3ttA=="], + "@vitest/runner": ["@vitest/runner@4.1.4", "", { "dependencies": { "@vitest/utils": "4.1.4", "pathe": "^2.0.3" } }, "sha512-xTp7VZ5aXP5ZJrn15UtJUWlx6qXLnGtF6jNxHepdPHpMfz/aVPx+htHtgcAL2mDXJgKhpoo2e9/hVJsIeFbytQ=="], - "@vitest/snapshot": ["@vitest/snapshot@4.1.3", "", { "dependencies": { "@vitest/pretty-format": "4.1.3", "@vitest/utils": "4.1.3", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-9l+k/J9KG5wPJDX9BcFFzhhwNjwkRb8RsnYhaT1vPY7OufxmQFc9sZzScRCPTiETzl37mrIWVY9zxzmdVeJwDQ=="], + "@vitest/snapshot": ["@vitest/snapshot@4.1.4", "", { "dependencies": { "@vitest/pretty-format": "4.1.4", "@vitest/utils": "4.1.4", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-MCjCFgaS8aZz+m5nTcEcgk/xhWv0rEH4Yl53PPlMXOZ1/Ka2VcZU6CJ+MgYCZbcJvzGhQRjVrGQNZqkGPttIKw=="], - "@vitest/spy": ["@vitest/spy@4.1.3", "", {}, "sha512-ujj5Uwxagg4XUIfAUyRQxAg631BP6e9joRiN99mr48Bg9fRs+5mdUElhOoZ6rP5mBr8Bs3lmrREnkrQWkrsTCw=="], + "@vitest/spy": ["@vitest/spy@4.1.4", "", {}, "sha512-XxNdAsKW7C+FLydqFJLb5KhJtl3PGCMmYwFRfhvIgxJvLSXhhVI1zM8f1qD3Zg7RCjTSzDVyct6sghs9UEgBEQ=="], - "@vitest/utils": ["@vitest/utils@4.1.3", "", { "dependencies": { "@vitest/pretty-format": "4.1.3", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-Pc/Oexse/khOWsGB+w3q4yzA4te7W4gpZZAvk+fr8qXfTURZUMj5i7kuxsNK5mP/dEB6ao3jfr0rs17fHhbHdw=="], + "@vitest/utils": ["@vitest/utils@4.1.4", "", { "dependencies": { "@vitest/pretty-format": "4.1.4", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-13QMT+eysM5uVGa1rG4kegGYNp6cnQcsTc67ELFbhNLQO+vgsygtYJx2khvdt4gVQqSSpC/KT5FZZxUpP3Oatw=="], "@volar/language-core": ["@volar/language-core@2.4.23", "", { "dependencies": { "@volar/source-map": "2.4.23" } }, "sha512-hEEd5ET/oSmBC6pi1j6NaNYRWoAiDhINbT8rmwtINugR39loROSlufGdYMF9TaKGfz+ViGs1Idi3mAhnuPcoGQ=="], @@ -806,7 +806,7 @@ "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - "eslint": ["eslint@10.2.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.4", "@eslint/config-helpers": "^0.5.4", "@eslint/core": "^1.2.0", "@eslint/plugin-kit": "^0.7.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-+L0vBFYGIpSNIt/KWTpFonPrqYvgKw1eUI5Vn7mEogrQcWtWYtNQ7dNqC+px/J0idT3BAkiWrhfS7k+Tum8TUA=="], + "eslint": ["eslint@10.2.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.5.5", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-wiyGaKsDgqXvF40P8mDwiUp/KQjE1FdrIEJsM8PZ3XCiniTMXS3OHWWUe5FI5agoCnr8x4xPrTDZuxsBlNHl+Q=="], "eslint-compat-utils": ["eslint-compat-utils@0.5.1", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q=="], @@ -938,7 +938,7 @@ "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], - "globals": ["globals@17.4.0", "", {}, "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw=="], + "globals": ["globals@17.5.0", "", {}, "sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g=="], "globrex": ["globrex@0.1.2", "", {}, "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="], @@ -1014,7 +1014,7 @@ "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], - "knip": ["knip@6.3.0", "", { "dependencies": { "@nodelib/fs.walk": "^1.2.3", "fast-glob": "^3.3.3", "formatly": "^0.3.0", "get-tsconfig": "4.13.7", "jiti": "^2.6.0", "minimist": "^1.2.8", "oxc-parser": "^0.121.0", "oxc-resolver": "^11.19.1", "picocolors": "^1.1.1", "picomatch": "^4.0.1", "smol-toml": "^1.6.1", "strip-json-comments": "5.0.3", "unbash": "^2.2.0", "yaml": "^2.8.2", "zod": "^4.1.11" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-g6dVPoTw6iNm3cubC5IWxVkVsd0r5hXhTBTbAGIEQN53GdA2ZM/slMTPJ7n5l8pBebNQPHpxjmKxuR4xVQ2/hQ=="], + "knip": ["knip@6.4.1", "", { "dependencies": { "@nodelib/fs.walk": "^1.2.3", "fast-glob": "^3.3.3", "formatly": "^0.3.0", "get-tsconfig": "4.13.7", "jiti": "^2.6.0", "minimist": "^1.2.8", "oxc-parser": "^0.121.0", "oxc-resolver": "^11.19.1", "picocolors": "^1.1.1", "picomatch": "^4.0.1", "smol-toml": "^1.6.1", "strip-json-comments": "5.0.3", "unbash": "^2.2.0", "yaml": "^2.8.2", "zod": "^4.1.11" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-Ry+ywmDFSZvKp/jx7LxMgsZWRTs931alV84e60lh0Stf6kSRYqSIUTkviyyDFRcSO3yY1Kpbi83OirN+4lA2Xw=="], "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], @@ -1308,7 +1308,7 @@ "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], - "rolldown": ["rolldown@1.0.0-rc.13", "", { "dependencies": { "@oxc-project/types": "=0.123.0", "@rolldown/pluginutils": "1.0.0-rc.13" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.13", "@rolldown/binding-darwin-arm64": "1.0.0-rc.13", "@rolldown/binding-darwin-x64": "1.0.0-rc.13", "@rolldown/binding-freebsd-x64": "1.0.0-rc.13", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.13", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.13", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.13", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.13", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.13", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.13", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.13" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-bvVj8YJmf0rq4pSFmH7laLa6pYrhghv3PRzrCdRAr23g66zOKVJ4wkvFtgohtPLWmthgg8/rkaqRHrpUEh0Zbw=="], + "rolldown": ["rolldown@1.0.0-rc.15", "", { "dependencies": { "@oxc-project/types": "=0.124.0", "@rolldown/pluginutils": "1.0.0-rc.15" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.15", "@rolldown/binding-darwin-arm64": "1.0.0-rc.15", "@rolldown/binding-darwin-x64": "1.0.0-rc.15", "@rolldown/binding-freebsd-x64": "1.0.0-rc.15", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.15", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.15", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.15", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.15", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.15", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.15", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.15" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g=="], "rollup": ["rollup@4.60.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.60.1", "@rollup/rollup-android-arm64": "4.60.1", "@rollup/rollup-darwin-arm64": "4.60.1", "@rollup/rollup-darwin-x64": "4.60.1", "@rollup/rollup-freebsd-arm64": "4.60.1", "@rollup/rollup-freebsd-x64": "4.60.1", "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", "@rollup/rollup-linux-arm-musleabihf": "4.60.1", "@rollup/rollup-linux-arm64-gnu": "4.60.1", "@rollup/rollup-linux-arm64-musl": "4.60.1", "@rollup/rollup-linux-loong64-gnu": "4.60.1", "@rollup/rollup-linux-loong64-musl": "4.60.1", "@rollup/rollup-linux-ppc64-gnu": "4.60.1", "@rollup/rollup-linux-ppc64-musl": "4.60.1", "@rollup/rollup-linux-riscv64-gnu": "4.60.1", "@rollup/rollup-linux-riscv64-musl": "4.60.1", "@rollup/rollup-linux-s390x-gnu": "4.60.1", "@rollup/rollup-linux-x64-gnu": "4.60.1", "@rollup/rollup-linux-x64-musl": "4.60.1", "@rollup/rollup-openbsd-x64": "4.60.1", "@rollup/rollup-openharmony-arm64": "4.60.1", "@rollup/rollup-win32-arm64-msvc": "4.60.1", "@rollup/rollup-win32-ia32-msvc": "4.60.1", "@rollup/rollup-win32-x64-gnu": "4.60.1", "@rollup/rollup-win32-x64-msvc": "4.60.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w=="], @@ -1416,13 +1416,11 @@ "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="], - "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], "type-level-regexp": ["type-level-regexp@0.1.17", "", {}, "sha512-wTk4DH3cxwk196uGLK/E9pE45aLfeKJacKmcEgEOA/q5dnPGNxXt0cfYdFxb57L+sEpf1oJH4Dnx/pnRcku9jg=="], - "typescript": ["typescript@6.0.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="], + "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], "ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="], @@ -1434,7 +1432,7 @@ "undici": ["undici@7.24.7", "", {}, "sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ=="], - "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + "undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="], "unhead": ["unhead@2.1.13", "", { "dependencies": { "hookable": "^6.0.1" } }, "sha512-jO9M1sI6b2h/1KpIu4Jeu+ptumLmUKboRRLxys5pYHFeT+lqTzfNHbYUX9bxVDhC1FBszAGuWcUVlmvIPsah8Q=="], @@ -1448,7 +1446,7 @@ "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="], - "unocss": ["unocss@66.6.7", "", { "dependencies": { "@unocss/cli": "66.6.7", "@unocss/core": "66.6.7", "@unocss/preset-attributify": "66.6.7", "@unocss/preset-icons": "66.6.7", "@unocss/preset-mini": "66.6.7", "@unocss/preset-tagify": "66.6.7", "@unocss/preset-typography": "66.6.7", "@unocss/preset-uno": "66.6.7", "@unocss/preset-web-fonts": "66.6.7", "@unocss/preset-wind": "66.6.7", "@unocss/preset-wind3": "66.6.7", "@unocss/preset-wind4": "66.6.7", "@unocss/transformer-attributify-jsx": "66.6.7", "@unocss/transformer-compile-class": "66.6.7", "@unocss/transformer-directives": "66.6.7", "@unocss/transformer-variant-group": "66.6.7", "@unocss/vite": "66.6.7" }, "peerDependencies": { "@unocss/astro": "66.6.7", "@unocss/postcss": "66.6.7", "@unocss/webpack": "66.6.7" }, "optionalPeers": ["@unocss/astro", "@unocss/postcss", "@unocss/webpack"] }, "sha512-TdZ/JnKhrqkknrMvLl0KOwrGzFThEspFIyYiylFYJki2JkMN/5EJIr+vIZEGRX69hFTjTLi6utIpbipueqzNbw=="], + "unocss": ["unocss@66.6.8", "", { "dependencies": { "@unocss/cli": "66.6.8", "@unocss/core": "66.6.8", "@unocss/preset-attributify": "66.6.8", "@unocss/preset-icons": "66.6.8", "@unocss/preset-mini": "66.6.8", "@unocss/preset-tagify": "66.6.8", "@unocss/preset-typography": "66.6.8", "@unocss/preset-uno": "66.6.8", "@unocss/preset-web-fonts": "66.6.8", "@unocss/preset-wind": "66.6.8", "@unocss/preset-wind3": "66.6.8", "@unocss/preset-wind4": "66.6.8", "@unocss/transformer-attributify-jsx": "66.6.8", "@unocss/transformer-compile-class": "66.6.8", "@unocss/transformer-directives": "66.6.8", "@unocss/transformer-variant-group": "66.6.8", "@unocss/vite": "66.6.8" }, "peerDependencies": { "@unocss/astro": "66.6.8", "@unocss/postcss": "66.6.8", "@unocss/webpack": "66.6.8" }, "optionalPeers": ["@unocss/astro", "@unocss/postcss", "@unocss/webpack"] }, "sha512-stq9FbxedTDkoWrxnNQNnPQXOaM6L2Lobq8HzjXdR2tMc55gtfqDArqL7TESfnN7qeZsIocNYCHLNA4DXq50YQ=="], "unplugin": ["unplugin@1.16.1", "", { "dependencies": { "acorn": "^8.14.0", "webpack-virtual-modules": "^0.6.2" } }, "sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w=="], @@ -1466,9 +1464,9 @@ "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], - "vite": ["vite@8.0.7", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.13", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-P1PbweD+2/udplnThz3btF4cf6AgPky7kk23RtHUkJIU5BIxwPprhRGmOAHs6FTI7UiGbTNrgNP6jSYD6JaRnw=="], + "vite": ["vite@8.0.8", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.15", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw=="], - "vitest": ["vitest@4.1.3", "", { "dependencies": { "@vitest/expect": "4.1.3", "@vitest/mocker": "4.1.3", "@vitest/pretty-format": "4.1.3", "@vitest/runner": "4.1.3", "@vitest/snapshot": "4.1.3", "@vitest/spy": "4.1.3", "@vitest/utils": "4.1.3", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.3", "@vitest/browser-preview": "4.1.3", "@vitest/browser-webdriverio": "4.1.3", "@vitest/coverage-istanbul": "4.1.3", "@vitest/coverage-v8": "4.1.3", "@vitest/ui": "4.1.3", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-DBc4Tx0MPNsqb9isoyOq00lHftVx/KIU44QOm2q59npZyLUkENn8TMFsuzuO+4U2FUa9rgbbPt3udrP25GcjXw=="], + "vitest": ["vitest@4.1.4", "", { "dependencies": { "@vitest/expect": "4.1.4", "@vitest/mocker": "4.1.4", "@vitest/pretty-format": "4.1.4", "@vitest/runner": "4.1.4", "@vitest/snapshot": "4.1.4", "@vitest/spy": "4.1.4", "@vitest/utils": "4.1.4", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.4", "@vitest/browser-preview": "4.1.4", "@vitest/browser-webdriverio": "4.1.4", "@vitest/coverage-istanbul": "4.1.4", "@vitest/coverage-v8": "4.1.4", "@vitest/ui": "4.1.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-tFuJqTxKb8AvfyqMfnavXdzfy3h3sWZRWwfluGbkeR7n0HUev+FmNgZ8SDrRBTVrVCjgH5cA21qGbCffMNtWvg=="], "vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="], @@ -1478,7 +1476,7 @@ "vue-eslint-parser": ["vue-eslint-parser@10.4.0", "", { "dependencies": { "debug": "^4.4.0", "eslint-scope": "^8.2.0 || ^9.0.0", "eslint-visitor-keys": "^4.2.0 || ^5.0.0", "espree": "^10.3.0 || ^11.0.0", "esquery": "^1.6.0", "semver": "^7.6.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0" } }, "sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg=="], - "vue-tsc": ["vue-tsc@3.2.6", "", { "dependencies": { "@volar/typescript": "2.4.28", "@vue/language-core": "3.2.6" }, "peerDependencies": { "typescript": ">=5.0.0" }, "bin": { "vue-tsc": "bin/vue-tsc.js" } }, "sha512-gYW/kWI0XrwGzd0PKc7tVB/qpdeAkIZLNZb10/InizkQjHjnT8weZ/vBarZoj4kHKbUTZT/bAVgoOr8x4NsQ/Q=="], + "vue-tsc": ["vue-tsc@3.2.7", "", { "dependencies": { "@volar/typescript": "2.4.28", "@vue/language-core": "3.2.7" }, "peerDependencies": { "typescript": ">=5.0.0" }, "bin": { "vue-tsc": "bin/vue-tsc.js" } }, "sha512-zc1tL3HoQni1zGTGrwBVRQb7rGP5SWdu/m4rGB6JcnAC5MT5LFZIxF7Y+EJEnt4hGF23d60rXH7gRjHGb5KQQQ=="], "w3c-xmlserializer": ["w3c-xmlserializer@5.0.0", "", { "dependencies": { "xml-name-validator": "^5.0.0" } }, "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA=="], @@ -1526,6 +1524,10 @@ "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "@eslint/compat/@eslint/core": ["@eslint/core@1.2.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-8FTGbNzTvmSlc4cZBaShkC6YvFMG0riksYWRFKXztqVdXaQbcZLXlFbSpC05s70sGEsXAw0qwhx69JiW7hQS7A=="], + + "@eslint/markdown/@eslint/core": ["@eslint/core@1.2.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-8FTGbNzTvmSlc4cZBaShkC6YvFMG0riksYWRFKXztqVdXaQbcZLXlFbSpC05s70sGEsXAw0qwhx69JiW7hQS7A=="], + "@eslint/markdown/@eslint/plugin-kit": ["@eslint/plugin-kit@0.6.1", "", { "dependencies": { "@eslint/core": "^1.1.1", "levn": "^0.4.1" } }, "sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ=="], "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], @@ -1534,15 +1536,43 @@ "@quansync/fs/quansync": ["quansync@1.0.0", "", {}, "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA=="], + "@rolldown/binding-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow=="], + "@stylistic/eslint-plugin/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], "@stylistic/eslint-plugin/espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], - "@unocss/cli/cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], + "@typescript-eslint/parser/@typescript-eslint/types": ["@typescript-eslint/types@8.58.2", "", {}, "sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ=="], + + "@typescript-eslint/project-service/@typescript-eslint/types": ["@typescript-eslint/types@8.58.2", "", {}, "sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ=="], + + "@typescript-eslint/rule-tester/@typescript-eslint/parser": ["@typescript-eslint/parser@8.58.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.58.0", "@typescript-eslint/types": "8.58.0", "@typescript-eslint/typescript-estree": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-rLoGZIf9afaRBYsPUMtvkDWykwXwUPL60HebR4JgTI8mxfFe2cQTu3AGitANp4b9B2QlVru6WzjgB2IzJKiCSA=="], + + "@typescript-eslint/rule-tester/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.58.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.58.0", "@typescript-eslint/tsconfig-utils": "8.58.0", "@typescript-eslint/types": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-7vv5UWbHqew/dvs+D3e1RvLv1v2eeZ9txRHPnEEBUgSNLx5ghdzjHa0sgLWYVKssH+lYmV0JaWdoubo0ncGYLA=="], + + "@typescript-eslint/rule-tester/@typescript-eslint/utils": ["@typescript-eslint/utils@8.58.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.58.0", "@typescript-eslint/types": "8.58.0", "@typescript-eslint/typescript-estree": "8.58.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-RfeSqcFeHMHlAWzt4TBjWOAtoW9lnsAGiP3GbaX9uVgTYYrMbVnGONEfUCiSss+xMHFl+eHZiipmA8WkQ7FuNA=="], + + "@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.58.2", "", {}, "sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ=="], + + "@typescript-eslint/type-utils/@typescript-eslint/types": ["@typescript-eslint/types@8.58.2", "", {}, "sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ=="], + + "@typescript-eslint/typescript-estree/@typescript-eslint/types": ["@typescript-eslint/types@8.58.2", "", {}, "sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ=="], + + "@typescript-eslint/typescript-estree/tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="], + + "@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.58.2", "", {}, "sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ=="], + + "@typescript-eslint/visitor-keys/@typescript-eslint/types": ["@typescript-eslint/types@8.58.2", "", {}, "sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ=="], - "@unocss/transformer-attributify-jsx/oxc-parser": ["oxc-parser@0.115.0", "", { "dependencies": { "@oxc-project/types": "^0.115.0" }, "optionalDependencies": { "@oxc-parser/binding-android-arm-eabi": "0.115.0", "@oxc-parser/binding-android-arm64": "0.115.0", "@oxc-parser/binding-darwin-arm64": "0.115.0", "@oxc-parser/binding-darwin-x64": "0.115.0", "@oxc-parser/binding-freebsd-x64": "0.115.0", "@oxc-parser/binding-linux-arm-gnueabihf": "0.115.0", "@oxc-parser/binding-linux-arm-musleabihf": "0.115.0", "@oxc-parser/binding-linux-arm64-gnu": "0.115.0", "@oxc-parser/binding-linux-arm64-musl": "0.115.0", "@oxc-parser/binding-linux-ppc64-gnu": "0.115.0", "@oxc-parser/binding-linux-riscv64-gnu": "0.115.0", "@oxc-parser/binding-linux-riscv64-musl": "0.115.0", "@oxc-parser/binding-linux-s390x-gnu": "0.115.0", "@oxc-parser/binding-linux-x64-gnu": "0.115.0", "@oxc-parser/binding-linux-x64-musl": "0.115.0", "@oxc-parser/binding-openharmony-arm64": "0.115.0", "@oxc-parser/binding-wasm32-wasi": "0.115.0", "@oxc-parser/binding-win32-arm64-msvc": "0.115.0", "@oxc-parser/binding-win32-ia32-msvc": "0.115.0", "@oxc-parser/binding-win32-x64-msvc": "0.115.0" } }, "sha512-2w7Xn3CbS/zwzSY82S5WLemrRu3CT57uF7Lx8llrE/2bul6iMTcJE4Rbls7GDNbLn3ttATI68PfOz2Pt3KZ2cQ=="], + "@unocss/cli/tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="], + + "@unocss/transformer-attributify-jsx/oxc-parser": ["oxc-parser@0.124.0", "", { "dependencies": { "@oxc-project/types": "^0.124.0" }, "optionalDependencies": { "@oxc-parser/binding-android-arm-eabi": "0.124.0", "@oxc-parser/binding-android-arm64": "0.124.0", "@oxc-parser/binding-darwin-arm64": "0.124.0", "@oxc-parser/binding-darwin-x64": "0.124.0", "@oxc-parser/binding-freebsd-x64": "0.124.0", "@oxc-parser/binding-linux-arm-gnueabihf": "0.124.0", "@oxc-parser/binding-linux-arm-musleabihf": "0.124.0", "@oxc-parser/binding-linux-arm64-gnu": "0.124.0", "@oxc-parser/binding-linux-arm64-musl": "0.124.0", "@oxc-parser/binding-linux-ppc64-gnu": "0.124.0", "@oxc-parser/binding-linux-riscv64-gnu": "0.124.0", "@oxc-parser/binding-linux-riscv64-musl": "0.124.0", "@oxc-parser/binding-linux-s390x-gnu": "0.124.0", "@oxc-parser/binding-linux-x64-gnu": "0.124.0", "@oxc-parser/binding-linux-x64-musl": "0.124.0", "@oxc-parser/binding-openharmony-arm64": "0.124.0", "@oxc-parser/binding-wasm32-wasi": "0.124.0", "@oxc-parser/binding-win32-arm64-msvc": "0.124.0", "@oxc-parser/binding-win32-ia32-msvc": "0.124.0", "@oxc-parser/binding-win32-x64-msvc": "0.124.0" } }, "sha512-h07SFj/tp2U3cf3+LFX6MmOguQiM9ahwpGs0ZK5CGhgL8p4kk24etrJKsEzhXAvo7mfvoKTZooZ5MLKAPRmJ1g=="], + + "@unocss/vite/tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="], + + "@vitest/eslint-plugin/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0" } }, "sha512-W1Lur1oF50FxSnNdGp3Vs6P+yBRSmZiw4IIjEeYxd8UQJwhUF0gDgDD/W/Tgmh73mxgEU3qX0Bzdl/NGuSPEpQ=="], "@volar/typescript/@volar/language-core": ["@volar/language-core@2.4.28", "", { "dependencies": { "@volar/source-map": "2.4.28" } }, "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ=="], @@ -1608,16 +1638,28 @@ "editorconfig/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], + "eslint-flat-config-utils/@eslint/config-helpers": ["@eslint/config-helpers@0.5.4", "", { "dependencies": { "@eslint/core": "^1.2.0" } }, "sha512-jJhqiY3wPMlWWO3370M86CPJ7pt8GmEwSLglMfQhjXal07RCvhmU0as4IuUEW5SJeunfItiEetHmSxCCe9lDBg=="], + "eslint-plugin-jsdoc/@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.86.0", "", { "dependencies": { "@types/estree": "^1.0.8", "@typescript-eslint/types": "^8.58.0", "comment-parser": "1.4.6", "esquery": "^1.7.0", "jsdoc-type-pratt-parser": "~7.2.0" } }, "sha512-ukZmRQ81WiTpDWO6D/cTBM7XbrNtutHKvAVnZN/8pldAwLoJArGOvkNyxPTBGsPjsoaQBJxlH+tE2TNA/92Qgw=="], + "eslint-plugin-jsonc/@eslint/core": ["@eslint/core@1.2.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-8FTGbNzTvmSlc4cZBaShkC6YvFMG0riksYWRFKXztqVdXaQbcZLXlFbSpC05s70sGEsXAw0qwhx69JiW7hQS7A=="], + "eslint-plugin-jsonc/@eslint/plugin-kit": ["@eslint/plugin-kit@0.6.1", "", { "dependencies": { "@eslint/core": "^1.1.1", "levn": "^0.4.1" } }, "sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ=="], "eslint-plugin-n/globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="], + "eslint-plugin-perfectionist/@typescript-eslint/utils": ["@typescript-eslint/utils@8.58.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.58.0", "@typescript-eslint/types": "8.58.0", "@typescript-eslint/typescript-estree": "8.58.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-RfeSqcFeHMHlAWzt4TBjWOAtoW9lnsAGiP3GbaX9uVgTYYrMbVnGONEfUCiSss+xMHFl+eHZiipmA8WkQ7FuNA=="], + + "eslint-plugin-toml/@eslint/core": ["@eslint/core@1.2.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-8FTGbNzTvmSlc4cZBaShkC6YvFMG0riksYWRFKXztqVdXaQbcZLXlFbSpC05s70sGEsXAw0qwhx69JiW7hQS7A=="], + "eslint-plugin-toml/@eslint/plugin-kit": ["@eslint/plugin-kit@0.6.1", "", { "dependencies": { "@eslint/core": "^1.1.1", "levn": "^0.4.1" } }, "sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ=="], + "eslint-plugin-unicorn/globals": ["globals@17.4.0", "", {}, "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw=="], + "eslint-plugin-vue/xml-name-validator": ["xml-name-validator@4.0.0", "", {}, "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw=="], + "eslint-plugin-yml/@eslint/core": ["@eslint/core@1.2.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-8FTGbNzTvmSlc4cZBaShkC6YvFMG0riksYWRFKXztqVdXaQbcZLXlFbSpC05s70sGEsXAw0qwhx69JiW7hQS7A=="], + "eslint-plugin-yml/@eslint/plugin-kit": ["@eslint/plugin-kit@0.6.1", "", { "dependencies": { "@eslint/core": "^1.1.1", "levn": "^0.4.1" } }, "sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ=="], "eslint-plugin-yml/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], @@ -1644,9 +1686,9 @@ "playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], - "rolldown/@oxc-project/types": ["@oxc-project/types@0.123.0", "", {}, "sha512-YtECP/y8Mj1lSHiUWGSRzy/C6teUKlS87dEfuVKT09LgQbUsBW1rNg+MiJ4buGu3yuADV60gbIvo9/HplA56Ew=="], + "rolldown/@oxc-project/types": ["@oxc-project/types@0.124.0", "", {}, "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg=="], - "rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.13", "", {}, "sha512-3ngTAv6F/Py35BsYbeeLeecvhMKdsKm4AoOETVhAA+Qc8nrA2I0kF7oa93mE9qnIurngOSpMnQ0x2nQY2FPviA=="], + "rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.15", "", {}, "sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g=="], "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -1656,12 +1698,12 @@ "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "tsx/esbuild": ["esbuild@0.27.7", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.7", "@esbuild/android-arm": "0.27.7", "@esbuild/android-arm64": "0.27.7", "@esbuild/android-x64": "0.27.7", "@esbuild/darwin-arm64": "0.27.7", "@esbuild/darwin-x64": "0.27.7", "@esbuild/freebsd-arm64": "0.27.7", "@esbuild/freebsd-x64": "0.27.7", "@esbuild/linux-arm": "0.27.7", "@esbuild/linux-arm64": "0.27.7", "@esbuild/linux-ia32": "0.27.7", "@esbuild/linux-loong64": "0.27.7", "@esbuild/linux-mips64el": "0.27.7", "@esbuild/linux-ppc64": "0.27.7", "@esbuild/linux-riscv64": "0.27.7", "@esbuild/linux-s390x": "0.27.7", "@esbuild/linux-x64": "0.27.7", "@esbuild/netbsd-arm64": "0.27.7", "@esbuild/netbsd-x64": "0.27.7", "@esbuild/openbsd-arm64": "0.27.7", "@esbuild/openbsd-x64": "0.27.7", "@esbuild/openharmony-arm64": "0.27.7", "@esbuild/sunos-x64": "0.27.7", "@esbuild/win32-arm64": "0.27.7", "@esbuild/win32-ia32": "0.27.7", "@esbuild/win32-x64": "0.27.7" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w=="], - "unconfig/quansync": ["quansync@1.0.0", "", {}, "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA=="], "unconfig-core/quansync": ["quansync@1.0.0", "", {}, "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA=="], + "unplugin-combine/rolldown": ["rolldown@1.0.0-rc.13", "", { "dependencies": { "@oxc-project/types": "=0.123.0", "@rolldown/pluginutils": "1.0.0-rc.13" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.13", "@rolldown/binding-darwin-arm64": "1.0.0-rc.13", "@rolldown/binding-darwin-x64": "1.0.0-rc.13", "@rolldown/binding-freebsd-x64": "1.0.0-rc.13", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.13", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.13", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.13", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.13", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.13", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.13", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.13" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-bvVj8YJmf0rq4pSFmH7laLa6pYrhghv3PRzrCdRAr23g66zOKVJ4wkvFtgohtPLWmthgg8/rkaqRHrpUEh0Zbw=="], + "unplugin-vue-define-options/@vue-macros/common": ["@vue-macros/common@1.16.1", "", { "dependencies": { "@vue/compiler-sfc": "^3.5.13", "ast-kit": "^1.4.0", "local-pkg": "^1.0.0", "magic-string-ast": "^0.7.0", "pathe": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "vue": "^2.7.0 || ^3.2.25" }, "optionalPeers": ["vue"] }, "sha512-Pn/AWMTjoMYuquepLZP813BIcq8DTZiNCoaceuNlvaYuOTd8DqBZWc5u0uOMQZMInwME1mdSmmBAcTluiV9Jtg=="], "unplugin-vue-macros/@vue-macros/boolean-prop": ["@vue-macros/boolean-prop@0.5.5", "", { "dependencies": { "@vue-macros/common": "1.16.1", "@vue/compiler-core": "^3.5.13" } }, "sha512-FfsIPefse634+jtqKC4AN3VUZ0OjndWqAlkOepV8h1UQ1pJnPk6DD87HhxGGtDuzOX9cKrMobvGHcPoqidQzMA=="], @@ -1676,7 +1718,7 @@ "unplugin-vue-macros/@vue-macros/volar": ["@vue-macros/volar@0.30.15", "", { "dependencies": { "@vue-macros/boolean-prop": "0.5.5", "@vue-macros/common": "1.16.1", "@vue-macros/config": "0.6.1", "@vue-macros/short-bind": "1.1.5", "@vue-macros/short-vmodel": "1.5.5", "@vue/language-core": "2.1.10", "muggle-string": "^0.4.1", "ts-macro": "^0.1.17" }, "peerDependencies": { "vue-tsc": "2.1.10" }, "optionalPeers": ["vue-tsc"] }, "sha512-CU2/XTH1Md06bpE+Opc8LDnY9t06tX8V2daZTWemsNb2NxxzRE+5Xj+EUGR/pG3R9dDXAZ7kQfERiIgO+dAb8w=="], - "vue-tsc/@vue/language-core": ["@vue/language-core@3.2.6", "", { "dependencies": { "@volar/language-core": "2.4.28", "@vue/compiler-dom": "^3.5.0", "@vue/shared": "^3.5.0", "alien-signals": "^3.0.0", "muggle-string": "^0.4.1", "path-browserify": "^1.0.1", "picomatch": "^4.0.2" } }, "sha512-xYYYX3/aVup576tP/23sEUpgiEnujrENaoNRbaozC1/MA9I6EGFQRJb4xrt/MmUCAGlxTKL2RmT8JLTPqagCkg=="], + "vue-tsc/@vue/language-core": ["@vue/language-core@3.2.7", "", { "dependencies": { "@volar/language-core": "2.4.28", "@vue/compiler-dom": "^3.5.0", "@vue/shared": "^3.5.0", "alien-signals": "^3.1.2", "muggle-string": "^0.4.1", "path-browserify": "^1.0.1", "picomatch": "^4.0.4" } }, "sha512-Gn4q/tRxbpVGLEuARQ43p3YELlNAFgRUVCgW9U5Cr+5q4vfD2bWDWpl3ABbJMXUt5xlE1dF8dkigg2aUq7JYYw=="], "wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], @@ -1688,47 +1730,61 @@ "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-android-arm-eabi": ["@oxc-parser/binding-android-arm-eabi@0.115.0", "", { "os": "android", "cpu": "arm" }, "sha512-VoB2rhgoqgYf64d6Qs5emONQW8ASiTc0xp+aUE4JUhxjX+0pE3gblTYDO0upcN5vt9UlBNmUhAwfSifkfre7nw=="], + "@typescript-eslint/rule-tester/@typescript-eslint/parser/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0" } }, "sha512-W1Lur1oF50FxSnNdGp3Vs6P+yBRSmZiw4IIjEeYxd8UQJwhUF0gDgDD/W/Tgmh73mxgEU3qX0Bzdl/NGuSPEpQ=="], + + "@typescript-eslint/rule-tester/@typescript-eslint/parser/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="], + + "@typescript-eslint/rule-tester/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.58.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.58.0", "@typescript-eslint/types": "^8.58.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-8Q/wBPWLQP1j16NxoPNIKpDZFMaxl7yWIoqXWYeWO+Bbd2mjgvoF0dxP2jKZg5+x49rgKdf7Ck473M8PC3V9lg=="], + + "@typescript-eslint/rule-tester/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.58.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-doNSZEVJsWEu4htiVC+PR6NpM+pa+a4ClH9INRWOWCUzMst/VA9c4gXq92F8GUD1rwhNvRLkgjfYtFXegXQF7A=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-android-arm64": ["@oxc-parser/binding-android-arm64@0.115.0", "", { "os": "android", "cpu": "arm64" }, "sha512-lWRX75u+gqfB4TF3pWCHuvhaeneAmRl2b2qNBcl4S6yJ0HtnT4VXOMEZrq747i4Zby1ZTxj6mtOe678Bg8gRLw=="], + "@typescript-eslint/rule-tester/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-darwin-arm64": ["@oxc-parser/binding-darwin-arm64@0.115.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ii/oOZjfGY1aszXTy29Z5DRyCEnBOrAXDVCvfdfXFQsOZlbbOa7NMHD7D+06YFe5qdxfmbWAYv4yn6QJi/0d2g=="], + "@typescript-eslint/rule-tester/@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0" } }, "sha512-W1Lur1oF50FxSnNdGp3Vs6P+yBRSmZiw4IIjEeYxd8UQJwhUF0gDgDD/W/Tgmh73mxgEU3qX0Bzdl/NGuSPEpQ=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-darwin-x64": ["@oxc-parser/binding-darwin-x64@0.115.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-R/sW/p8l77wglbjpMcF+h/3rWbp9zk1mRP3U14mxTYIC2k3m+aLBpXXgk2zksqf9qKk5mcc4GIYsuCn9l8TgDg=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-android-arm-eabi": ["@oxc-parser/binding-android-arm-eabi@0.124.0", "", { "os": "android", "cpu": "arm" }, "sha512-+R9zCafSL8ovjokdPtorUp3sXrh8zQ2AC2L0ivXNvlLR0WS+5WdPkNVrnENq5UvzagM4Xgl0NPsJKz3Hv9+y8g=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-freebsd-x64": ["@oxc-parser/binding-freebsd-x64@0.115.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-CSJ5ldNm9wIGGkhaIJeGmxRMZbgxThRN+X1ufYQQUNi5jZDV/U3C2QDMywpP93fczNBj961hXtcUPO/oVGq4Pw=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-android-arm64": ["@oxc-parser/binding-android-arm64@0.124.0", "", { "os": "android", "cpu": "arm64" }, "sha512-ULHC/gVZ+nP4pd3kNNQTYaQ/e066BW/KuY5qUsvwkVWwOUQGDg+WpfyVOmQ4xfxoue6cMlkKkJ+ntdzfDXpNlg=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-arm-gnueabihf": ["@oxc-parser/binding-linux-arm-gnueabihf@0.115.0", "", { "os": "linux", "cpu": "arm" }, "sha512-uWFwssE5dHfQ8lH+ktrsD9JA49+Qa0gtxZHUs62z1e91NgGz6O7jefHGI6aygNyKNS45pnnBSDSP/zV977MsOQ=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-darwin-arm64": ["@oxc-parser/binding-darwin-arm64@0.124.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-fGJ2hw7bnbUYn6UvTjp0m4WJ9zXz3cohgcwcgeo7gUZehpPNpvcVEVeIVHNmHnAuAw/ysf4YJR8DA1E+xCA4Lw=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-arm-musleabihf": ["@oxc-parser/binding-linux-arm-musleabihf@0.115.0", "", { "os": "linux", "cpu": "arm" }, "sha512-fZbqt8y/sKQ+v6bBCuv/mYYFoC0+fZI3mGDDEemmDOhT78+aUs2+4ZMdbd2btlXmnLaScl37r8IRbhnok5Ka9w=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-darwin-x64": ["@oxc-parser/binding-darwin-x64@0.124.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-j0+re9pgps5BH2Tk3fm59Hi3QuLP3C4KhqXi6A+wRHHHJWDFR8mc/KI9mBrfk2JRT+15doGo+zv1eN75/9DuOw=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-arm64-gnu": ["@oxc-parser/binding-linux-arm64-gnu@0.115.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-1ej/MjuTY9tJEunU/hUPIFmgH5PqgMQoRjNOvOkibtJ3Zqlw/+Lc+HGHDNET8sjbgIkWzdhX+p4J96A5CPdbag=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-freebsd-x64": ["@oxc-parser/binding-freebsd-x64@0.124.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-0k5mS0npnrhKy72UfF51lpOZ2ESoPWn6gdFw+RdeRWcokraDW1O2kSx3laQ+yk7cCEavQdJSpWCYS/GvBbUCXQ=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-arm64-musl": ["@oxc-parser/binding-linux-arm64-musl@0.115.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-HjsZbJPH9mMd4swJRywVMsDZsJX0hyKb1iNHo5ijRl5yhtbO3lj7ImSrrL1oZ1VEg0te4iKmDGGz/6YPLd1G8w=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-arm-gnueabihf": ["@oxc-parser/binding-linux-arm-gnueabihf@0.124.0", "", { "os": "linux", "cpu": "arm" }, "sha512-P/i4eguRWvAUfGdfhQYg1jpwYkyUV6D3gefIH7HhmRl1Ph6P4IqTIEVcyJr1i/3vr1V5OHU4wonH6/ue/Qzvrw=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-ppc64-gnu": ["@oxc-parser/binding-linux-ppc64-gnu@0.115.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-zhhePoBrd7kQx3oClX/W6NldsuCbuMqaN9rRsY+6/WoorAb4j490PG/FjqgAXscWp2uSW2WV9L+ksn0wHrvsrg=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-arm-musleabihf": ["@oxc-parser/binding-linux-arm-musleabihf@0.124.0", "", { "os": "linux", "cpu": "arm" }, "sha512-/ameqFQH5fFP+66Atr8Ynv/2rYe4utcU7L4MoWS5JtrFLVO78g4qDLavyIlJxa6caSwYOvG/eO3c/DXqY5/6Rw=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-riscv64-gnu": ["@oxc-parser/binding-linux-riscv64-gnu@0.115.0", "", { "os": "linux", "cpu": "none" }, "sha512-t/IRojvUE9XrKu+/H1b8YINug+7Q6FLls5rsm2lxB5mnS8GN/eYAYrPgHkcg9/1SueRDSzGpDYu3lGWTObk1zw=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-arm64-gnu": ["@oxc-parser/binding-linux-arm64-gnu@0.124.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-gNeyEcXTtfrRCbj2EfxWU85Fs0wIX3p44Y3twnvuMfkWlLrb9M1Z25AYNSKjJM+fdAjeeQCjw0on47zFuBYwQw=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-riscv64-musl": ["@oxc-parser/binding-linux-riscv64-musl@0.115.0", "", { "os": "linux", "cpu": "none" }, "sha512-79jBHSSh/YpQRAmvYoaCfpyToRbJ/HBrdB7hxK2ku2JMehjopTVo+xMJss/RV7/ZYqeezgjvKDQzapJbgcjVZA=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-arm64-musl": ["@oxc-parser/binding-linux-arm64-musl@0.124.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-uvG7v4Tz9S8/PVqY0SP0DLHxo4hZGe+Pv2tGVnwcsjKCCUPjplbrFVvDzXq+kOaEoUkiCY0Kt1hlZ6FDJ1LKNQ=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-s390x-gnu": ["@oxc-parser/binding-linux-s390x-gnu@0.115.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-nA1TpxkhNTIOMMyiSSsa7XIVJVoOU/SsVrHIz3gHvWweB5PHCQfO7w+Lb2EP0lBWokv7HtA/KbF7aLDoXzmuMw=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-ppc64-gnu": ["@oxc-parser/binding-linux-ppc64-gnu@0.124.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-t7KZaaUhfp2au0MRpoENEFqwLKYDdptEry6V7pTAVdPEcFG4P6ii8yeGU9m6p5vb+b8WEKmdpGMNXBEYy7iJdw=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-x64-gnu": ["@oxc-parser/binding-linux-x64-gnu@0.115.0", "", { "os": "linux", "cpu": "x64" }, "sha512-9iVX789DoC3SaOOG+X6NcF/tVChgLp2vcHffzOC2/Z1JTPlz6bMG2ogvcW6/9s0BG2qvhNQImd+gbWYeQbOwVw=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-riscv64-gnu": ["@oxc-parser/binding-linux-riscv64-gnu@0.124.0", "", { "os": "linux", "cpu": "none" }, "sha512-eurGGaxHZiIQ+fBSageS8TAkRqZgdOiBeqNrWAqAPup9hXBTmQ0WcBjwsLElf+3jvDL9NhnX0dOgOqPfsjSjdg=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-x64-musl": ["@oxc-parser/binding-linux-x64-musl@0.115.0", "", { "os": "linux", "cpu": "x64" }, "sha512-RmQmk+mjCB0nMNfEYhaCxwofLo1Z95ebHw1AGvRiWGCd4zhCNOyskgCbMogIcQzSB3SuEKWgkssyaiQYVAA4hQ=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-riscv64-musl": ["@oxc-parser/binding-linux-riscv64-musl@0.124.0", "", { "os": "linux", "cpu": "none" }, "sha512-d1V7/ll1i/LhqE/gZy6Wbz6evlk0egh2XKkwMI3epiojtbtUwQSLIER0Y3yDBBocPuWOjJdvmjtEmPTTLXje/w=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-openharmony-arm64": ["@oxc-parser/binding-openharmony-arm64@0.115.0", "", { "os": "none", "cpu": "arm64" }, "sha512-viigraWWQhhDvX5aGq+wrQq58k00Xq3MHz/0R4AFMxGlZ8ogNonpEfNc73Q5Ly87Z6sU9BvxEdG0dnYTfVnmew=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-s390x-gnu": ["@oxc-parser/binding-linux-s390x-gnu@0.124.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-w1+cBvriUteOpox6ATqCFVkpGL47PFdcfCPGmgUZbd78Fw44U0gQkc+kVGvAOTvGrptMYgwomD1c6OTVvkrpGg=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-wasm32-wasi": ["@oxc-parser/binding-wasm32-wasi@0.115.0", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-IzGCrMwXhpb4kTXy/8lnqqqwjI7eOvy+r9AhVw+hsr8t1ecBBEHprcNy0aKatFHN6hsX7UMHHQmBAQjVvL/p1A=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-x64-gnu": ["@oxc-parser/binding-linux-x64-gnu@0.124.0", "", { "os": "linux", "cpu": "x64" }, "sha512-RRB1evQiXRtMCsQQiAh9U0H3HzguLpE0ytfStuhRgmOj7tqUCOVxkHsvM9geZjAax6NqVRj7VXx32qjjkZPsBw=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-win32-arm64-msvc": ["@oxc-parser/binding-win32-arm64-msvc@0.115.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-/ym+Absk/TLFvbhh3se9XYuI1D7BrUVHw4RaG/2dmWKgBenrZHaJsgnRb7NJtaOyjEOLIPtULx1wDdVL0SX2eg=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-linux-x64-musl": ["@oxc-parser/binding-linux-x64-musl@0.124.0", "", { "os": "linux", "cpu": "x64" }, "sha512-asVYN0qmSHlCU8H9Q47SmeJ/Z5EG4IWCC+QGxkfFboI5qh15aLlJnHmnrV61MwQRPXGnVC/sC3qKhrUyqGxUqw=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-win32-ia32-msvc": ["@oxc-parser/binding-win32-ia32-msvc@0.115.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-AQSZjIR+b+Te7uaO/hGTMjT8/oxlYrvKrOTi4KTHF/O6osjHEatUQ3y6ZW2+8+lJxy20zIcGz6iQFmFq/qDKkg=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-openharmony-arm64": ["@oxc-parser/binding-openharmony-arm64@0.124.0", "", { "os": "none", "cpu": "arm64" }, "sha512-nhwuxm6B8pn9lzAzMUfa571L5hCXYwQo8C8cx5aGOuHWCzruR8gPJnRRXGBci+uGaIIQEZDyU/U6HDgrSp/JlQ=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-win32-x64-msvc": ["@oxc-parser/binding-win32-x64-msvc@0.115.0", "", { "os": "win32", "cpu": "x64" }, "sha512-oxUl82N+fIO9jIaXPph8SPPHQXrA08BHokBBJW8ct9F/x6o6bZE6eUAhUtWajbtvFhL8UYcCWRMba+kww6MBlA=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-wasm32-wasi": ["@oxc-parser/binding-wasm32-wasi@0.124.0", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.2" }, "cpu": "none" }, "sha512-LWuq4Dl9tff7n+HjJcqoBjDlVCtruc0shgtdtGM+rTUIE9aFxHA/P+wCYR+aWMjN8m9vNaRME/sKXErmhmeKrA=="], - "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-project/types": ["@oxc-project/types@0.115.0", "", {}, "sha512-4n91DKnebUS4yjUHl2g3/b2T+IUdCfmoZGhmwsovZCDaJSs+QkVAM+0AqqTxHSsHfeiMuueT75cZaZcT/m0pSw=="], + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-win32-arm64-msvc": ["@oxc-parser/binding-win32-arm64-msvc@0.124.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-aOh3Lf3AeH0dgzT4yBXcArFZ8VhqNXwZ/xlN0GqBtgVaGoHOOqL2YHlcVIgT+ghsXPVR2PTtYgBiQ1CNK7jp5A=="], + + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-win32-ia32-msvc": ["@oxc-parser/binding-win32-ia32-msvc@0.124.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-sib5xC0nz/+SCpaETBuHBz4SXS02KuG5HtyOcHsO/SK5ZvLRGhOZx0elDKawjb6adFkD7dQCqpXUS25wY6ELKQ=="], + + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-win32-x64-msvc": ["@oxc-parser/binding-win32-x64-msvc@0.124.0", "", { "os": "win32", "cpu": "x64" }, "sha512-UgojtjGUgZgAZQYt7SC6VO65OVdxEkRe2q+2vbHJO//18qw3Hrk6UvHGQKldsQKgbVcIBT/YBrt85YberiYIPQ=="], + + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-project/types": ["@oxc-project/types@0.124.0", "", {}, "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg=="], + + "@vitest/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="], "@volar/typescript/@volar/language-core/@volar/source-map": ["@volar/source-map@2.4.28", "", {}, "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ=="], @@ -1848,63 +1904,49 @@ "editorconfig/minimatch/brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="], - "glob/minimatch/brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="], - - "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], - - "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.7", "", { "os": "aix", "cpu": "ppc64" }, "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg=="], - - "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.7", "", { "os": "android", "cpu": "arm" }, "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ=="], - - "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.7", "", { "os": "android", "cpu": "arm64" }, "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ=="], - - "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.7", "", { "os": "android", "cpu": "x64" }, "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg=="], - - "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw=="], + "eslint-flat-config-utils/@eslint/config-helpers/@eslint/core": ["@eslint/core@1.2.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-8FTGbNzTvmSlc4cZBaShkC6YvFMG0riksYWRFKXztqVdXaQbcZLXlFbSpC05s70sGEsXAw0qwhx69JiW7hQS7A=="], - "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ=="], + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0" } }, "sha512-W1Lur1oF50FxSnNdGp3Vs6P+yBRSmZiw4IIjEeYxd8UQJwhUF0gDgDD/W/Tgmh73mxgEU3qX0Bzdl/NGuSPEpQ=="], - "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.7", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w=="], + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.58.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.58.0", "@typescript-eslint/tsconfig-utils": "8.58.0", "@typescript-eslint/types": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-7vv5UWbHqew/dvs+D3e1RvLv1v2eeZ9txRHPnEEBUgSNLx5ghdzjHa0sgLWYVKssH+lYmV0JaWdoubo0ncGYLA=="], - "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.7", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ=="], + "glob/minimatch/brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="], - "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.7", "", { "os": "linux", "cpu": "arm" }, "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA=="], + "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], - "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A=="], + "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.7", "", { "os": "linux", "cpu": "ia32" }, "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg=="], + "unplugin-combine/rolldown/@oxc-project/types": ["@oxc-project/types@0.123.0", "", {}, "sha512-YtECP/y8Mj1lSHiUWGSRzy/C6teUKlS87dEfuVKT09LgQbUsBW1rNg+MiJ4buGu3yuADV60gbIvo9/HplA56Ew=="], - "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q=="], + "unplugin-combine/rolldown/@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.13", "", { "os": "android", "cpu": "arm64" }, "sha512-5ZiiecKH2DXAVJTNN13gNMUcCDg4Jy8ZjbXEsPnqa248wgOVeYRX0iqXXD5Jz4bI9BFHgKsI2qmyJynstbmr+g=="], - "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw=="], + "unplugin-combine/rolldown/@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.13", "", { "os": "darwin", "cpu": "arm64" }, "sha512-tz/v/8G77seu8zAB3A5sK3UFoOl06zcshEzhUO62sAEtrEuW/H1CcyoupOrD+NbQJytYgA4CppXPzlrmp4JZKA=="], - "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.7", "", { "os": "linux", "cpu": "ppc64" }, "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ=="], + "unplugin-combine/rolldown/@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.13", "", { "os": "darwin", "cpu": "x64" }, "sha512-8DakphqOz8JrMYWTJmWA+vDJxut6LijZ8Xcdc4flOlAhU7PNVwo2MaWBF9iXjJAPo5rC/IxEFZDhJ3GC7NHvug=="], - "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.7", "", { "os": "linux", "cpu": "none" }, "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ=="], + "unplugin-combine/rolldown/@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.13", "", { "os": "freebsd", "cpu": "x64" }, "sha512-4wBQFfjDuXYN/SVI8inBF3Aa+isq40rc6VMFbk5jcpolUBTe5cYnMsHZ51nFWsx3PVyyNN3vgoESki0Hmr/4BA=="], - "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.7", "", { "os": "linux", "cpu": "s390x" }, "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw=="], + "unplugin-combine/rolldown/@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.13", "", { "os": "linux", "cpu": "arm" }, "sha512-JW/e4yPIXLms+jmnbwwy5LA/LxVwZUWLN8xug+V200wzaVi5TEGIWQlh8o91gWYFxW609euI98OCCemmWGuPrw=="], - "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.7", "", { "os": "linux", "cpu": "x64" }, "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA=="], + "unplugin-combine/rolldown/@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-ZfKWpXiUymDnavepCaM6KG/uGydJ4l2nBmMxg60Ci4CbeefpqjPWpfaZM7PThOhk2dssqBAcwLc6rAyr0uTdXg=="], - "tsx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w=="], + "unplugin-combine/rolldown/@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-bmRg3O6Z0gq9yodKKWCIpnlH051sEfdVwt+6m5UDffAQMUUqU0xjnQqqAUm+Gu7ofAAly9DqiQDtKu2nPDEABA=="], - "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.7", "", { "os": "none", "cpu": "x64" }, "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw=="], + "unplugin-combine/rolldown/@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "ppc64" }, "sha512-8Wtnbw4k7pMYN9B/mOEAsQ8HOiq7AZ31Ig4M9BKn2So4xRaFEhtCSa4ZJaOutOWq50zpgR4N5+L/opnlaCx8wQ=="], - "tsx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.7", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A=="], + "unplugin-combine/rolldown/@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "s390x" }, "sha512-D/0Nlo8mQuxSMohNJUF2lDXWRsFDsHldfRRgD9bRgktj+EndGPj4DOV37LqDKPYS+osdyhZEH7fTakTAEcW7qg=="], - "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.7", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg=="], + "unplugin-combine/rolldown/@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "x64" }, "sha512-eRrPvat2YaVQcwwKi/JzOP6MKf1WRnOCr+VaI3cTWz3ZoLcP/654z90lVCJ4dAuMEpPdke0n+qyAqXDZdIC4rA=="], - "tsx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.7", "", { "os": "none", "cpu": "arm64" }, "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw=="], + "unplugin-combine/rolldown/@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.13", "", { "os": "linux", "cpu": "x64" }, "sha512-PsdONiFRp8hR8KgVjTWjZ9s7uA3uueWL0t74/cKHfM4dR5zXYv4AjB8BvA+QDToqxAFg4ZkcVEqeu5F7inoz5w=="], - "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.7", "", { "os": "sunos", "cpu": "x64" }, "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA=="], + "unplugin-combine/rolldown/@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.13", "", { "os": "none", "cpu": "arm64" }, "sha512-hCNXgC5dI3TVOLrPT++PKFNZ+1EtS0mLQwfXXXSUD/+rGlB65gZDwN/IDuxLpQP4x8RYYHqGomlUXzpO8aVI2w=="], - "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA=="], + "unplugin-combine/rolldown/@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.13", "", { "dependencies": { "@emnapi/core": "1.9.1", "@emnapi/runtime": "1.9.1", "@napi-rs/wasm-runtime": "^1.1.2" }, "cpu": "none" }, "sha512-viLS5C5et8NFtLWw9Sw3M/w4vvnVkbWkO7wSNh3C+7G1+uCkGpr6PcjNDSFcNtmXY/4trjPBqUfcOL+P3sWy/g=="], - "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.7", "", { "os": "win32", "cpu": "ia32" }, "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw=="], + "unplugin-combine/rolldown/@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.13", "", { "os": "win32", "cpu": "arm64" }, "sha512-Fqa3Tlt1xL4wzmAYxGNFV36Hb+VfPc9PYU+E25DAnswXv3ODDu/yyWjQDbXMo5AGWkQVjLgQExuVu8I/UaZhPQ=="], - "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.7", "", { "os": "win32", "cpu": "x64" }, "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg=="], + "unplugin-combine/rolldown/@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.13", "", { "os": "win32", "cpu": "x64" }, "sha512-/pLI5kPkGEi44TDlnbio3St/5gUFeN51YWNAk/Gnv6mEQBOahRBh52qVFVBpmrnU01n2yysvBML9Ynu7K4kGAQ=="], "unplugin-vue-define-options/@vue-macros/common/ast-kit": ["ast-kit@1.4.3", "", { "dependencies": { "@babel/parser": "^7.27.0", "pathe": "^2.0.3" } }, "sha512-MdJqjpodkS5J149zN0Po+HPshkTdUyrvF7CKTafUgv69vBSPtncrj+3IiUgqdd7ElIEkbeXCsEouBUwLrw9Ilg=="], @@ -1928,12 +1970,28 @@ "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "@typescript-eslint/rule-tester/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="], + + "@unocss/transformer-attributify-jsx/oxc-parser/@oxc-parser/binding-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow=="], + "@vue-macros/api/oxc-resolver/@oxc-resolver/binding-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], "editorconfig/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="], + + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.58.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.58.0", "@typescript-eslint/types": "^8.58.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-8Q/wBPWLQP1j16NxoPNIKpDZFMaxl7yWIoqXWYeWO+Bbd2mjgvoF0dxP2jKZg5+x49rgKdf7Ck473M8PC3V9lg=="], + + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.58.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-doNSZEVJsWEu4htiVC+PR6NpM+pa+a4ClH9INRWOWCUzMst/VA9c4gXq92F8GUD1rwhNvRLkgjfYtFXegXQF7A=="], + + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="], + "glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "unplugin-combine/rolldown/@rolldown/binding-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" } }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="], + + "unplugin-combine/rolldown/@rolldown/binding-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.9.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA=="], + "unplugin-vue-macros/@vue-macros/volar/@vue/language-core/@volar/language-core": ["@volar/language-core@2.4.15", "", { "dependencies": { "@volar/source-map": "2.4.15" } }, "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA=="], "unplugin-vue-macros/@vue-macros/volar/@vue/language-core/alien-signals": ["alien-signals@0.2.2", "", {}, "sha512-cZIRkbERILsBOXTQmMrxc9hgpxglstn69zm+F1ARf4aPAzdAFYd6sBq87ErO0Fj3DV94tglcyHG5kQz9nDC/8A=="], @@ -1942,16 +2000,12 @@ "vue-tsc/@vue/language-core/@volar/language-core/@volar/source-map": ["@volar/source-map@2.4.28", "", {}, "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ=="], - "@vue-macros/api/oxc-resolver/@oxc-resolver/binding-wasm32-wasi/@napi-rs/wasm-runtime/@emnapi/core": ["@emnapi/core@1.9.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA=="], - - "@vue-macros/api/oxc-resolver/@oxc-resolver/binding-wasm32-wasi/@napi-rs/wasm-runtime/@emnapi/runtime": ["@emnapi/runtime@1.9.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw=="], + "unplugin-combine/rolldown/@rolldown/binding-wasm32-wasi/@emnapi/core/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="], "unplugin-vue-macros/@vue-macros/volar/@vue/language-core/@volar/language-core/@volar/source-map": ["@volar/source-map@2.4.15", "", {}, "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg=="], "unplugin-vue-macros/@vue-macros/volar/@vue/language-core/minimatch/brace-expansion": ["brace-expansion@2.0.3", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA=="], - "@vue-macros/api/oxc-resolver/@oxc-resolver/binding-wasm32-wasi/@napi-rs/wasm-runtime/@emnapi/core/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="], - "unplugin-vue-macros/@vue-macros/volar/@vue/language-core/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], } } diff --git a/package.json b/package.json index 423c3ff..47b6b60 100644 --- a/package.json +++ b/package.json @@ -25,35 +25,35 @@ "web-tree-sitter": "^0.26.8" }, "devDependencies": { - "@antfu/eslint-config": "^8.0.0", + "@antfu/eslint-config": "^8.2.0", "@iconify-json/carbon": "^1.2.20", "@iconify-json/line-md": "^1.2.16", "@iconify-json/mdi": "^1.2.3", "@iconify/utils": "^3.1.0", "@playwright/test": "^1.59.1", - "@types/node": "^25.5.2", - "@unocss/eslint-config": "^66.6.7", - "@unocss/eslint-plugin": "^66.6.7", - "@unocss/reset": "^66.6.7", - "@vitejs/plugin-vue": "^6.0.5", - "@vitest/coverage-v8": "^4.1.3", + "@types/node": "^25.6.0", + "@unocss/eslint-config": "^66.6.8", + "@unocss/eslint-plugin": "^66.6.8", + "@unocss/reset": "^66.6.8", + "@vitejs/plugin-vue": "^6.0.6", + "@vitest/coverage-v8": "^4.1.4", "@vue-macros/volar": "^3.1.2", "@vue/test-utils": "^2.4.6", - "eslint": "^10.2.0", + "eslint": "^10.2.1", "eslint-plugin-format": "^2.0.1", "jsdom": "^29.0.2", - "knip": "^6.3.0", + "knip": "^6.4.1", "lint-staged": "^16.4.0", "simple-git-hooks": "^2.13.1", "taze": "^19.11.0", "tree-sitter-cli": "^0.26.8", "tree-sitter-cpp": "^0.23.4", - "typescript": "^6.0.2", - "unocss": "^66.6.7", + "typescript": "^6.0.3", + "unocss": "^66.6.8", "unplugin-vue-macros": "^2.14.5", - "vite": "^8.0.7", - "vitest": "^4.1.3", - "vue-tsc": "^3.2.6" + "vite": "^8.0.8", + "vitest": "^4.1.4", + "vue-tsc": "^3.2.7" }, "simple-git-hooks": { "pre-commit": "bunx lint-staged" diff --git a/playwright.config.ts b/playwright.config.ts index f29eb0f..21ab6ed 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -4,6 +4,10 @@ export default defineConfig({ testDir: 'test/e2e', timeout: 60_000, retries: 1, + // Our snapshots are pure JSON extracted from a deterministic interpreter; + // strip Playwright's default OS suffix so Darwin and Linux goldens match + // and one checked-in file covers every CI runner. + snapshotPathTemplate: '{testDir}/{testFileName}-snapshots/{arg}{ext}', use: { baseURL: 'http://localhost:3333/StructViz/', headless: true, diff --git a/src/components/DataStructureView.vue b/src/components/DataStructureView.vue index bc637b1..a3c8b03 100644 --- a/src/components/DataStructureView.vue +++ b/src/components/DataStructureView.vue @@ -182,8 +182,20 @@ const contentRef = shallowRef(null) // Forward-declare placement so onDragEnd can reference it let placementRef: ReturnType | undefined +// One-shot flag set by onDragEnd; consumed (and reset) by onUpdated to skip +// the auto-pan that would otherwise undo a user drag out of the viewport. +let suppressAutoPanOnce = false + +/** Reactive dep for geometry that isn't tracked by Vue (DOM rects). Bumped + * after zoom updates settle into the DOM so the next render of the arrow + * overlay re-measures with fresh getBoundingClientRect values. Without this + * a zoom click renders one tick with stale rects and arrows appear offset + * until the user pans. */ +const arrowGeometryTick = shallowRef(0) + const { panOffset, + zoom, isPanning, didDrag, getDragDelta, @@ -191,15 +203,22 @@ const { panToElement, resetPan, clampPan, + setZoom, + zoomIn, + zoomOut, + resetZoom, } = usePannableCanvas({ canvasRef, hasContent: () => hasContent.value, onDragEnd(key, dx, dy) { const pos = placementRef?.getPosition(key) - if (pos) { + if (pos) placementRef?.setPosition(key, pos.x + dx, pos.y + dy) - placementRef?.markUserDragged(key) - } + // The drag commits a position that the next triggered relayout is free + // to override — we no longer track user drags as sticky. Suppress the + // one-shot auto-relayout so the dropped position survives at least the + // immediate bounds-change reaction (feels less teleporty). + suppressAutoPanOnce = true }, contentBounds: () => placementRef?.getContentBounds() ?? null, }) @@ -324,11 +343,8 @@ function invalidateStaleTreePositions( } } - // Apply invalidation (skip user-dragged items) - for (const key of expanded) { - if (!placement.isUserDragged(key)) - placement.remove(key) - } + for (const key of expanded) + placement.remove(key) // Update stored maps prevChildToParent.clear() @@ -393,15 +409,47 @@ function measureAndPlace(): NodeListOf | null { if (treePlacedKeys.size > 0) placement.evictOverlapping(treePlacedKeys) - // Step 3: Place remaining standalone items - for (const el of els) { - const key = el.dataset.placeKey! + // Step 3: Place non-pointer standalone items first so pointer cards (in + // step 3.5) can see their targets' positions. + const pointerItems: DataItem[] = [] + for (const item of standaloneItems.value) { + const key = `item-${item.address}` if (treePlacedKeys.has(key)) continue - const size = measured.get(key)! + const size = measured.get(key) + if (!size) + continue + if (item.kind === 'pointer') { + pointerItems.push(item) + continue + } placement.placeNew(key, size.w, size.h) } + // Step 3.5: Place pointer cards, topo-sorted so targets land first when a + // chain of pointers points through each other (p1 -> p2 -> x). Each pointer + // is probed against four target-adjacent candidate slots; the closest free + // one wins. Past a distance cap it falls through to a free-slot placement + // so crowded graphs don't shove pointers into far corners just to hug the + // target. + const sortedPointers = topoSortPointers(pointerItems) + for (const item of sortedPointers) { + const key = `item-${item.address}` + const size = measured.get(key) + if (!size) + continue + if (placement.getPosition(key)) { + // Already placed — consider relocating closer to target if the target + // has since moved far enough to open a significantly better slot. + // Guarded by a hysteresis threshold to prevent chasing small drifts. + maybeRelocatePointerNearTarget(key, item, size) + continue + } + const placedNearTarget = tryPlacePointerNearTarget(key, item, size) + if (!placedNearTarget) + placement.placeNew(key, size.w, size.h) + } + // Step 4: Retain only active keys const activeKeys = new Set() for (const el of els) @@ -411,6 +459,200 @@ function measureAndPlace(): NodeListOf | null { return els } +/** Resolve a pointer item's target allocation base, or null if the pointer + * is null / points outside any live allocation. */ +function pointerTargetBase(item: DataItem): number | null { + if (typeof item.type !== 'object' || item.type.type !== 'pointer') + return null + let raw: number + try { + raw = context.memory.readScalar(item.address, item.type) as number + } + catch { + return null + } + if (!raw) + return null + const alloc = context.memory.findAllocation(raw) + if (!alloc || alloc.dead) + return null + return alloc.base +} + +/** DFS-based topological sort: targets come before pointers that reference + * them. Pointer-to-pointer cycles fall through in original order so we + * always place every item exactly once. */ +function topoSortPointers(items: DataItem[]): DataItem[] { + const byAddr = new Map(items.map(i => [i.address, i])) + const visited = new Set() + const onPath = new Set() + const sorted: DataItem[] = [] + function visit(item: DataItem) { + if (visited.has(item.address) || onPath.has(item.address)) + return + onPath.add(item.address) + const tgt = pointerTargetBase(item) + if (tgt !== null) { + const depItem = byAddr.get(tgt) + if (depItem) + visit(depItem) + } + onPath.delete(item.address) + visited.add(item.address) + sorted.push(item) + } + for (const item of items) visit(item) + return sorted +} + +/** Find the target's tree parent and return a candidate position inside the + * gutter between them (if wide enough to fit). Null when the target has + * no structural parent or the gutter is too narrow. */ +function gutterCandidate( + tgtBase: number, + tPos: { x: number, y: number }, + tSize: { w: number, h: number }, + size: { w: number, h: number }, +): { x: number, y: number } | null { + const margin = 8 + for (const tree of pointerGraph.value.trees) { + for (const edge of tree.edges) { + if (edge.toAddress !== tgtBase) + continue + const pKey = addressToKey(edge.fromAddress) + if (!pKey) + return null + const pPos = placement.getPosition(pKey) + const pSize = placement.getSize(pKey) + if (!pPos || !pSize) + return null + const tCy = tPos.y + tSize.h / 2 + // Parent left of target — gutter between parent.right and target.left + if (pPos.x + pSize.w <= tPos.x) { + const l = pPos.x + pSize.w + margin + const r = tPos.x - margin + if (r - l >= size.w) + return { x: (l + r) / 2 - size.w / 2, y: tCy - size.h / 2 } + } + else if (pPos.x >= tPos.x + tSize.w) { + const l = tPos.x + tSize.w + margin + const r = pPos.x - margin + if (r - l >= size.w) + return { x: (l + r) / 2 - size.w / 2, y: tCy - size.h / 2 } + } + return null + } + } + return null +} + +/** Candidate slots around `target` that a pointer card might occupy: + * four sides at a fixed gap + an optional gutter between target and its + * tree parent when the gap is wide enough. Shared by initial placement + * and relocation so both paths consider the same geometry. */ +function pointerCandidatesAround( + tgtBase: number, + tPos: { x: number, y: number }, + tSize: { w: number, h: number }, + size: { w: number, h: number }, +): Array<{ x: number, y: number }> { + const gap = 20 + const tCx = tPos.x + tSize.w / 2 + const tCy = tPos.y + tSize.h / 2 + const candidates: Array<{ x: number, y: number }> = [ + { x: tPos.x + tSize.w + gap, y: tCy - size.h / 2 }, + { x: tPos.x - size.w - gap, y: tCy - size.h / 2 }, + { x: tCx - size.w / 2, y: tPos.y + tSize.h + gap }, + { x: tCx - size.w / 2, y: tPos.y - size.h - gap }, + ] + const gutter = gutterCandidate(tgtBase, tPos, tSize, size) + if (gutter) + candidates.push(gutter) + return candidates +} + +/** If the pointer is already placed but the target has drifted so far that + * a candidate slot is now meaningfully closer, relocate it. A + * hysteresis threshold prevents oscillation: we only move when the + * improvement exceeds ~40px, so a series of small target nudges doesn't + * thrash the pointer back and forth. */ +const RELOCATION_HYSTERESIS = 40 +function maybeRelocatePointerNearTarget(key: string, item: DataItem, size: { w: number, h: number }) { + const tgtBase = pointerTargetBase(item) + if (tgtBase === null) + return + const targetKey = addressToKey(tgtBase) + if (!targetKey) + return + const tPos = placement.getPosition(targetKey) + const tSize = placement.getSize(targetKey) + const currentPos = placement.getPosition(key) + if (!tPos || !tSize || !currentPos) + return + const tCx = tPos.x + tSize.w / 2 + const tCy = tPos.y + tSize.h / 2 + const currentDist = Math.hypot( + currentPos.x + size.w / 2 - tCx, + currentPos.y + size.h / 2 - tCy, + ) + const threshold = currentDist - RELOCATION_HYSTERESIS + if (threshold <= 0) + return + const ordered = pointerCandidatesAround(tgtBase, tPos, tSize, size) + .map((c) => { + const cx = c.x + size.w / 2 + const cy = c.y + size.h / 2 + return { ...c, d: Math.hypot(cx - tCx, cy - tCy) } + }) + .filter(c => c.d < threshold) + .sort((a, b) => a.d - b.d) + for (const c of ordered) { + if (placement.tryPlaceAt(key, c.x, c.y, size.w, size.h)) + return + } +} + +/** Try target-adjacent candidate slots (right, left, below, above, plus an + * optional "gutter between target and its tree parent" slot when an + * arrow-size override leaves room) and place the pointer at the closest + * free one within a distance cap. Returns true on success. */ +function tryPlacePointerNearTarget(key: string, item: DataItem, size: { w: number, h: number }): boolean { + const tgtBase = pointerTargetBase(item) + if (tgtBase === null) + return false + const targetKey = addressToKey(tgtBase) + if (!targetKey) + return false + const tPos = placement.getPosition(targetKey) + const tSize = placement.getSize(targetKey) + if (!tPos || !tSize) + return false + + // Distance cap: ~2x the bigger of the two card dimensions. Past that the + // "near target" heuristic breaks down and free-slot placement looks + // cleaner in crowded graphs. + const maxDist = 2 * Math.max(tSize.w, tSize.h, size.w, size.h) + + const tCx = tPos.x + tSize.w / 2 + const tCy = tPos.y + tSize.h / 2 + + // Walk nearest → farthest until one commits successfully. Candidate list + // is tiny, so sort is trivial; tryPlaceAt is the only side-effect. + const ordered = pointerCandidatesAround(tgtBase, tPos, tSize, size) + .map((c) => { + const cx = c.x + size.w / 2 + const cy = c.y + size.h / 2 + return { ...c, d: Math.hypot(cx - tCx, cy - tCy) } + }) + .filter(c => c.d <= maxDist) + .sort((a, b) => a.d - b.d) + for (const c of ordered) { + if (placement.tryPlaceAt(key, c.x, c.y, size.w, size.h)) + return true + } + return false +} + /** Recursively place children of a tree node via placeRelative */ function placeTreeChildren( parentAddress: number, @@ -449,12 +691,43 @@ function placeTreeChildren( // Look up struct-level arrowSize for the parent const arrowSizeOverride = context.structMeta[parentNode.structName]?.arrowSize + // Subtree leaf count — used in place of the physical card height so each + // branch reserves Y-space proportional to its descendants. Without this, + // deep branches' leaves land at the same Y as shallow branches' in + // different subtrees (classic "tidy tree" collision). Forward edges only + // so back-links / cycle edges don't cause infinite recursion; visit guard + // as belt and suspenders. + const leafCache = new Map() + const leafVisiting = new Set() + function leafCount(addr: number): number { + const cached = leafCache.get(addr) + if (cached !== undefined) + return cached + if (leafVisiting.has(addr)) + return 1 + leafVisiting.add(addr) + const edges = edgesByParent.get(addr) ?? [] + const forward = edges.filter(e => e.direction !== 'left') + const count = forward.length === 0 + ? 1 + : forward.reduce((s, e) => s + leafCount(e.toAddress), 0) + leafVisiting.delete(addr) + leafCache.set(addr, count) + return count + } + let maxH = 0 + for (const [, s] of measured) maxH = Math.max(maxH, s.h) + const rowPitch = (maxH || 88) + 16 + function placeGroup(group: ChildInfo[], dir: 'right' | 'left') { - const heights = group.map(c => c.h) + // Pass subtree extents as sibling heights so placeRelative's centering + // reserves enough room for each branch's descendants. A child with N + // leaves gets `N * rowPitch` of Y-space; a leaf gets rowPitch. + const extents = group.map(c => Math.max(c.h, leafCount(c.address) * rowPitch - 16)) for (let i = 0; i < group.length; i++) { const child = group[i] const size = measured.get(child.key)! - placement.placeRelative(child.key, parentKey, size.w, size.h, i, heights, dir, arrowSizeOverride) + placement.placeRelative(child.key, parentKey, size.w, size.h, i, extents, dir, arrowSizeOverride) placedKeys.add(child.key) placeTreeChildren(child.address, child.key, edgesByParent, measured, placedKeys) } @@ -485,24 +758,42 @@ onUpdated(() => nextTick(() => { if (els) animateEnterLeave(els) - // Auto-pan when content bounds changed and items are outside the visible viewport + // Step-triggered auto-relayout. When bounds changed AND the content's + // rendered extents fall outside the viewport, re-run layout and then + // auto-scale so everything fits. const bounds = placement.getContentBounds() const canvas = canvasRef.value if (bounds && canvas) { const boundsKey = `${bounds.minX},${bounds.minY},${bounds.maxX},${bounds.maxY}` if (boundsKey !== prevBoundsKey) { prevBoundsKey = boundsKey - // Check if any content is outside the current viewport - const viewLeft = -panOffset.x - const viewTop = -panOffset.y - const viewRight = viewLeft + canvas.clientWidth - const viewBottom = viewTop + canvas.clientHeight - if (bounds.minX < viewLeft || bounds.minY < viewTop - || bounds.maxX > viewRight || bounds.maxY > viewBottom) { - autoPanToContent() + // Overflow check MUST operate in screen space — content-space bounds + // alone don't encode the current zoom. Doing it in content-space would + // misfire at zoom != 1 and keep re-triggering autoRelayout, freezing + // the UI under the runaway reaction. + const z = zoom.value + const cw = canvas.clientWidth + const ch = canvas.clientHeight + const renderedLeft = panOffset.x + bounds.minX * z + const renderedTop = panOffset.y + bounds.minY * z + const renderedRight = panOffset.x + bounds.maxX * z + const renderedBottom = panOffset.y + bounds.maxY * z + const overflows = renderedLeft < 0 || renderedTop < 0 + || renderedRight > cw || renderedBottom > ch + if (!suppressAutoPanOnce && overflows) { + autoRelayoutInPlace() + autoScaleToFit() + // Relayout + scale moved positions → bounds key stored above is now + // stale. Snap prev to the post-relayout bounds so the next + // onUpdated doesn't see "bounds changed" and re-enter this branch + // for the same structural state. + const nb = placement.getContentBounds() + if (nb) + prevBoundsKey = `${nb.minX},${nb.minY},${nb.maxX},${nb.maxY}` } } } + suppressAutoPanOnce = false clampPan() })) @@ -513,6 +804,18 @@ watch(hasContent, (has) => { resetPan() }) +// Zoom changes only flow into the CSS transform on contentRef; arrow +// endpoints come from getBoundingClientRect which isn't a Vue dep. After the +// DOM has applied the new scale we bump the tick so the arrow render runs +// again with fresh rects. Without this, the first render after a zoom click +// measures the pre-scale DOM and arrows stay at their old positions until +// the user pans/interacts. +watch(zoom, () => { + nextTick(() => { + arrowGeometryTick.value++ + }) +}) + /** Get the final visual position of an item: placement + transient drag delta. * Uses transform (GPU-accelerated) instead of left/top (triggers layout). */ function getItemStyle(key: string) { @@ -655,6 +958,48 @@ const arrowEdges = computed((): (ArrowEdge | DanglingArrowEdge)[] => { } } + // Extra (non-tree) pointer edges: primitive pointer variables, struct + // fields whose target is not a struct, etc. Rendered with direction + // 'dynamic' so the arrow picks the nearest borders on both ends. + for (const edge of graph.extraEdges) { + const fromKey = addressToKey(edge.fromAddress) + const toKey = addressToKey(edge.toAddress) + if (fromKey && toKey) { + edges.push({ + id: `extra-${edge.fromFieldAddress}->${edge.toAddress}`, + fromKey, + toKey, + fieldAddress: edge.fromFieldAddress, + isCycle: false, + isDangling: false, + direction: edge.direction, + color: edge.color, + arrowStyle: edge.style, + fallbackStyle: edge.fallbackStyle, + arrowAnchor: getTargetAnchor(edge.toAddress), + }) + } + } + + for (const edge of graph.extraDanglingEdges) { + const fromKey = addressToKey(edge.fromAddress) + if (fromKey) { + edges.push({ + id: `extra-dangling-${edge.fromFieldAddress}`, + fromKey, + toKey: undefined, + fieldAddress: edge.fromFieldAddress, + isCycle: false, + isDangling: true, + danglingLabel: formatAddr(edge.toAddress), + direction: edge.direction, + color: edge.color, + arrowStyle: edge.style, + fallbackStyle: edge.fallbackStyle, + }) + } + } + return edges }) @@ -672,15 +1017,23 @@ function measureFieldY(parentKey: string, fieldAddress: number): number | undefi if (!fieldEl) return undefined + // Touch the tick so the render re-runs once the DOM has actually settled + // into the new zoom scale. See arrowGeometryTick declaration for context. + // eslint-disable-next-line ts/no-unused-expressions + arrowGeometryTick.value const parentRect = parentEl.getBoundingClientRect() const fieldRect = fieldEl.getBoundingClientRect() - // Offset within the parent + parent's content-space position + // Offset within the parent + parent's content-space position. + // getBoundingClientRect includes the canvas's CSS scale, so the raw screen + // pixel offset must be divided by zoom to bring it back into content space + // — otherwise at zoom 2x the arrow stems from 2× the correct field Y. const pos = placement.getPosition(parentKey) const delta = getDragDelta(parentKey) if (!pos) return undefined - const fieldCenterOffset = (fieldRect.top + fieldRect.height / 2) - parentRect.top - return pos.y + delta.y + fieldCenterOffset + const fieldCenterScreen = (fieldRect.top + fieldRect.height / 2) - parentRect.top + const z = zoom.value || 1 + return pos.y + delta.y + fieldCenterScreen / z } /** Get arrow props from a computed edge */ @@ -746,32 +1099,51 @@ function autoLayout() { measureAndPlace() } -// ---- Auto-pan to cover content after placement ---- +/** Step-triggered variant used from onUpdated when new structure overflows + * the viewport. Wipes positions (no user-drag exception — we no longer + * treat drags as sticky) and re-places from scratch, but keeps the + * current pan / zoom so the viewport frame stays stable. */ +function autoRelayoutInPlace() { + placement.clearPositions() + prevChildToParent.clear() + prevParentToChildren.clear() + settlingKeys.clear() + measureAndPlace() +} -function autoPanToContent() { +/** Scale the DS canvas down so the entire content bounding box fits inside + * the viewport (with a small padding), then center it. Never zooms in + * above 1x, so resting layout stays at the natural card size. Clamps at + * MIN_ZOOM when the content is still too large at the smallest allowed + * zoom — partial visibility is better than an invisible tangle. */ +const AUTO_FIT_PADDING = 24 +function autoScaleToFit() { const bounds = placement.getContentBounds() const canvas = canvasRef.value if (!bounds || !canvas) return const cw = canvas.clientWidth const ch = canvas.clientHeight - - // Center content in the viewport if it fits, otherwise align top-left with margin const contentW = bounds.maxX - bounds.minX const contentH = bounds.maxY - bounds.minY - const margin = 16 - - if (contentW <= cw && contentH <= ch) { - // Content fits: center it - panOffset.x = (cw - contentW) / 2 - bounds.minX - panOffset.y = (ch - contentH) / 2 - bounds.minY - } - else { - // Content overflows: align top-left with margin, prefer showing larger structures - panOffset.x = margin - bounds.minX - panOffset.y = margin - bounds.minY - } - clampPan() + if (contentW <= 0 || contentH <= 0) + return + // Scale-to-fit along the tighter axis; capped at 1 so we never + // auto-zoom IN — the user's current zoom preference wins if content + // already fits at 1x. + const zoomW = (cw - AUTO_FIT_PADDING * 2) / contentW + const zoomH = (ch - AUTO_FIT_PADDING * 2) / contentH + const target = Math.min(1, zoomW, zoomH) + setZoom(target) + // Re-center the content in the viewport at whatever zoom setZoom ended + // at (may be clamped to MIN_ZOOM). Rendered position of a content-space + // point p is `pan + p * z`; solving for "content center renders at + // viewport center" gives the expressions below. + const z = zoom.value + const cx = (bounds.minX + bounds.maxX) / 2 + const cy = (bounds.minY + bounds.maxY) / 2 + panOffset.x = cw / 2 - z * cx + panOffset.y = ch / 2 - z * cy } // Auto-pan to selected node @@ -781,6 +1153,65 @@ watch(() => props.selectedAddress, (addr) => { panToElement(`[data-testid="ds-node-${addr}"], [data-testid="ds-item-${addr}"]`) }) +// ---- Pointer-arrow hover wiring ---- + +/** Resolve a byte address inside a pointer scalar to the memory-map arrow it + * represents. Returns null for non-pointer bytes, padding, or dead allocs. + * Mirrors ByteMap's syncPointerArrow so hovering a DS-view arrow / pointer + * card produces the same primary-emphasis arrow in MemoryMap. */ +function pointerArrowFor(fieldAddr: number) { + // eslint-disable-next-line ts/no-unused-expressions + context.memoryVersion + const info = context.memory.describeByte(fieldAddr) + if (!info || info.isPadding || info.allocation.dead) + return null + const leafType = info.leafType + if (typeof leafType !== 'object' || leafType.type !== 'pointer') + return null + try { + const target = context.memory.readScalar(info.leafBase, leafType) as number + return { source: info.leafBase, sourceSize: info.leafSize, target } + } + catch { + return null + } +} + +/** Wired into . Extends the existing setField call + * (which highlights the field row / pointer card via `data-field-addr`) with + * a setPointerArrow so MemoryMap's arrow overlay lights up with primary + * emphasis for the same pointer. */ +function onArrowHoverField(fieldAddress: number | null) { + hover.setField(fieldAddress) + if (fieldAddress === null) { + hover.setPointerArrow(null) + return + } + hover.setPointerArrow(pointerArrowFor(fieldAddress)) +} + +function onItemEnter(item: DataItem) { + hover.setHover(item.address, 'ds') + if (item.varName) + emit('hoverVariable', item.varName) + // Hovering a primitive pointer card mirrors the effect of hovering its + // byte in ByteMap — MemoryMap draws the primary arrow. + if (item.kind === 'pointer') + hover.setPointerArrow(pointerArrowFor(item.address)) +} + +function onItemLeave() { + hover.setHover(null, null) + emit('hoverVariable', null) +} + +/** True when a CanvasArrow hover is pointing at the pointer this card holds + * (primitive pointer items only — struct fields already highlight via + * `data-field-addr` inside DSValue). */ +function isArrowSourceItem(item: DataItem): boolean { + return item.kind === 'pointer' && hover.fieldAddress.value === item.address +} + // ---- Color/shape for types ---- const kindColors: Record = { @@ -811,22 +1242,58 @@ const kindBg: Record = { class="relative h-full select-none overflow-hidden p-2" :class="hasContent ? (isPanning ? 'cursor-grabbing' : 'cursor-grab') : ''" > - - + + + + + +
No data to display
-
+
= { isHoverBoosted(item.address) ? 'bg-blue-500/20!' : '', !isHoverBoosted(item.address) && isStatementLhs(item.address) ? 'bg-blue-500/10!' : '', !isHoverBoosted(item.address) && isStatementRhs(item.address) && !isStatementLhs(item.address) ? 'bg-green-500/10!' : '', - !hasCodeHighlight(item.address) && isNodeHighlighted(item.address) ? 'bg-blue-500/10!' : '', + !hasCodeHighlight(item.address) && isArrowSourceItem(item) ? 'bg-blue-500/15! ring-1 ring-blue-400/40' : '', + !hasCodeHighlight(item.address) && isNodeHighlighted(item.address) && !isArrowSourceItem(item) ? 'bg-blue-500/10!' : '', item.dimmed ? 'opacity-40' : '', ]" :style="getItemStyle(`item-${item.address}`)" @click="!didDrag && emit('selectNode', item.address)" - @pointerenter="hover.setHover(item.address, 'ds'); item.varName && emit('hoverVariable', item.varName)" - @pointerleave="hover.setHover(null, null); emit('hoverVariable', null)" + @pointerenter="onItemEnter(item)" + @pointerleave="onItemLeave()" >
{{ item.label }} @@ -874,7 +1342,7 @@ const kindBg: Record = { v-for="edge in arrowEdges" :key="edge.id" v-bind="getArrowProps(edge)" - @hover-field="hover.setField($event)" + @hover-field="onArrowHoverField" />
diff --git a/src/components/InfoModal.vue b/src/components/InfoModal.vue new file mode 100644 index 0000000..596b916 --- /dev/null +++ b/src/components/InfoModal.vue @@ -0,0 +1,207 @@ + + + diff --git a/src/components/MemoryCell.vue b/src/components/MemoryCell.vue index 5868c86..9024c8f 100644 --- a/src/components/MemoryCell.vue +++ b/src/components/MemoryCell.vue @@ -21,6 +21,8 @@ const props = defineProps<{ fieldValues?: Map changed?: boolean highlightedFieldAddress?: number | null + statementLhsAddresses?: ReadonlySet + statementRhsAddresses?: ReadonlySet }>() const emit = defineEmits<{ @@ -41,7 +43,7 @@ const structName = computed(() => { diff --git a/src/styles/main.css b/src/styles/main.css index 5c9d97c..57e2131 100755 --- a/src/styles/main.css +++ b/src/styles/main.css @@ -23,6 +23,35 @@ html.dark { color: #e2e4e8; } +/* --- View-transition theme toggle --- + Replace the default cross-fade with the circular-reveal animation + driven from dark.ts. We animate only one side per transition (the + other stays a static snapshot underneath), so both pseudo-elements + need `animation: none` to disable the browser's built-in fade, and + the layer being animated needs to sit on top. `mix-blend-mode: normal` + prevents the stacked pseudo-elements from double-rendering colors. */ +::view-transition-old(root), +::view-transition-new(root) { + animation: none; + mix-blend-mode: normal; +} + +/* Going to light (html not .dark): new (light) expands over old (dark). */ +::view-transition-old(root) { + z-index: 1; +} +::view-transition-new(root) { + z-index: 9999; +} + +/* Going to dark (html .dark): old (light) shrinks away to reveal new (dark). */ +.dark::view-transition-old(root) { + z-index: 9999; +} +.dark::view-transition-new(root) { + z-index: 1; +} + /* Speed slider custom styling */ input[type='range'] { -webkit-appearance: none; diff --git a/test/e2e/templates.spec.ts b/test/e2e/templates.spec.ts new file mode 100644 index 0000000..cdd40fc --- /dev/null +++ b/test/e2e/templates.spec.ts @@ -0,0 +1,81 @@ +import { readdirSync } from 'node:fs' +import { dirname, join } from 'node:path' +import { fileURLToPath } from 'node:url' +import { expect, test } from '@playwright/test' + +// One integration test per template. Each runs the template to completion +// (at fastest simulation speed) and compares a structured view-state +// snapshot against the checked-in golden. On first run / after intentional +// changes, regenerate with: +// +// bun run test:e2e -- --update-snapshots +// +// The snapshot captures "what the three views should show" (allocations, +// their byte contents, and the pointer graph) rather than pixels, so it's +// stable across font/zoom/animation drift and diffs cleanly in PRs. + +const thisDir = dirname(fileURLToPath(import.meta.url)) +const templatesDir = join(thisDir, '..', '..', 'src', 'templates', 'general') + +const templateNames = readdirSync(templatesDir) + .filter(f => f.endsWith('.cpp')) + .map(f => f.replace(/\.cpp$/, '')) + // blank has no breakpoint + no allocations; nothing interesting to snapshot + .filter(name => name !== 'blank') + .sort() + +interface VizSnapshot { + endianness: 'le' | 'be' + pausedAt: { line: number, text: string } | null + allocations: Array<{ base: string, size: number, region: string, layout: string }> + liveBytes: Record + pointerEdges: Array<{ source: string, target: string }> +} + +test.describe.configure({ mode: 'parallel' }) + +for (const template of templateNames) { + test(`${template}: views match golden snapshot`, async ({ page }) => { + // Pre-seed localStorage so the app boots straight into this template at + // fastest speed. useStorage treats strings as raw — no JSON.stringify. + // Also wipe `code` so the default (template source) kicks in instead of + // whatever previous session happened to leave there. + await page.addInitScript(({ name }) => { + localStorage.setItem('selected-template', name) + localStorage.setItem('sim-speed', '50') + localStorage.removeItem('code') + }, { name: template }) + await page.goto('/') + // tree-sitter WASM loads asynchronously; btn-step flips data-ready=true + // once the parser is live. Without this the Run click is a no-op. + await expect(page.getByTestId('btn-step')).toHaveAttribute('data-ready', 'true', { timeout: 20_000 }) + + // Click Run and wait for the interpreter to pause at the breakpoint. + // Tracks "was ever active" on window so we don't false-positive on the + // pre-click isActive=false state. + // Reset the "was ever running" latch so the waitForFunction below + // doesn't short-circuit on the pre-click idle state. + await page.evaluate(() => { + const w = window as unknown as { __sawRunning: boolean } + w.__sawRunning = false + }) + await page.click('[data-testid="btn-run"]') + await page.waitForFunction(() => { + const w = window as unknown as { __viz?: { isRunning: () => boolean }, __sawRunning: boolean } + if (!w.__viz) + return false + if (w.__viz.isRunning()) { + w.__sawRunning = true + return false + } + return w.__sawRunning === true + }, null, { timeout: 45_000 }) + + const snapshot = await page.evaluate(() => { + const w = window as unknown as { __viz: { snapshot: () => VizSnapshot } } + return w.__viz.snapshot() + }) + const canonical = `${JSON.stringify(snapshot, null, 2)}\n` + expect(canonical).toMatchSnapshot(`${template}.json`) + }) +} diff --git a/test/e2e/templates.spec.ts-snapshots/avl-rotations.json b/test/e2e/templates.spec.ts-snapshots/avl-rotations.json new file mode 100644 index 0000000..2eeca24 --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/avl-rotations.json @@ -0,0 +1,53 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 100, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3fd0", + "size": 16, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3fe0", + "size": 16, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3ff0", + "size": 16, + "region": "heap", + "layout": "struct TreeNode" + } + ], + "liveBytes": { + "0x0004": "e0 3f 00 00", + "0x3fd0": "0a 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00", + "0x3fe0": "14 00 00 00 02 00 00 00 d0 3f 00 00 f0 3f 00 00", + "0x3ff0": "1e 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3fe0" + }, + { + "source": "0x3fe8", + "target": "0x3fd0" + }, + { + "source": "0x3fec", + "target": "0x3ff0" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/bst-delete.json b/test/e2e/templates.spec.ts-snapshots/bst-delete.json new file mode 100644 index 0000000..b0e67d7 --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/bst-delete.json @@ -0,0 +1,53 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 78, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3fc4", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3fdc", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3ff4", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + } + ], + "liveBytes": { + "0x0004": "f4 3f 00 00", + "0x3fc4": "04 00 00 00 00 00 00 00 00 00 00 00", + "0x3fdc": "07 00 00 00 00 00 00 00 00 00 00 00", + "0x3ff4": "06 00 00 00 c4 3f 00 00 dc 3f 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3ff4" + }, + { + "source": "0x3ff8", + "target": "0x3fc4" + }, + { + "source": "0x3ffc", + "target": "0x3fdc" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/bst-freeAll.json b/test/e2e/templates.spec.ts-snapshots/bst-freeAll.json new file mode 100644 index 0000000..b00ae0a --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/bst-freeAll.json @@ -0,0 +1,24 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 48, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + } + ], + "liveBytes": { + "0x0004": "f4 3f 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3ff4" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/bst-insert.json b/test/e2e/templates.spec.ts-snapshots/bst-insert.json new file mode 100644 index 0000000..e5f77b2 --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/bst-insert.json @@ -0,0 +1,75 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 35, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3fc4", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3fd0", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3fdc", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3fe8", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3ff4", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + } + ], + "liveBytes": { + "0x0004": "f4 3f 00 00", + "0x3fc4": "04 00 00 00 00 00 00 00 00 00 00 00", + "0x3fd0": "01 00 00 00 00 00 00 00 00 00 00 00", + "0x3fdc": "07 00 00 00 00 00 00 00 00 00 00 00", + "0x3fe8": "03 00 00 00 d0 3f 00 00 c4 3f 00 00", + "0x3ff4": "05 00 00 00 e8 3f 00 00 dc 3f 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3ff4" + }, + { + "source": "0x3fec", + "target": "0x3fd0" + }, + { + "source": "0x3ff0", + "target": "0x3fc4" + }, + { + "source": "0x3ff8", + "target": "0x3fe8" + }, + { + "source": "0x3ffc", + "target": "0x3fdc" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/bst-search.json b/test/e2e/templates.spec.ts-snapshots/bst-search.json new file mode 100644 index 0000000..5657849 --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/bst-search.json @@ -0,0 +1,93 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 51, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x00a0", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x00bc", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3fc4", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3fd0", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3fdc", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3fe8", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3ff4", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + } + ], + "liveBytes": { + "0x0004": "f4 3f 00 00", + "0x00a0": "c4 3f 00 00", + "0x00bc": "00 00 00 00", + "0x3fc4": "04 00 00 00 00 00 00 00 00 00 00 00", + "0x3fd0": "01 00 00 00 00 00 00 00 00 00 00 00", + "0x3fdc": "07 00 00 00 00 00 00 00 00 00 00 00", + "0x3fe8": "03 00 00 00 d0 3f 00 00 c4 3f 00 00", + "0x3ff4": "05 00 00 00 e8 3f 00 00 dc 3f 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3ff4" + }, + { + "source": "0x00a0", + "target": "0x3fc4" + }, + { + "source": "0x3fec", + "target": "0x3fd0" + }, + { + "source": "0x3ff0", + "target": "0x3fc4" + }, + { + "source": "0x3ff8", + "target": "0x3fe8" + }, + { + "source": "0x3ffc", + "target": "0x3fdc" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/btree.json b/test/e2e/templates.spec.ts-snapshots/btree.json new file mode 100644 index 0000000..9abbaf1 --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/btree.json @@ -0,0 +1,97 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 56, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x0008", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x000c", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x0010", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3f80", + "size": 32, + "region": "heap", + "layout": "struct BTreeNode" + }, + { + "base": "0x3fa0", + "size": 32, + "region": "heap", + "layout": "struct BTreeNode" + }, + { + "base": "0x3fc0", + "size": 32, + "region": "heap", + "layout": "struct BTreeNode" + }, + { + "base": "0x3fe0", + "size": 32, + "region": "heap", + "layout": "struct BTreeNode" + } + ], + "liveBytes": { + "0x0004": "e0 3f 00 00", + "0x0008": "c0 3f 00 00", + "0x000c": "a0 3f 00 00", + "0x0010": "80 3f 00 00", + "0x3f80": "02 00 00 00 19 00 00 00 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "0x3fa0": "01 00 00 00 0e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "0x3fc0": "02 00 00 00 03 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", + "0x3fe0": "02 00 00 00 0a 00 00 00 14 00 00 00 00 00 00 00 c0 3f 00 00 a0 3f 00 00 80 3f 00 00 00 00 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3fe0" + }, + { + "source": "0x0008", + "target": "0x3fc0" + }, + { + "source": "0x000c", + "target": "0x3fa0" + }, + { + "source": "0x0010", + "target": "0x3f80" + }, + { + "source": "0x3ff0", + "target": "0x3fc0" + }, + { + "source": "0x3ff4", + "target": "0x3fa0" + }, + { + "source": "0x3ff8", + "target": "0x3f80" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/bubble-sort.json b/test/e2e/templates.spec.ts-snapshots/bubble-sort.json new file mode 100644 index 0000000..e6c36cb --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/bubble-sort.json @@ -0,0 +1,33 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 27, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 24, + "region": "stack", + "layout": "array[6]" + }, + { + "base": "0x001c", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x0020", + "size": 4, + "region": "stack", + "layout": "scalar" + } + ], + "liveBytes": { + "0x0004": "01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 08 00 00 00", + "0x001c": "06 00 00 00", + "0x0020": "05 00 00 00" + }, + "pointerEdges": [] +} diff --git a/test/e2e/templates.spec.ts-snapshots/doubly-insertBack.json b/test/e2e/templates.spec.ts-snapshots/doubly-insertBack.json new file mode 100644 index 0000000..101f7f1 --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/doubly-insertBack.json @@ -0,0 +1,61 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 48, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3fdc", + "size": 12, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3fe8", + "size": 12, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3ff4", + "size": 12, + "region": "heap", + "layout": "struct ListNode" + } + ], + "liveBytes": { + "0x0004": "f4 3f 00 00", + "0x3fdc": "03 00 00 00 00 00 00 00 e8 3f 00 00", + "0x3fe8": "02 00 00 00 dc 3f 00 00 f4 3f 00 00", + "0x3ff4": "01 00 00 00 e8 3f 00 00 00 00 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3ff4" + }, + { + "source": "0x3fe4", + "target": "0x3fe8" + }, + { + "source": "0x3fec", + "target": "0x3fdc" + }, + { + "source": "0x3ff0", + "target": "0x3ff4" + }, + { + "source": "0x3ff8", + "target": "0x3fe8" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/doubly-reverse.json b/test/e2e/templates.spec.ts-snapshots/doubly-reverse.json new file mode 100644 index 0000000..d353c77 --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/doubly-reverse.json @@ -0,0 +1,91 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 64, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3fc4", + "size": 12, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3fd0", + "size": 12, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3fdc", + "size": 12, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3fe8", + "size": 12, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3ff4", + "size": 12, + "region": "heap", + "layout": "struct ListNode" + } + ], + "liveBytes": { + "0x0004": "c4 3f 00 00", + "0x3fc4": "05 00 00 00 d0 3f 00 00 00 00 00 00", + "0x3fd0": "04 00 00 00 dc 3f 00 00 c4 3f 00 00", + "0x3fdc": "03 00 00 00 e8 3f 00 00 d0 3f 00 00", + "0x3fe8": "02 00 00 00 f4 3f 00 00 dc 3f 00 00", + "0x3ff4": "01 00 00 00 00 00 00 00 e8 3f 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3fc4" + }, + { + "source": "0x3fc8", + "target": "0x3fd0" + }, + { + "source": "0x3fd4", + "target": "0x3fdc" + }, + { + "source": "0x3fd8", + "target": "0x3fc4" + }, + { + "source": "0x3fe0", + "target": "0x3fe8" + }, + { + "source": "0x3fe4", + "target": "0x3fd0" + }, + { + "source": "0x3fec", + "target": "0x3ff4" + }, + { + "source": "0x3ff0", + "target": "0x3fdc" + }, + { + "source": "0x3ffc", + "target": "0x3fe8" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/singly-delete.json b/test/e2e/templates.spec.ts-snapshots/singly-delete.json new file mode 100644 index 0000000..3349e6f --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/singly-delete.json @@ -0,0 +1,53 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 57, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3fe0", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3ff0", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3ff8", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + } + ], + "liveBytes": { + "0x0004": "f8 3f 00 00", + "0x3fe0": "04 00 00 00 00 00 00 00", + "0x3ff0": "02 00 00 00 e0 3f 00 00", + "0x3ff8": "01 00 00 00 f0 3f 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3ff8" + }, + { + "source": "0x3ff4", + "target": "0x3fe0" + }, + { + "source": "0x3ffc", + "target": "0x3ff0" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/singly-freeAll.json b/test/e2e/templates.spec.ts-snapshots/singly-freeAll.json new file mode 100644 index 0000000..4c89d35 --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/singly-freeAll.json @@ -0,0 +1,19 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 42, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + } + ], + "liveBytes": { + "0x0004": "00 00 00 00" + }, + "pointerEdges": [] +} diff --git a/test/e2e/templates.spec.ts-snapshots/singly-insertBack.json b/test/e2e/templates.spec.ts-snapshots/singly-insertBack.json new file mode 100644 index 0000000..e195c20 --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/singly-insertBack.json @@ -0,0 +1,53 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 31, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3fe8", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3ff0", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3ff8", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + } + ], + "liveBytes": { + "0x0004": "f8 3f 00 00", + "0x3fe8": "03 00 00 00 00 00 00 00", + "0x3ff0": "02 00 00 00 e8 3f 00 00", + "0x3ff8": "01 00 00 00 f0 3f 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3ff8" + }, + { + "source": "0x3ff4", + "target": "0x3fe8" + }, + { + "source": "0x3ffc", + "target": "0x3ff0" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/singly-insertFront.json b/test/e2e/templates.spec.ts-snapshots/singly-insertFront.json new file mode 100644 index 0000000..7a55a98 --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/singly-insertFront.json @@ -0,0 +1,53 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 21, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3fe8", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3ff0", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3ff8", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + } + ], + "liveBytes": { + "0x0004": "e8 3f 00 00", + "0x3fe8": "01 00 00 00 f0 3f 00 00", + "0x3ff0": "02 00 00 00 f8 3f 00 00", + "0x3ff8": "03 00 00 00 00 00 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3fe8" + }, + { + "source": "0x3fec", + "target": "0x3ff0" + }, + { + "source": "0x3ff4", + "target": "0x3ff8" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/singly-loop.json b/test/e2e/templates.spec.ts-snapshots/singly-loop.json new file mode 100644 index 0000000..196dca1 --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/singly-loop.json @@ -0,0 +1,79 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 39, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x0044", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3fe0", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3fe8", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3ff0", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3ff8", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + } + ], + "liveBytes": { + "0x0004": "f8 3f 00 00", + "0x0044": "e0 3f 00 00", + "0x3fe0": "04 00 00 00 f0 3f 00 00", + "0x3fe8": "03 00 00 00 e0 3f 00 00", + "0x3ff0": "02 00 00 00 e8 3f 00 00", + "0x3ff8": "01 00 00 00 f0 3f 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3ff8" + }, + { + "source": "0x0044", + "target": "0x3fe0" + }, + { + "source": "0x3fe4", + "target": "0x3ff0" + }, + { + "source": "0x3fec", + "target": "0x3fe0" + }, + { + "source": "0x3ff4", + "target": "0x3fe8" + }, + { + "source": "0x3ffc", + "target": "0x3ff0" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/singly-reverse.json b/test/e2e/templates.spec.ts-snapshots/singly-reverse.json new file mode 100644 index 0000000..52eb515 --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/singly-reverse.json @@ -0,0 +1,75 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 49, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3fd8", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3fe0", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3fe8", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3ff0", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + }, + { + "base": "0x3ff8", + "size": 8, + "region": "heap", + "layout": "struct ListNode" + } + ], + "liveBytes": { + "0x0004": "d8 3f 00 00", + "0x3fd8": "05 00 00 00 e0 3f 00 00", + "0x3fe0": "04 00 00 00 e8 3f 00 00", + "0x3fe8": "03 00 00 00 f0 3f 00 00", + "0x3ff0": "02 00 00 00 f8 3f 00 00", + "0x3ff8": "01 00 00 00 00 00 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3fd8" + }, + { + "source": "0x3fdc", + "target": "0x3fe0" + }, + { + "source": "0x3fe4", + "target": "0x3fe8" + }, + { + "source": "0x3fec", + "target": "0x3ff0" + }, + { + "source": "0x3ff4", + "target": "0x3ff8" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/tree-cycle.json b/test/e2e/templates.spec.ts-snapshots/tree-cycle.json new file mode 100644 index 0000000..8df7f60 --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/tree-cycle.json @@ -0,0 +1,79 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 32, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x0008", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x000c", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3fdc", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3fe8", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3ff4", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + } + ], + "liveBytes": { + "0x0004": "f4 3f 00 00", + "0x0008": "e8 3f 00 00", + "0x000c": "dc 3f 00 00", + "0x3fdc": "03 00 00 00 f4 3f 00 00 00 00 00 00", + "0x3fe8": "02 00 00 00 00 00 00 00 00 00 00 00", + "0x3ff4": "01 00 00 00 e8 3f 00 00 dc 3f 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3ff4" + }, + { + "source": "0x0008", + "target": "0x3fe8" + }, + { + "source": "0x000c", + "target": "0x3fdc" + }, + { + "source": "0x3fe0", + "target": "0x3ff4" + }, + { + "source": "0x3ff8", + "target": "0x3fe8" + }, + { + "source": "0x3ffc", + "target": "0x3fdc" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/tree-dangling.json b/test/e2e/templates.spec.ts-snapshots/tree-dangling.json new file mode 100644 index 0000000..3c63124 --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/tree-dangling.json @@ -0,0 +1,86 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 39, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x0008", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x000c", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x0010", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3fd0", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3fdc", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3ff4", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + } + ], + "liveBytes": { + "0x0004": "f4 3f 00 00", + "0x0008": "e8 3f 00 00", + "0x000c": "dc 3f 00 00", + "0x0010": "d0 3f 00 00", + "0x3fd0": "02 00 00 00 00 00 00 00 00 00 00 00", + "0x3fdc": "0f 00 00 00 00 00 00 00 00 00 00 00", + "0x3ff4": "0a 00 00 00 e8 3f 00 00 dc 3f 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3ff4" + }, + { + "source": "0x0008", + "target": "0x3fe8" + }, + { + "source": "0x000c", + "target": "0x3fdc" + }, + { + "source": "0x0010", + "target": "0x3fd0" + }, + { + "source": "0x3ff8", + "target": "0x3fe8" + }, + { + "source": "0x3ffc", + "target": "0x3fdc" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/tree-rebuild.json b/test/e2e/templates.spec.ts-snapshots/tree-rebuild.json new file mode 100644 index 0000000..095e61c --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/tree-rebuild.json @@ -0,0 +1,75 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 33, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x000c", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x0028", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3fd0", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3fdc", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3fe8", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3ff4", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + } + ], + "liveBytes": { + "0x000c": "f4 3f 00 00", + "0x0028": "e8 3f 00 00", + "0x3fd0": "04 00 00 00 00 00 00 00 00 00 00 00", + "0x3fdc": "03 00 00 00 00 00 00 00 e8 3f 00 00", + "0x3fe8": "02 00 00 00 d0 3f 00 00 00 00 00 00", + "0x3ff4": "01 00 00 00 00 00 00 00 dc 3f 00 00" + }, + "pointerEdges": [ + { + "source": "0x000c", + "target": "0x3ff4" + }, + { + "source": "0x0028", + "target": "0x3fe8" + }, + { + "source": "0x3fe4", + "target": "0x3fe8" + }, + { + "source": "0x3fec", + "target": "0x3fd0" + }, + { + "source": "0x3ffc", + "target": "0x3fdc" + } + ] +} diff --git a/test/e2e/templates.spec.ts-snapshots/tree-skewed.json b/test/e2e/templates.spec.ts-snapshots/tree-skewed.json new file mode 100644 index 0000000..3512846 --- /dev/null +++ b/test/e2e/templates.spec.ts-snapshots/tree-skewed.json @@ -0,0 +1,75 @@ +{ + "endianness": "le", + "pausedAt": { + "line": 38, + "text": "breakpoint()" + }, + "allocations": [ + { + "base": "0x0004", + "size": 4, + "region": "stack", + "layout": "scalar" + }, + { + "base": "0x3fc4", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3fd0", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3fdc", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3fe8", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + }, + { + "base": "0x3ff4", + "size": 12, + "region": "heap", + "layout": "struct TreeNode" + } + ], + "liveBytes": { + "0x0004": "f4 3f 00 00", + "0x3fc4": "05 00 00 00 00 00 00 00 00 00 00 00", + "0x3fd0": "04 00 00 00 00 00 00 00 c4 3f 00 00", + "0x3fdc": "03 00 00 00 00 00 00 00 d0 3f 00 00", + "0x3fe8": "02 00 00 00 00 00 00 00 dc 3f 00 00", + "0x3ff4": "01 00 00 00 00 00 00 00 e8 3f 00 00" + }, + "pointerEdges": [ + { + "source": "0x0004", + "target": "0x3ff4" + }, + { + "source": "0x3fd8", + "target": "0x3fc4" + }, + { + "source": "0x3fe4", + "target": "0x3fd0" + }, + { + "source": "0x3ff0", + "target": "0x3fdc" + }, + { + "source": "0x3ffc", + "target": "0x3fe8" + } + ] +} diff --git a/test/e2e/visualization.spec.ts b/test/e2e/visualization.spec.ts deleted file mode 100644 index f106a18..0000000 --- a/test/e2e/visualization.spec.ts +++ /dev/null @@ -1,297 +0,0 @@ -import { expect, test } from '@playwright/test' - -// Helper: click the step button N times, waiting for each step to complete -// by observing the data-step attribute (memory version) change on the button. -async function stepN(page: import('@playwright/test').Page, n: number) { - const btn = page.getByTestId('btn-step') - for (let i = 0; i < n; i++) { - const before = Number(await btn.getAttribute('data-step')) || 0 - await btn.click() - // Wait for version to increment (first step is slower due to init + parse) - await expect(async () => { - const after = Number(await btn.getAttribute('data-step')) || 0 - expect(after).toBeGreaterThan(before) - }).toPass({ timeout: 10_000 }) - } -} - -test.beforeEach(async ({ page }) => { - await page.goto('/') - // The Step button renders immediately, but tree-sitter WASM loads - // asynchronously and the first click is a no-op until `tree` is populated. - // `data-ready` flips to "true" once the parser has loaded and produced a - // tree — wait on it deterministically instead of a fixed timeout. - await expect(page.getByTestId('btn-step')).toHaveAttribute('data-ready', 'true', { timeout: 15_000 }) -}) - -test.describe('memory map', () => { - test('shows stack variables after stepping', async ({ page }) => { - await stepN(page, 3) - - const stackColumn = page.getByTestId('stack-column') - await expect(stackColumn).toBeVisible() - const entries = stackColumn.locator('[data-testid^="stack-entry-"]') - await expect(entries.first()).toBeVisible() - }) - - test('shows heap allocations after new ListNode', async ({ page }) => { - await stepN(page, 5) - - const heapColumn = page.getByTestId('heap-column') - await expect(heapColumn).toBeVisible() - const heapCells = heapColumn.locator('[data-testid^="heap-cell-"]') - await expect(heapCells.first()).toBeVisible() - await expect(heapCells.first()).toContainText('ListNode') - }) - - test('shows caller scope variables (not just current scope)', async ({ page }) => { - // Step into insertBack — head from main should still be visible - await stepN(page, 4) - - const stackColumn = page.getByTestId('stack-column') - const stackText = await stackColumn.textContent() - expect(stackText).toContain('head') - }) - - test('does not dim variables in if/while scopes (only caller)', async ({ page }) => { - await stepN(page, 12) - - const stackColumn = page.getByTestId('stack-column') - const currentEntries = stackColumn.locator('[data-testid^="stack-entry-"]:not(.opacity-40)') - const count = await currentEntries.count() - expect(count).toBeGreaterThanOrEqual(2) - }) -}) - -test.describe('data structure panel', () => { - test('shows DS items after building list', async ({ page }) => { - await stepN(page, 15) - - const dsView = page.getByTestId('ds-view') - await expect(dsView).toBeVisible() - const items = dsView.locator('[data-testid^="ds-item-"]') - await expect(items.first()).toBeVisible() - }) - - test('shows detail panel when clicking a DS item', async ({ page }) => { - await stepN(page, 15) - - const dsView = page.getByTestId('ds-view') - // Click a struct item (contains "ListNode"), not a stack pointer - const structItem = dsView.locator('[data-testid^="ds-item-"]').filter({ hasText: 'ListNode' }).first() - await structItem.click() - - const fieldTable = page.getByTestId('field-table') - await expect(fieldTable).toBeVisible() - await expect(fieldTable).toContainText('data') - await expect(fieldTable).toContainText('next') - }) - - test('close button hides detail panel', async ({ page }) => { - await stepN(page, 15) - - const firstItem = page.getByTestId('ds-view').locator('[data-testid^="ds-item-"]').first() - await firstItem.click() - await expect(page.getByTestId('field-table')).toBeVisible() - - await page.getByTestId('detail-close').click({ force: true }) - - await expect(page.getByTestId('field-table')).not.toBeVisible() - await expect(page.getByTestId('ds-view')).toBeVisible() - }) -}) - -// Helper to select a template via dropdown -async function selectTemplate(page: import('@playwright/test').Page, name: string) { - await page.getByTestId('template-picker').locator('button').first().click() - await page.waitForTimeout(100) - await page.getByTestId(`template-${name}`).click() - await page.waitForTimeout(200) -} - -test.describe('reverse algorithm visualization', () => { - test.beforeEach(async ({ page }) => { - await selectTemplate(page, 'singly-reverse') - }) - - test('shows DS items mid-reverse', async ({ page }) => { - // Step through insertBack phase + into reverse - await stepN(page, 62) - - const dsView = page.getByTestId('ds-view') - await expect(dsView).toBeVisible() - - const items = dsView.locator('[data-testid^="ds-item-"]') - const count = await items.count() - expect(count).toBeGreaterThanOrEqual(1) - }) - - test('shows complete reversed list after completion', async ({ page }) => { - await page.getByTestId('btn-run').click() - await page.waitForTimeout(20_000) - - const dsView = page.getByTestId('ds-view') - const items = dsView.locator('[data-testid^="ds-item-"]') - const count = await items.count() - expect(count).toBeGreaterThanOrEqual(1) - }) -}) - -test.describe('viewport overflow', () => { - test('page does not scroll beyond viewport after running reverse', async ({ page }) => { - await selectTemplate(page, 'singly-reverse') - - await page.getByTestId('btn-run').click() - await page.waitForTimeout(20_000) - - const bodyHeight = await page.evaluate(() => document.body.scrollHeight) - const viewportHeight = await page.evaluate(() => window.innerHeight) - expect(bodyHeight).toBeLessThanOrEqual(viewportHeight + 1) - }) -}) - -test.describe('hover interactions', () => { - test('hovering a DS item highlights the heap cell', async ({ page }) => { - await stepN(page, 15) - - const dsView = page.getByTestId('ds-view') - // Target a heap struct item (contains "ListNode"), not a stack pointer - const structItem = dsView.locator('[data-testid^="ds-item-"]').filter({ hasText: 'ListNode' }).first() - - const testId = await structItem.getAttribute('data-testid') - const address = testId?.replace('ds-item-', '') - - await structItem.hover() - await page.waitForTimeout(200) - - if (address) { - const heapCell = page.getByTestId(`heap-cell-${address}`) - const classes = await heapCell.getAttribute('class') - expect(classes).toContain('border-l-blue-400') - } - }) - - test('hovering a stack variable card highlights its declaration in Monaco', async ({ page }) => { - await stepN(page, 5) - - await page.waitForSelector('.view-overlays', { state: 'attached' }) - - const dataCard = page.locator('.cursor-pointer.border-l-3').filter({ hasText: 'data' }).filter({ hasText: 'int' }).first() - await expect(dataCard).toBeVisible() - - await dataCard.hover() - await page.waitForTimeout(200) - - const decoration = page.locator('.view-overlays .bg-cyan-500').first() - await expect(decoration).toBeAttached() - }) -}) - -test.describe('pointer arrows', () => { - // Skipped: kept as documentation for the "arrows stay at the previous view's - // coordinates after a KeepAlive toggle" regression. getBoundingClientRect - // isn't a Vue reactive dep, so ArrowOverlay's computed won't re-run on a - // plain mode swap — the fix is a MutationObserver on the host that bumps - // `tick` when the KeepAlive subtree changes. Re-enable if that regression - // resurfaces. - test.skip('arrows re-anchor to the active view after toggling Bytes/Allocations', async ({ page }) => { - await selectTemplate(page, 'doubly-insertBack') - await page.getByTestId('btn-run').click() - await page.waitForTimeout(3500) - - await page.getByRole('button', { name: 'Bytes' }).click() - await page.waitForTimeout(300) - const arrowsToggle = page.getByRole('button', { name: 'arrows' }) - await arrowsToggle.click() - await page.waitForTimeout(300) - - for (let i = 0; i < 4; i++) { - await page.getByRole('button', { name: 'Allocations' }).click() - await page.waitForTimeout(250) - await page.getByRole('button', { name: 'Bytes' }).click() - await page.waitForTimeout(250) - } - await page.getByRole('button', { name: 'Allocations' }).click() - await page.waitForTimeout(400) - - const check = await page.evaluate(() => { - const bezier = Array.from(document.querySelectorAll('svg path')) - .map(el => ({ el, d: el.getAttribute('d') ?? '' })) - .filter(({ d }) => /^M[\d.]+\s[\d.]+\sQ/.test(d)) - if (bezier.length === 0) - return { arrows: 0, bad: [] as { path: string, start: [number, number] }[] } - - const links = Array.from(document.querySelectorAll('[data-pointer-source]')) - .filter(el => el.offsetParent !== null) - .map(el => el.getBoundingClientRect()) - if (links.length === 0) - return { arrows: bezier.length, bad: [{ path: '(no AddressLinks visible)', start: [0, 0] as [number, number] }] } - - const tol = 4 - const bad: { path: string, start: [number, number] }[] = [] - for (const { el, d } of bezier) { - const m = d.match(/^M([\d.]+)\s([\d.]+)/) - if (!m) - continue - const svg = el.closest('svg')!.getBoundingClientRect() - const cx = svg.left + Number.parseFloat(m[1]) - const cy = svg.top + Number.parseFloat(m[2]) - const insideLink = links.some(r => - cx >= r.left - tol && cx <= r.right + tol - && cy >= r.top - tol && cy <= r.bottom + tol, - ) - if (!insideLink) - bad.push({ path: d, start: [Math.round(cx), Math.round(cy)] }) - } - return { arrows: bezier.length, bad } - }) - - expect(check.arrows).toBeGreaterThan(0) - expect(check.bad, `${check.bad.length} arrow(s) do not start at any AddressLink: ${JSON.stringify(check.bad, null, 2)}`).toEqual([]) - }) -}) - -test.describe('selection interactions', () => { - test('clicking different DS items changes selection', async ({ page }) => { - await stepN(page, 15) - - const dsView = page.getByTestId('ds-view') - - const firstItem = dsView.locator('[data-testid^="ds-item-"]').first() - await firstItem.click() - const fieldTable = page.getByTestId('field-table') - await expect(fieldTable).toBeVisible() - const firstText = await fieldTable.textContent() - - const secondItem = dsView.locator('[data-testid^="ds-item-"]').nth(1) - await secondItem.click() - await expect(fieldTable).toBeVisible() - const secondText = await fieldTable.textContent() - expect(secondText).not.toBe(firstText) - }) - - test('selection clears when simulation starts', async ({ page }) => { - await stepN(page, 15) - - const dsView = page.getByTestId('ds-view') - const firstItem = dsView.locator('[data-testid^="ds-item-"]').first() - await firstItem.click() - await expect(page.getByTestId('field-table')).toBeVisible() - - await page.getByTestId('btn-run').click() - await page.waitForTimeout(500) - await expect(page.getByTestId('field-table')).not.toBeVisible() - - await page.getByTestId('btn-pause').click() - }) - - test('DS item gets selected outline on click', async ({ page }) => { - await stepN(page, 15) - - const dsView = page.getByTestId('ds-view') - const firstItem = dsView.locator('[data-testid^="ds-item-"]').first() - await firstItem.click() - - await expect(firstItem).toHaveClass(/outline/) - }) -}) diff --git a/test/memory-map/overlay-geometry.test.ts b/test/memory-map/overlay-geometry.test.ts index ee3091c..1683960 100644 --- a/test/memory-map/overlay-geometry.test.ts +++ b/test/memory-map/overlay-geometry.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from 'vitest' import { allocationPath, allocationRects } from '../../src/components/MemoryMap/overlayGeometry' -const G = { bytesPerRow: 8, cellWidth: 32, rowHeight: 28, labelWidth: 62, regionStart: 0 } +const G = { bytesPerRow: 8, cellWidth: 32, rowHeight: 28, labelWidth: 62, xOffset: 0, regionStart: 0 } describe('allocationRects', () => { it('single row, aligned to column start', () => { @@ -10,6 +10,15 @@ describe('allocationRects', () => { ]) }) + it('honours xOffset when rows are centered', () => { + // A centered wrapper shifts rows by `xOffset` before the label column; + // every rect's x must shift by the same amount (width is unchanged). + const g = { ...G, xOffset: 20 } + expect(allocationRects(0, 4, g)).toEqual([ + { x: 20 + 62, y: 0, width: 128, height: 28 }, + ]) + }) + it('single row, mid-row start', () => { // base 12 → row 1 (12 / 8 = 1), col 4 (12 % 8 = 4) expect(allocationRects(12, 4, G)).toEqual([