From fc22ce6027aba3a55270e9643016b3b4df99eaee Mon Sep 17 00:00:00 2001 From: Chris Kruining Date: Tue, 25 Feb 2025 16:21:21 +1100 Subject: [PATCH] got to a stable point again. next up is comming up with a decent API for modifications --- .vscode/launch.json | 2 +- app.config.ts | 1 + bun.lock | 151 ++++++++++--- package.json | 17 +- src/components/textarea/textarea.tsx | 16 +- src/features/edit-context/index.ts | 3 - src/features/edit-context/tokenizer.ts | 194 ----------------- .../createEditor-should-create-1.png | Bin 0 -> 21680 bytes src/features/editor/context.spec.tsx | 87 ++++++++ .../{edit-context => editor}/context.ts | 201 +++++++----------- src/features/editor/editor.tsx | 20 ++ src/features/editor/index.tsx | 4 + src/features/editor/map.ts | 114 ++++++++++ src/features/source/source.spec.ts | 6 +- .../(editor)/experimental/formatter.tsx | 5 +- src/utilities.spec.ts | 40 +++- src/utilities.ts | 3 + tsconfig.json | 1 + vitest.config.ts | 8 +- 19 files changed, 498 insertions(+), 375 deletions(-) delete mode 100644 src/features/edit-context/index.ts delete mode 100644 src/features/edit-context/tokenizer.ts create mode 100644 src/features/editor/__screenshots__/context.spec.tsx/createEditor-should-create-1.png create mode 100644 src/features/editor/context.spec.tsx rename src/features/{edit-context => editor}/context.ts (57%) create mode 100644 src/features/editor/editor.tsx create mode 100644 src/features/editor/index.tsx create mode 100644 src/features/editor/map.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index 71c1b04..a6d750e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -56,7 +56,7 @@ // The arguments to pass to the `bun` executable, if any. // Unlike `args`, these are passed to the executable itself, not the program. "runtimeArgs": [ - "--bun", + "run", "test" ], }, diff --git a/app.config.ts b/app.config.ts index 0d91e94..6c28aef 100644 --- a/app.config.ts +++ b/app.config.ts @@ -1,6 +1,7 @@ import { defineConfig } from '@solidjs/start/config'; import solidSvg from 'vite-plugin-solid-svg'; import devtools from 'solid-devtools/vite'; +import { resolve } from 'node:path'; export default defineConfig({ vite: { diff --git a/bun.lock b/bun.lock index 2973470..5577395 100644 --- a/bun.lock +++ b/bun.lock @@ -5,6 +5,7 @@ "name": "calque", "dependencies": { "@solid-primitives/clipboard": "^1.6.0", + "@solid-primitives/context": "^0.3.0", "@solid-primitives/destructure": "^0.2.0", "@solid-primitives/event-listener": "^2.4.0", "@solid-primitives/i18n": "^2.2.0", @@ -27,7 +28,7 @@ "remark-stringify": "^11.0.0", "sitemap": "^8.0.0", "solid-icons": "^1.1.0", - "solid-js": "^1.9.4", + "solid-js": "^1.9.5", "ts-pattern": "^5.6.2", "unified": "^11.0.5", "unist-util-find": "^3.0.0", @@ -35,21 +36,23 @@ "vinxi": "^0.5.3", }, "devDependencies": { - "@happy-dom/global-registrator": "^17.1.1", + "@happy-dom/global-registrator": "^17.1.8", "@sinonjs/fake-timers": "^14.0.0", "@solidjs/testing-library": "^0.8.10", "@testing-library/jest-dom": "^6.6.3", "@testing-library/user-event": "^14.6.1", "@types/sinonjs__fake-timers": "^8.1.5", "@types/wicg-file-system-access": "^2023.10.5", - "@vitest/coverage-istanbul": "3.0.6", - "@vitest/coverage-v8": "3.0.6", - "bun-types": "^1.2.2", + "@vitest/browser": "^3.0.7", + "@vitest/coverage-istanbul": "3.0.7", + "@vitest/coverage-v8": "3.0.7", + "bun-types": "^1.2.3", "jsdom": "^26.0.0", + "playwright": "^1.50.1", "solid-devtools": "^0.33.0", "vite-plugin-solid": "^2.11.2", "vite-plugin-solid-svg": "^0.8.1", - "vitest": "^3.0.6", + "vitest": "^3.0.7", "workbox-window": "^7.3.0", }, }, @@ -103,6 +106,12 @@ "@bcoe/v8-coverage": ["@bcoe/v8-coverage@1.0.2", "", {}, "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA=="], + "@bundled-es-modules/cookie": ["@bundled-es-modules/cookie@2.0.1", "", { "dependencies": { "cookie": "^0.7.2" } }, "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw=="], + + "@bundled-es-modules/statuses": ["@bundled-es-modules/statuses@1.0.1", "", { "dependencies": { "statuses": "^2.0.1" } }, "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg=="], + + "@bundled-es-modules/tough-cookie": ["@bundled-es-modules/tough-cookie@0.1.6", "", { "dependencies": { "@types/tough-cookie": "^4.0.5", "tough-cookie": "^4.1.4" } }, "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw=="], + "@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.3.4", "", { "dependencies": { "mime": "^3.0.0" } }, "sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q=="], "@csstools/color-helpers": ["@csstools/color-helpers@5.0.1", "", {}, "sha512-MKtmkA0BX87PKaO1NFRTFH+UnkgnmySQOvNxJubsadusqPEC2aJ9MOQiMceZJJ6oitUl/i0L6u0M1IrmAOmgBA=="], @@ -169,7 +178,15 @@ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.20.2", "", { "os": "win32", "cpu": "x64" }, "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ=="], - "@happy-dom/global-registrator": ["@happy-dom/global-registrator@17.1.1", "", { "dependencies": { "happy-dom": "^17.1.1" } }, "sha512-if4TVRU4SnQwpOC9pN/a892nXPpctqER/rYIS9E/YsqwpaPANhMjFM7/+Ibd748gP6OuDJbspQ0axFrCscI1og=="], + "@happy-dom/global-registrator": ["@happy-dom/global-registrator@17.1.8", "", { "dependencies": { "happy-dom": "^17.1.8" } }, "sha512-8/INgMD5gqzhaGnRbcHvQ3cYa70ZbdUTMiCQg+4Pz22vogILU2Q1spnneunMVjAtx6DBRMO8rBnDeMREVVyADQ=="], + + "@inquirer/confirm": ["@inquirer/confirm@5.1.6", "", { "dependencies": { "@inquirer/core": "^10.1.7", "@inquirer/type": "^3.0.4" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-6ZXYK3M1XmaVBZX6FCfChgtponnL0R6I7k8Nu+kaoNkT828FVZTcca1MqmWQipaW2oNREQl5AaPCUOOCVNdRMw=="], + + "@inquirer/core": ["@inquirer/core@10.1.7", "", { "dependencies": { "@inquirer/figures": "^1.0.10", "@inquirer/type": "^3.0.4", "ansi-escapes": "^4.3.2", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-AA9CQhlrt6ZgiSy6qoAigiA1izOa751ugX6ioSjqgJ+/Gd+tEN/TORk5sUYNjXuHWfW0r1n/a6ak4u/NqHHrtA=="], + + "@inquirer/figures": ["@inquirer/figures@1.0.10", "", {}, "sha512-Ey6176gZmeqZuY/W/nZiUyvmb1/qInjcpiZjXWi6nON+nxJpD1bxtSoBxNliGISae32n6OwbY+TSXPZ1CfS4bw=="], + + "@inquirer/type": ["@inquirer/type@3.0.4", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-2MNFrDY8jkFYc9Il9DgLsHhMzuHnOYM1+CUYVWbzu9oT0hC7V7EcYvdCKeoll/Fcci04A+ERZ9wcc7cQ8lTkIA=="], "@ioredis/commands": ["@ioredis/commands@1.2.0", "", {}, "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg=="], @@ -193,6 +210,8 @@ "@mapbox/node-pre-gyp": ["@mapbox/node-pre-gyp@2.0.0", "", { "dependencies": { "consola": "^3.2.3", "detect-libc": "^2.0.0", "https-proxy-agent": "^7.0.5", "node-fetch": "^2.6.7", "nopt": "^8.0.0", "semver": "^7.5.3", "tar": "^7.4.0" }, "bin": { "node-pre-gyp": "bin/node-pre-gyp" } }, "sha512-llMXd39jtP0HpQLVI37Bf1m2ADlEb35GYSh1SDSLsBhR+5iCxiNGlT31yqbNtVHygHAtMy6dWFERpU2JgufhPg=="], + "@mswjs/interceptors": ["@mswjs/interceptors@0.37.6", "", { "dependencies": { "@open-draft/deferred-promise": "^2.2.0", "@open-draft/logger": "^0.3.0", "@open-draft/until": "^2.0.0", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "strict-event-emitter": "^0.5.1" } }, "sha512-wK+5pLK5XFmgtH3aQ2YVvA3HohS3xqV/OxuVOdNx9Wpnz7VE/fnC+e1A7ln6LFYeck7gOJ/dsZV6OLplOtAJ2w=="], + "@netlify/functions": ["@netlify/functions@2.8.2", "", { "dependencies": { "@netlify/serverless-functions-api": "1.26.1" } }, "sha512-DeoAQh8LuNPvBE4qsKlezjKj0PyXDryOFJfJKo3Z1qZLKzQ21sT314KQKPVjfvw6knqijj+IO+0kHXy/TJiqNA=="], "@netlify/node-cookies": ["@netlify/node-cookies@0.1.0", "", {}, "sha512-OAs1xG+FfLX0LoRASpqzVntVV/RpYkgpI0VrUnw2u0Q1qiZUzcPffxRK8HF3gc4GjuhG5ahOEMJ9bswBiZPq0g=="], @@ -207,6 +226,12 @@ "@nothing-but/utils": ["@nothing-but/utils@0.17.0", "", {}, "sha512-TuCHcHLOqDL0SnaAxACfuRHBNRgNJcNn9X0GiH5H3YSDBVquCr3qEIG3FOQAuMyZCbu9w8nk2CHhOsn7IvhIwQ=="], + "@open-draft/deferred-promise": ["@open-draft/deferred-promise@2.2.0", "", {}, "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA=="], + + "@open-draft/logger": ["@open-draft/logger@0.3.0", "", { "dependencies": { "is-node-process": "^1.2.0", "outvariant": "^1.4.0" } }, "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ=="], + + "@open-draft/until": ["@open-draft/until@2.1.0", "", {}, "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg=="], + "@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="], "@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.1", "", { "os": "android", "cpu": "arm64" }, "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA=="], @@ -239,6 +264,8 @@ "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], + "@polka/url": ["@polka/url@1.0.0-next.28", "", {}, "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw=="], + "@redocly/ajv": ["@redocly/ajv@8.11.2", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js-replace": "^1.0.1" } }, "sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg=="], "@redocly/config": ["@redocly/config@0.20.3", "", {}, "sha512-Nyyv1Bj7GgYwj/l46O0nkH1GTKWbO3Ixe7KFcn021aZipkZd+z8Vlu1BwkhqtVgivcKaClaExtWU/lDHkjBzag=="], @@ -327,6 +354,8 @@ "@solid-primitives/clipboard": ["@solid-primitives/clipboard@1.6.0", "", { "dependencies": { "@solid-primitives/utils": "^6.3.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-mZQVAqyXt1Cp9zZieGhKwSRMoNQg9z3ErqtnVxAxw5LAheAC09Z5OHr1Ln0kLjRDhC+r6GiNzOKzFVuTH+ERyQ=="], + "@solid-primitives/context": ["@solid-primitives/context@0.3.0", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-hVLWfZbXuz23gpJ+flCllbKidlIDCcSTOtlhSo9AhQ/vNiwvenLK8J4B2Hw2WCa4ETGPpQcNfgQHSNffEV5YeQ=="], + "@solid-primitives/cursor": ["@solid-primitives/cursor@0.0.115", "", { "dependencies": { "@solid-primitives/utils": "^6.2.3" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-8nEmUN/sacXPChwuJOAi6Yi6VnxthW/Jk8VGvvcF38AenjUvOA6FHI6AkJILuFXjQw1PGxia1YbH/Mn77dPiOA=="], "@solid-primitives/destructure": ["@solid-primitives/destructure@0.2.0", "", { "dependencies": { "@solid-primitives/utils": "^6.3.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-nfE6nSkyLle+hIQzvxGwzyt3TvFwgBjhFiQ7y2Cq+amBiwpvVVm+1qncE8tKaKk6JNn/CilgXZgJ/KMb/p3csA=="], @@ -397,6 +426,8 @@ "@types/braces": ["@types/braces@3.0.5", "", {}, "sha512-SQFof9H+LXeWNz8wDe7oN5zu7ket0qwMu5vZubW4GCJ8Kkeh6nBWUz87+KTz/G3Kqsrp0j/W253XJb3KMEeg3w=="], + "@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="], + "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], "@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], @@ -421,6 +452,10 @@ "@types/sinonjs__fake-timers": ["@types/sinonjs__fake-timers@8.1.5", "", {}, "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ=="], + "@types/statuses": ["@types/statuses@2.0.5", "", {}, "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A=="], + + "@types/tough-cookie": ["@types/tough-cookie@4.0.5", "", {}, "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="], + "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="], "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], @@ -439,23 +474,25 @@ "@vinxi/server-components": ["@vinxi/server-components@0.5.0", "", { "dependencies": { "@vinxi/plugin-directives": "0.5.0", "acorn": "^8.10.0", "acorn-loose": "^8.3.0", "acorn-typescript": "^1.4.3", "astring": "^1.8.6", "magicast": "^0.2.10", "recast": "^0.23.4" }, "peerDependencies": { "vinxi": "^0.5.0" } }, "sha512-2p6ZYzoqF7ZAriU0rC9KJWSX/n5qHhUBs7x04SLYzmy9lFxQNw3YHsmsA4b3aHDU+Mxw26wyFwvIbrL6eU3Gyw=="], - "@vitest/coverage-istanbul": ["@vitest/coverage-istanbul@3.0.6", "", { "dependencies": { "@istanbuljs/schema": "^0.1.3", "debug": "^4.4.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-instrument": "^6.0.3", "istanbul-lib-report": "^3.0.1", "istanbul-lib-source-maps": "^5.0.6", "istanbul-reports": "^3.1.7", "magicast": "^0.3.5", "test-exclude": "^7.0.1", "tinyrainbow": "^2.0.0" }, "peerDependencies": { "vitest": "3.0.6" } }, "sha512-e+8HkmVlPpqOZXIWGE8opxex3trTMCeCMHax7yG0JbWOtGRVKBjuNS/GGA/eta89LuXUrCIcQrRfJHLUrWl7Wg=="], + "@vitest/browser": ["@vitest/browser@3.0.7", "", { "dependencies": { "@testing-library/dom": "^10.4.0", "@testing-library/user-event": "^14.6.1", "@vitest/mocker": "3.0.7", "@vitest/utils": "3.0.7", "magic-string": "^0.30.17", "msw": "^2.7.3", "sirv": "^3.0.1", "tinyrainbow": "^2.0.0", "ws": "^8.18.1" }, "peerDependencies": { "playwright": "*", "vitest": "3.0.7", "webdriverio": "^7.0.0 || ^8.0.0 || ^9.0.0" }, "optionalPeers": ["playwright", "webdriverio"] }, "sha512-TDzZtnbe37KZLSLhvlO1pUkeRSRzW3rOhPLsshX8agGoPELMlG7EvS4z9GfsdaCxsP7oWLBJpFjNJwLS458Bzg=="], - "@vitest/coverage-v8": ["@vitest/coverage-v8@3.0.6", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^1.0.2", "debug": "^4.4.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-lib-source-maps": "^5.0.6", "istanbul-reports": "^3.1.7", "magic-string": "^0.30.17", "magicast": "^0.3.5", "std-env": "^3.8.0", "test-exclude": "^7.0.1", "tinyrainbow": "^2.0.0" }, "peerDependencies": { "@vitest/browser": "3.0.6", "vitest": "3.0.6" }, "optionalPeers": ["@vitest/browser"] }, "sha512-JRTlR8Bw+4BcmVTICa7tJsxqphAktakiLsAmibVLAWbu1lauFddY/tXeM6sAyl1cgkPuXtpnUgaCPhTdz1Qapg=="], + "@vitest/coverage-istanbul": ["@vitest/coverage-istanbul@3.0.7", "", { "dependencies": { "@istanbuljs/schema": "^0.1.3", "debug": "^4.4.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-instrument": "^6.0.3", "istanbul-lib-report": "^3.0.1", "istanbul-lib-source-maps": "^5.0.6", "istanbul-reports": "^3.1.7", "magicast": "^0.3.5", "test-exclude": "^7.0.1", "tinyrainbow": "^2.0.0" }, "peerDependencies": { "vitest": "3.0.7" } }, "sha512-hkd7rlfnqQJFlg6IPv9aFNaxJNkWLasdfaMJR3MBsBkxddSYy5ax9sW6Vv1/3tmmyT9m/b0lHDNknybKJ33cXw=="], - "@vitest/expect": ["@vitest/expect@3.0.6", "", { "dependencies": { "@vitest/spy": "3.0.6", "@vitest/utils": "3.0.6", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-zBduHf/ja7/QRX4HdP1DSq5XrPgdN+jzLOwaTq/0qZjYfgETNFCKf9nOAp2j3hmom3oTbczuUzrzg9Hafh7hNg=="], + "@vitest/coverage-v8": ["@vitest/coverage-v8@3.0.7", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^1.0.2", "debug": "^4.4.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-lib-source-maps": "^5.0.6", "istanbul-reports": "^3.1.7", "magic-string": "^0.30.17", "magicast": "^0.3.5", "std-env": "^3.8.0", "test-exclude": "^7.0.1", "tinyrainbow": "^2.0.0" }, "peerDependencies": { "@vitest/browser": "3.0.7", "vitest": "3.0.7" }, "optionalPeers": ["@vitest/browser"] }, "sha512-Av8WgBJLTrfLOer0uy3CxjlVuWK4CzcLBndW1Nm2vI+3hZ2ozHututkfc7Blu1u6waeQ7J8gzPK/AsBRnWA5mQ=="], - "@vitest/mocker": ["@vitest/mocker@3.0.6", "", { "dependencies": { "@vitest/spy": "3.0.6", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-KPztr4/tn7qDGZfqlSPQoF2VgJcKxnDNhmfR3VgZ6Fy1bO8T9Fc1stUiTXtqz0yG24VpD00pZP5f8EOFknjNuQ=="], + "@vitest/expect": ["@vitest/expect@3.0.7", "", { "dependencies": { "@vitest/spy": "3.0.7", "@vitest/utils": "3.0.7", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-QP25f+YJhzPfHrHfYHtvRn+uvkCFCqFtW9CktfBxmB+25QqWsx7VB2As6f4GmwllHLDhXNHvqedwhvMmSnNmjw=="], - "@vitest/pretty-format": ["@vitest/pretty-format@3.0.6", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-Zyctv3dbNL+67qtHfRnUE/k8qxduOamRfAL1BurEIQSyOEFffoMvx2pnDSSbKAAVxY0Ej2J/GH2dQKI0W2JyVg=="], + "@vitest/mocker": ["@vitest/mocker@3.0.7", "", { "dependencies": { "@vitest/spy": "3.0.7", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-qui+3BLz9Eonx4EAuR/i+QlCX6AUZ35taDQgwGkK/Tw6/WgwodSrjN1X2xf69IA/643ZX5zNKIn2svvtZDrs4w=="], - "@vitest/runner": ["@vitest/runner@3.0.6", "", { "dependencies": { "@vitest/utils": "3.0.6", "pathe": "^2.0.3" } }, "sha512-JopP4m/jGoaG1+CBqubV/5VMbi7L+NQCJTu1J1Pf6YaUbk7bZtaq5CX7p+8sY64Sjn1UQ1XJparHfcvTTdu9cA=="], + "@vitest/pretty-format": ["@vitest/pretty-format@3.0.7", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-CiRY0BViD/V8uwuEzz9Yapyao+M9M008/9oMOSQydwbwb+CMokEq3XVaF3XK/VWaOK0Jm9z7ENhybg70Gtxsmg=="], - "@vitest/snapshot": ["@vitest/snapshot@3.0.6", "", { "dependencies": { "@vitest/pretty-format": "3.0.6", "magic-string": "^0.30.17", "pathe": "^2.0.3" } }, "sha512-qKSmxNQwT60kNwwJHMVwavvZsMGXWmngD023OHSgn873pV0lylK7dwBTfYP7e4URy5NiBCHHiQGA9DHkYkqRqg=="], + "@vitest/runner": ["@vitest/runner@3.0.7", "", { "dependencies": { "@vitest/utils": "3.0.7", "pathe": "^2.0.3" } }, "sha512-WeEl38Z0S2ZcuRTeyYqaZtm4e26tq6ZFqh5y8YD9YxfWuu0OFiGFUbnxNynwLjNRHPsXyee2M9tV7YxOTPZl2g=="], - "@vitest/spy": ["@vitest/spy@3.0.6", "", { "dependencies": { "tinyspy": "^3.0.2" } }, "sha512-HfOGx/bXtjy24fDlTOpgiAEJbRfFxoX3zIGagCqACkFKKZ/TTOE6gYMKXlqecvxEndKFuNHcHqP081ggZ2yM0Q=="], + "@vitest/snapshot": ["@vitest/snapshot@3.0.7", "", { "dependencies": { "@vitest/pretty-format": "3.0.7", "magic-string": "^0.30.17", "pathe": "^2.0.3" } }, "sha512-eqTUryJWQN0Rtf5yqCGTQWsCFOQe4eNz5Twsu21xYEcnFJtMU5XvmG0vgebhdLlrHQTSq5p8vWHJIeJQV8ovsA=="], - "@vitest/utils": ["@vitest/utils@3.0.6", "", { "dependencies": { "@vitest/pretty-format": "3.0.6", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" } }, "sha512-18ktZpf4GQFTbf9jK543uspU03Q2qya7ZGya5yiZ0Gx0nnnalBvd5ZBislbl2EhLjM8A8rt4OilqKG7QwcGkvQ=="], + "@vitest/spy": ["@vitest/spy@3.0.7", "", { "dependencies": { "tinyspy": "^3.0.2" } }, "sha512-4T4WcsibB0B6hrKdAZTM37ekuyFZt2cGbEGd2+L0P8ov15J1/HUsUaqkXEQPNAWr4BtPPe1gI+FYfMHhEKfR8w=="], + + "@vitest/utils": ["@vitest/utils@3.0.7", "", { "dependencies": { "@vitest/pretty-format": "3.0.7", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" } }, "sha512-xePVpCRfooFX3rANQjwoditoXgWb1MaFbzmGuPP59MK6i13mrnDw/yEIyJudLeW6/38mCNcwCiJIGmpDPibAIg=="], "abbrev": ["abbrev@3.0.0", "", {}, "sha512-+/kfrslGQ7TNV2ecmQwMJj/B65g5KVq1/L3SGVZ3tCYGqlzFuFCGBZJtMP99wH3NpEUyAjn0zPdPUg0D+DwrOA=="], @@ -477,6 +514,8 @@ "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], + "ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="], + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], @@ -543,7 +582,7 @@ "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], - "bun-types": ["bun-types@1.2.2", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-RCbMH5elr9gjgDGDhkTTugA21XtJAy/9jkKe/G3WR2q17VPGhcquf9Sir6uay9iW+7P/BV0CAHA1XlHXMAVKHg=="], + "bun-types": ["bun-types@1.2.3", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-P7AeyTseLKAvgaZqQrvp3RqFM3yN9PlcLuSTe7SoJOfZkER73mLdT2vEQi8U64S1YvM/ldcNiQjn0Sn7H9lGgg=="], "c12": ["c12@2.0.1", "", { "dependencies": { "chokidar": "^4.0.1", "confbox": "^0.1.7", "defu": "^6.1.4", "dotenv": "^16.4.5", "giget": "^1.2.3", "jiti": "^2.3.0", "mlly": "^1.7.1", "ohash": "^1.1.4", "pathe": "^1.1.2", "perfect-debounce": "^1.0.0", "pkg-types": "^1.2.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-Z4JgsKXHG37C6PYUtIxCfLJZvo6FyhHJoClwwb9ftUkLpPSkuYqn6Tr+vnaN8hymm0kIbcg6Ey3kv/Q71k5w/A=="], @@ -577,6 +616,8 @@ "cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="], + "cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="], + "clipboardy": ["clipboardy@4.0.0", "", { "dependencies": { "execa": "^8.0.1", "is-wsl": "^3.1.0", "is64bit": "^2.0.0" } }, "sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w=="], "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], @@ -609,6 +650,8 @@ "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + "cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], + "cookie-es": ["cookie-es@1.2.2", "", {}, "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg=="], "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], @@ -769,7 +812,7 @@ "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], - "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + "fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], @@ -793,11 +836,13 @@ "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + "graphql": ["graphql@16.10.0", "", {}, "sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ=="], + "gzip-size": ["gzip-size@7.0.0", "", { "dependencies": { "duplexer": "^0.1.2" } }, "sha512-O1Ld7Dr+nqPnmGpdhzLmMTQ4vAsD+rHwMm1NLUmoUFFymBOMKxCCrtDxqdBRYXdeEPEi3SyoR4TizJLQrnKBNA=="], "h3": ["h3@1.13.0", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": ">=0.2.0 <0.4.0", "defu": "^6.1.4", "destr": "^2.0.3", "iron-webcrypto": "^1.2.1", "ohash": "^1.1.4", "radix3": "^1.1.2", "ufo": "^1.5.4", "uncrypto": "^0.1.3", "unenv": "^1.10.0" } }, "sha512-vFEAu/yf8UMUcB4s43OaDaigcqpQd14yanmOsn+NcRX3/guSKncyE2rOYhq8RIchgJrPSs/QiIddnTTR1ddiAg=="], - "happy-dom": ["happy-dom@17.1.1", "", { "dependencies": { "webidl-conversions": "^7.0.0", "whatwg-mimetype": "^3.0.0" } }, "sha512-OSTkBlmD/6Do7gCd7nZB5iFq1bF9VQg/iFmjHmxvVX2S1UiOpo6sT+aFNnu3XUsB8hCZb9+GZ0G1g1TaMiAggw=="], + "happy-dom": ["happy-dom@17.1.8", "", { "dependencies": { "webidl-conversions": "^7.0.0", "whatwg-mimetype": "^3.0.0" } }, "sha512-Yxbq/FG79z1rhAf/iB6YM8wO2JB/JDQBy99RiLSs+2siEAi5J05x9eW1nnASHZJbpldjJE2KuFLsLZ+AzX/IxA=="], "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], @@ -833,6 +878,8 @@ "hastscript": ["hastscript@9.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-jzaLBGavEDKHrc5EfFImKN7nZKKBdSLIdGvCwDZ9TfzbF2ffXiov8CKE445L2Z1Ek2t/m4SKQ2j6Ipv7NyUolw=="], + "headers-polyfill": ["headers-polyfill@4.0.3", "", {}, "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ=="], + "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], "html-encoding-sniffer": ["html-encoding-sniffer@4.0.0", "", { "dependencies": { "whatwg-encoding": "^3.1.1" } }, "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ=="], @@ -893,6 +940,8 @@ "is-module": ["is-module@1.0.0", "", {}, "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="], + "is-node-process": ["is-node-process@1.2.0", "", {}, "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw=="], + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], @@ -1059,8 +1108,14 @@ "mlly": ["mlly@1.7.4", "", { "dependencies": { "acorn": "^8.14.0", "pathe": "^2.0.1", "pkg-types": "^1.3.0", "ufo": "^1.5.4" } }, "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw=="], + "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + "msw": ["msw@2.7.3", "", { "dependencies": { "@bundled-es-modules/cookie": "^2.0.1", "@bundled-es-modules/statuses": "^1.0.1", "@bundled-es-modules/tough-cookie": "^0.1.6", "@inquirer/confirm": "^5.0.0", "@mswjs/interceptors": "^0.37.0", "@open-draft/deferred-promise": "^2.2.0", "@open-draft/until": "^2.1.0", "@types/cookie": "^0.6.0", "@types/statuses": "^2.0.4", "graphql": "^16.8.1", "headers-polyfill": "^4.0.2", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", "strict-event-emitter": "^0.5.1", "type-fest": "^4.26.1", "yargs": "^17.7.2" }, "peerDependencies": { "typescript": ">= 4.8.x" }, "optionalPeers": ["typescript"], "bin": { "msw": "cli/index.js" } }, "sha512-+mycXv8l2fEAjFZ5sjrtjJDmm2ceKGjrNbBr1durRg6VkU9fNUE/gsmQ51hWbHqs+l35W1iM+ZsmOD9Fd6lspw=="], + + "mute-stream": ["mute-stream@2.0.0", "", {}, "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA=="], + "nanoid": ["nanoid@3.3.8", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w=="], "nitropack": ["nitropack@2.10.4", "", { "dependencies": { "@cloudflare/kv-asset-handler": "^0.3.4", "@netlify/functions": "^2.8.2", "@rollup/plugin-alias": "^5.1.1", "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-inject": "^5.0.5", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^15.3.0", "@rollup/plugin-replace": "^6.0.1", "@rollup/plugin-terser": "^0.4.4", "@rollup/pluginutils": "^5.1.3", "@types/http-proxy": "^1.17.15", "@vercel/nft": "^0.27.5", "archiver": "^7.0.1", "c12": "2.0.1", "chokidar": "^3.6.0", "citty": "^0.1.6", "compatx": "^0.1.8", "confbox": "^0.1.8", "consola": "^3.2.3", "cookie-es": "^1.2.2", "croner": "^9.0.0", "crossws": "^0.3.1", "db0": "^0.2.1", "defu": "^6.1.4", "destr": "^2.0.3", "dot-prop": "^9.0.0", "esbuild": "^0.24.0", "escape-string-regexp": "^5.0.0", "etag": "^1.8.1", "fs-extra": "^11.2.0", "globby": "^14.0.2", "gzip-size": "^7.0.0", "h3": "^1.13.0", "hookable": "^5.5.3", "httpxy": "^0.1.5", "ioredis": "^5.4.1", "jiti": "^2.4.0", "klona": "^2.0.6", "knitwork": "^1.1.0", "listhen": "^1.9.0", "magic-string": "^0.30.12", "magicast": "^0.3.5", "mime": "^4.0.4", "mlly": "^1.7.2", "node-fetch-native": "^1.6.4", "ofetch": "^1.4.1", "ohash": "^1.1.4", "openapi-typescript": "^7.4.2", "pathe": "^1.1.2", "perfect-debounce": "^1.0.0", "pkg-types": "^1.2.1", "pretty-bytes": "^6.1.1", "radix3": "^1.1.2", "rollup": "^4.24.3", "rollup-plugin-visualizer": "^5.12.0", "scule": "^1.3.0", "semver": "^7.6.3", "serve-placeholder": "^2.0.2", "serve-static": "^1.16.2", "std-env": "^3.7.0", "ufo": "^1.5.4", "uncrypto": "^0.1.3", "unctx": "^2.3.1", "unenv": "^1.10.0", "unimport": "^3.13.1", "unstorage": "^1.13.1", "untyped": "^1.5.1", "unwasm": "^0.3.9" }, "peerDependencies": { "xml2js": "^0.6.2" }, "optionalPeers": ["xml2js"], "bin": { "nitro": "dist/cli/index.mjs", "nitropack": "dist/cli/index.mjs" } }, "sha512-sJiG/MIQlZCVSw2cQrFG1H6mLeSqHlYfFerRjLKz69vUfdu0EL2l0WdOxlQbzJr3mMv/l4cOlCCLzVRzjzzF/g=="], @@ -1105,6 +1160,8 @@ "openapi-typescript": ["openapi-typescript@7.6.1", "", { "dependencies": { "@redocly/openapi-core": "^1.28.0", "ansi-colors": "^4.1.3", "change-case": "^5.4.4", "parse-json": "^8.1.0", "supports-color": "^9.4.0", "yargs-parser": "^21.1.1" }, "peerDependencies": { "typescript": "^5.x" }, "bin": { "openapi-typescript": "bin/cli.js" } }, "sha512-F7RXEeo/heF3O9lOXo2bNjCOtfp7u+D6W3a3VNEH2xE6v+fxLtn5nq0uvUcA1F5aT+CMhNeC5Uqtg5tlXFX/ag=="], + "outvariant": ["outvariant@1.4.3", "", {}, "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA=="], + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], "parse-json": ["parse-json@8.1.0", "", { "dependencies": { "@babel/code-frame": "^7.22.13", "index-to-position": "^0.1.2", "type-fest": "^4.7.1" } }, "sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA=="], @@ -1137,6 +1194,10 @@ "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], + "playwright": ["playwright@1.50.1", "", { "dependencies": { "playwright-core": "1.50.1" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw=="], + + "playwright-core": ["playwright-core@1.50.1", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ=="], + "pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="], "postcss": ["postcss@8.5.2", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA=="], @@ -1151,8 +1212,12 @@ "property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="], + "psl": ["psl@1.15.0", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w=="], + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + "querystringify": ["querystringify@2.2.0", "", {}, "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="], + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], "radix3": ["radix3@1.1.2", "", {}, "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA=="], @@ -1261,6 +1326,8 @@ "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + "sirv": ["sirv@3.0.1", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A=="], + "sitemap": ["sitemap@8.0.0", "", { "dependencies": { "@types/node": "^17.0.5", "@types/sax": "^1.2.1", "arg": "^5.0.0", "sax": "^1.2.4" }, "bin": { "sitemap": "dist/cli.js" } }, "sha512-+AbdxhM9kJsHtruUF39bwS/B0Fytw6Fr1o4ZAIAEqA6cke2xcoO2GleBw9Zw7nRzILVEgz7zBM5GiTJjie1G9A=="], "slash": ["slash@5.1.0", "", {}, "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg=="], @@ -1271,7 +1338,7 @@ "solid-icons": ["solid-icons@1.1.0", "", { "peerDependencies": { "solid-js": "*" } }, "sha512-IesTfr/F1ElVwH2E1110s2RPXH4pujKfSs+koT8rwuTAdleO5s26lNSpqJV7D1+QHooJj18mcOiz2PIKs0ic+A=="], - "solid-js": ["solid-js@1.9.4", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "^1.1.0", "seroval-plugins": "^1.1.0" } }, "sha512-ipQl8FJ31bFUoBNScDQTG3BjN6+9Rg+Q+f10bUbnO6EOTTf5NGerJeHc7wyu5I4RMHEl/WwZwUmy/PTRgxxZ8g=="], + "solid-js": ["solid-js@1.9.5", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "^1.1.0", "seroval-plugins": "^1.1.0" } }, "sha512-ogI3DaFcyn6UhYhrgcyRAMbu/buBJitYQASZz5WzfQVPP10RD2AbCoRZ517psnezrasyCbWzIxZ6kVqet768xw=="], "solid-refresh": ["solid-refresh@0.6.3", "", { "dependencies": { "@babel/generator": "^7.23.6", "@babel/helper-module-imports": "^7.22.15", "@babel/types": "^7.23.6" }, "peerDependencies": { "solid-js": "^1.3" } }, "sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA=="], @@ -1297,6 +1364,8 @@ "streamx": ["streamx@2.22.0", "", { "dependencies": { "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" }, "optionalDependencies": { "bare-events": "^2.2.0" } }, "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw=="], + "strict-event-emitter": ["strict-event-emitter@0.5.1", "", {}, "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ=="], + "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=="], "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], @@ -1359,6 +1428,8 @@ "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], + "totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="], + "tough-cookie": ["tough-cookie@5.1.1", "", { "dependencies": { "tldts": "^6.1.32" } }, "sha512-Ek7HndSVkp10hmHP9V4qZO1u+pn1RU5sI0Fw+jCU3lyvuMZcgqsNgc6CmJJZyByK4Vm/qotGRJlfgAX8q+4JiA=="], "tr46": ["tr46@5.0.0", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g=="], @@ -1375,7 +1446,7 @@ "type-detect": ["type-detect@4.0.8", "", {}, "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="], - "type-fest": ["type-fest@2.19.0", "", {}, "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA=="], + "type-fest": ["type-fest@4.34.1", "", {}, "sha512-6kSc32kT0rbwxD6QL1CYe8IqdzN/J/ILMrNK+HMQCKH3insCDRY/3ITb0vcBss0a3t72fzh2YSzj8ko1HgwT3g=="], "typescript": ["typescript@5.7.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw=="], @@ -1427,6 +1498,8 @@ "uri-js-replace": ["uri-js-replace@1.0.1", "", {}, "sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g=="], + "url-parse": ["url-parse@1.5.10", "", { "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ=="], + "urlpattern-polyfill": ["urlpattern-polyfill@8.0.2", "", {}, "sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ=="], "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], @@ -1443,7 +1516,7 @@ "vite": ["vite@6.1.0", "", { "dependencies": { "esbuild": "^0.24.2", "postcss": "^8.5.1", "rollup": "^4.30.1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ=="], - "vite-node": ["vite-node@3.0.6", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.6.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-s51RzrTkXKJrhNbUzQRsarjmAae7VmMPAsRT7lppVpIg6mK3zGthP9Hgz0YQQKuNcF+Ii7DfYk3Fxz40jRmePw=="], + "vite-node": ["vite-node@3.0.7", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.6.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-2fX0QwX4GkkkpULXdT1Pf4q0tC1i1lFOyseKoonavXUNlQ77KpW2XqBGGNIm/J4Ows4KxgGJzDguYVPKwG/n5A=="], "vite-plugin-solid": ["vite-plugin-solid@2.11.2", "", { "dependencies": { "@babel/core": "^7.23.3", "@types/babel__core": "^7.20.4", "babel-preset-solid": "^1.8.4", "merge-anything": "^5.1.7", "solid-refresh": "^0.6.3", "vitefu": "^1.0.4" }, "peerDependencies": { "@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*", "solid-js": "^1.7.2", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-/OXVasW5OIRSFXnqzMgm8X3hPvf+JTbGecjQhmk7QnbDFq4hqdLssuYAWw9GsJGfzUPiMHM3ME2Y2XHPsTWmkw=="], @@ -1451,7 +1524,7 @@ "vitefu": ["vitefu@1.0.5", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["vite"] }, "sha512-h4Vflt9gxODPFNGPwp4zAMZRpZR7eslzwH2c5hn5kNZ5rhnKyRJ50U+yGCdc2IRaBs8O4haIgLNGrV5CrpMsCA=="], - "vitest": ["vitest@3.0.6", "", { "dependencies": { "@vitest/expect": "3.0.6", "@vitest/mocker": "3.0.6", "@vitest/pretty-format": "^3.0.6", "@vitest/runner": "3.0.6", "@vitest/snapshot": "3.0.6", "@vitest/spy": "3.0.6", "@vitest/utils": "3.0.6", "chai": "^5.2.0", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", "pathe": "^2.0.3", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", "vite-node": "3.0.6", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.0.6", "@vitest/ui": "3.0.6", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-/iL1Sc5VeDZKPDe58oGK4HUFLhw6b5XdY1MYawjuSaDA4sEfYlY9HnS6aCEG26fX+MgUi7MwlduTBHHAI/OvMA=="], + "vitest": ["vitest@3.0.7", "", { "dependencies": { "@vitest/expect": "3.0.7", "@vitest/mocker": "3.0.7", "@vitest/pretty-format": "^3.0.7", "@vitest/runner": "3.0.7", "@vitest/snapshot": "3.0.7", "@vitest/spy": "3.0.7", "@vitest/utils": "3.0.7", "chai": "^5.2.0", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", "pathe": "^2.0.3", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", "vite-node": "3.0.7", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.0.7", "@vitest/ui": "3.0.7", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-IP7gPK3LS3Fvn44x30X1dM9vtawm0aesAa2yBIZ9vQf+qB69NXC5776+Qmcr7ohUXIQuLhk7xQR0aSUIDPqavg=="], "w3c-xmlserializer": ["w3c-xmlserializer@5.0.0", "", { "dependencies": { "xml-name-validator": "^5.0.0" } }, "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA=="], @@ -1483,7 +1556,7 @@ "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - "ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + "ws": ["ws@8.18.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w=="], "xml-name-validator": ["xml-name-validator@5.0.0", "", {}, "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg=="], @@ -1499,6 +1572,8 @@ "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + "yoctocolors-cjs": ["yoctocolors-cjs@2.1.2", "", {}, "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA=="], + "zip-stream": ["zip-stream@6.0.1", "", { "dependencies": { "archiver-utils": "^5.0.0", "compress-commons": "^6.0.2", "readable-stream": "^4.0.0" } }, "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA=="], "zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="], @@ -1511,8 +1586,12 @@ "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "@bundled-es-modules/tough-cookie/tough-cookie": ["tough-cookie@4.1.4", "", { "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", "universalify": "^0.2.0", "url-parse": "^1.5.3" } }, "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag=="], + "@cloudflare/kv-asset-handler/mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="], + "@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], + "@mapbox/node-pre-gyp/detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], "@parcel/watcher-wasm/napi-wasm": ["napi-wasm@1.1.3", "", { "bundled": true }, "sha512-h/4nMGsHjZDCYmQVNODIrYACVJ+I9KItbG+0si6W/jSjdA9JbWDoU4LLeMXVcEQGHjttI2tuXqDrbGF7qkUHHg=="], @@ -1547,6 +1626,8 @@ "ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="], + "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "archiver-utils/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], @@ -1555,12 +1636,16 @@ "boxen/chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="], + "boxen/type-fest": ["type-fest@2.19.0", "", {}, "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA=="], + "c12/chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], "c12/jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="], "c12/pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], + "chokidar/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + "cliui/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], @@ -1575,8 +1660,6 @@ "dax-sh/undici-types": ["undici-types@5.28.4", "", {}, "sha512-3OeMF5Lyowe8VW0skf5qaIE7Or3yS9LS7fvMUI0gg4YxpIBVg0L8BxCmROw2CcYhSkpR68Epz7CGc8MPj94Uww=="], - "dot-prop/type-fest": ["type-fest@4.34.1", "", {}, "sha512-6kSc32kT0rbwxD6QL1CYe8IqdzN/J/ILMrNK+HMQCKH3insCDRY/3ITb0vcBss0a3t72fzh2YSzj8ko1HgwT3g=="], - "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], "giget/pathe": ["pathe@2.0.2", "", {}, "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w=="], @@ -1589,6 +1672,8 @@ "is-inside-container/is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], + "jsdom/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + "lazystream/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], "listhen/@parcel/watcher-wasm": ["@parcel/watcher-wasm@2.5.1", "", { "dependencies": { "is-glob": "^4.0.3", "micromatch": "^4.0.5", "napi-wasm": "^1.1.0" } }, "sha512-RJxlQQLkaMMIuWRozy+z2vEqbaQlCuaCgVZIUCzQLYggY22LZbP5Y1+ia+FD724Ids9e+XIyOLXLrLgQSHIthw=="], @@ -1617,8 +1702,6 @@ "openapi-typescript/supports-color": ["supports-color@9.4.0", "", {}, "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw=="], - "parse-json/type-fest": ["type-fest@4.34.1", "", {}, "sha512-6kSc32kT0rbwxD6QL1CYe8IqdzN/J/ILMrNK+HMQCKH3insCDRY/3ITb0vcBss0a3t72fzh2YSzj8ko1HgwT3g=="], - "pkg-types/pathe": ["pathe@2.0.2", "", {}, "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w=="], "pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], @@ -1627,6 +1710,8 @@ "readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "rollup/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + "rollup-plugin-visualizer/source-map": ["source-map@0.7.4", "", {}, "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA=="], "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -1669,6 +1754,8 @@ "vite/esbuild": ["esbuild@0.24.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.24.2", "@esbuild/android-arm": "0.24.2", "@esbuild/android-arm64": "0.24.2", "@esbuild/android-x64": "0.24.2", "@esbuild/darwin-arm64": "0.24.2", "@esbuild/darwin-x64": "0.24.2", "@esbuild/freebsd-arm64": "0.24.2", "@esbuild/freebsd-x64": "0.24.2", "@esbuild/linux-arm": "0.24.2", "@esbuild/linux-arm64": "0.24.2", "@esbuild/linux-ia32": "0.24.2", "@esbuild/linux-loong64": "0.24.2", "@esbuild/linux-mips64el": "0.24.2", "@esbuild/linux-ppc64": "0.24.2", "@esbuild/linux-riscv64": "0.24.2", "@esbuild/linux-s390x": "0.24.2", "@esbuild/linux-x64": "0.24.2", "@esbuild/netbsd-arm64": "0.24.2", "@esbuild/netbsd-x64": "0.24.2", "@esbuild/openbsd-arm64": "0.24.2", "@esbuild/openbsd-x64": "0.24.2", "@esbuild/sunos-x64": "0.24.2", "@esbuild/win32-arm64": "0.24.2", "@esbuild/win32-ia32": "0.24.2", "@esbuild/win32-x64": "0.24.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA=="], + "vite/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + "wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], @@ -1677,6 +1764,12 @@ "yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "@bundled-es-modules/tough-cookie/tough-cookie/universalify": ["universalify@0.2.0", "", {}, "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg=="], + + "@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "@inquirer/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "@vercel/nft/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], "ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -1813,6 +1906,8 @@ "yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "@vercel/nft/glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], "giget/tar/minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], diff --git a/package.json b/package.json index d8ac624..ae5ab32 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ }, "dependencies": { "@solid-primitives/clipboard": "^1.6.0", + "@solid-primitives/context": "^0.3.0", "@solid-primitives/destructure": "^0.2.0", "@solid-primitives/event-listener": "^2.4.0", "@solid-primitives/i18n": "^2.2.0", @@ -29,7 +30,7 @@ "remark-stringify": "^11.0.0", "sitemap": "^8.0.0", "solid-icons": "^1.1.0", - "solid-js": "^1.9.4", + "solid-js": "^1.9.5", "ts-pattern": "^5.6.2", "unified": "^11.0.5", "unist-util-find": "^3.0.0", @@ -37,21 +38,23 @@ "vinxi": "^0.5.3" }, "devDependencies": { - "@happy-dom/global-registrator": "^17.1.1", + "@happy-dom/global-registrator": "^17.1.8", "@sinonjs/fake-timers": "^14.0.0", "@solidjs/testing-library": "^0.8.10", "@testing-library/jest-dom": "^6.6.3", "@testing-library/user-event": "^14.6.1", "@types/sinonjs__fake-timers": "^8.1.5", "@types/wicg-file-system-access": "^2023.10.5", - "@vitest/coverage-istanbul": "3.0.6", - "@vitest/coverage-v8": "3.0.6", - "bun-types": "^1.2.2", + "@vitest/browser": "^3.0.7", + "@vitest/coverage-istanbul": "3.0.7", + "@vitest/coverage-v8": "3.0.7", + "bun-types": "^1.2.3", "jsdom": "^26.0.0", + "playwright": "^1.50.1", "solid-devtools": "^0.33.0", "vite-plugin-solid": "^2.11.2", "vite-plugin-solid-svg": "^0.8.1", - "vitest": "^3.0.6", + "vitest": "^3.0.7", "workbox-window": "^7.3.0" }, "scripts": { @@ -59,7 +62,7 @@ "build": "vinxi build", "start": "vinxi start", "version": "vinxi version", - "test": "vitest --coverage", + "test": "vitest --coverage --browser=chromium", "test:ci": "vitest run" } } \ No newline at end of file diff --git a/src/components/textarea/textarea.tsx b/src/components/textarea/textarea.tsx index 9d987b1..39c20f8 100644 --- a/src/components/textarea/textarea.tsx +++ b/src/components/textarea/textarea.tsx @@ -1,12 +1,13 @@ import { Component, createEffect, createMemo, createSignal, For, on, untrack } from 'solid-js'; import { createSelection, getTextNodes } from '@solid-primitives/selection'; import { isServer } from 'solid-js/web'; -import { createEditContext } from '~/features/edit-context'; +import { createEditContext } from '~/features/editor'; import { createSource } from '~/features/source'; import css from './textarea.module.css'; interface TextareaProps { class?: string; + title?: string; value: string; lang: string; placeholder?: string; @@ -20,28 +21,33 @@ export function Textarea(props: TextareaProps) { const source = createSource(() => props.value); const [text] = createEditContext(editorRef, () => source.out); + createEffect(() => { + source.out = text(); + }); + createEffect(() => { props.oninput?.(source.in); }); - createEffect(on(() => [editorRef(), source.spellingErrors] as const, ([ref, errors]) => { + createEffect(on(() => [editorRef()!, source.spellingErrors] as const, ([ref, errors]) => { createHighlights(ref, 'spelling-error', errors); })); - createEffect(on(() => [editorRef(), source.grammarErrors] as const, ([ref, errors]) => { + createEffect(on(() => [editorRef()!, source.grammarErrors] as const, ([ref, errors]) => { createHighlights(ref, 'grammar-error', errors); })); - createEffect(on(() => [editorRef(), source.queryResults] as const, ([ref, errors]) => { + createEffect(on(() => [editorRef()!, source.queryResults] as const, ([ref, errors]) => { createHighlights(ref, 'search-results', errors); })); return <> - source.query = e.target.value} /> + source.query = e.target.value} />
" && char !== " " && char !== "/" && char !== "") { - tagName += char; - char = htmlString.charAt(++pos); - } - - return tagName; -} - -function getCloseTagName(htmlString: string, pos: number) { - let tagName = ""; - let char = htmlString.charAt(pos); - - while (char !== ">" && char !== "") { - tagName += char; - char = htmlString.charAt(++pos); - } - - return tagName; -} - -function getWhiteSpace(htmlString: string, pos: number) { - let whitespace = ""; - let char = htmlString.charAt(pos); - - while (WHITESPACE.includes(char) && char !== "") { - whitespace += char; - char = htmlString.charAt(++pos); - } - - return whitespace; -} - -function getAttributeName(htmlString: string, pos: number) { - let attributeName = ""; - let char = htmlString.charAt(pos); - - while (char !== "=" && char !== " " && char !== ">" && char !== "") { - attributeName += char; - char = htmlString.charAt(++pos); - } - - return attributeName; -} - -function getAttributeValue(htmlString: string, pos: number, quote: string) { - let attributeValue = ""; - let char = htmlString.charAt(pos); - - const isAtEnd = (c) => { - if (quote) { - return c === quote || c === ""; - } - return c === " " || c === ">" || c === "/" || c === ""; - }; - - while (!isAtEnd(char)) { - attributeValue += char; - char = htmlString.charAt(++pos); - } - - return attributeValue; -} - -function getText(htmlString: string, pos: number) { - let text = ""; - let char = htmlString.charAt(pos); - - while (char !== "<" && char !== "") { - text += char; - char = htmlString.charAt(++pos); - } - - return text; -} - -export function tokenizeHTML(htmlString: string) { - let pos = 0; - let isInTag = false; - let isInAttribute = false; - let isAfterAttributeEqual = false; - - const tokens = []; - - while (pos < htmlString.length) { - const char = htmlString.charAt(pos); - const nextChar = htmlString.charAt(pos + 1); - - if (char === "<" && nextChar !== "/" && !isInTag && !isInAttribute) { - isInTag = true; - tokens.push({ type: "openTagStart", value: "<", pos }); - pos++; - const tagName = getOpenTagName(htmlString, pos); - tokens.push({ type: "tagName", value: tagName, pos }); - pos += tagName.length; - continue; - } - - if (WHITESPACE.includes(char) && isInTag) { - const whitespace = getWhiteSpace(htmlString, pos); - tokens.push({ type: "whitespace", value: whitespace, pos }); - pos += whitespace.length; - isInAttribute = false; - continue; - } - - if (char === ">" && isInTag && !isInAttribute) { - isInTag = false; - tokens.push({ type: "openTagEnd", value: ">", pos }); - pos++; - continue; - } - - if (isInTag && !isInAttribute && char === "/" && nextChar === ">") { - isInTag = false; - tokens.push({ type: "selfClose", value: "/>", pos }); - pos += 2; - continue; - } - - if (isInTag && !isInAttribute) { - isInAttribute = true; - const attributeName = getAttributeName(htmlString, pos); - tokens.push({ type: "attributeName", value: attributeName, pos }); - pos += attributeName.length; - - if (htmlString.charAt(pos) !== "=" && htmlString.charAt(pos) !== "'" && htmlString.charAt(pos) !== '"') { - isInAttribute = false; - } - - continue; - } - - if (char === "=" && isInAttribute && isInTag) { - isAfterAttributeEqual = true; - tokens.push({ type: "equal", value: "=", pos }); - pos++; - continue; - } - - if (isAfterAttributeEqual && isInAttribute && isInTag) { - const hasQuote = char === "'" || char === '"'; - const quote = hasQuote ? char : ""; - - if (hasQuote) { - tokens.push({ type: "quoteStart", value: quote, pos }); - pos++; - } - - const attributeValue = getAttributeValue(htmlString, pos, quote); - tokens.push({ type: "attributeValue", value: attributeValue, pos }); - pos += attributeValue.length; - - if (hasQuote && htmlString.charAt(pos) === quote) { - tokens.push({ type: "quoteEnd", value: quote, pos }); - pos++; - } - - isInAttribute = false; - isAfterAttributeEqual = false; - continue; - } - - if (!isInTag && char === "<" && nextChar === "/") { - tokens.push({ type: "closeTagStart", value: "") { - tokens.push({ type: "closeTagEnd", value: ">", pos }); - pos++; - } - - continue; - } - - if (!isInTag) { - const text = getText(htmlString, pos); - tokens.push({ type: "text", value: text, pos }); - pos += text.length; - continue; - } - } - - return tokens; -} \ No newline at end of file diff --git a/src/features/editor/__screenshots__/context.spec.tsx/createEditor-should-create-1.png b/src/features/editor/__screenshots__/context.spec.tsx/createEditor-should-create-1.png new file mode 100644 index 0000000000000000000000000000000000000000..d550b179e792a20f920f7d097106d1693bee6d8c GIT binary patch literal 21680 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 { + describe('create', () => { + it('should create', async () => { + // Arrange + const res = render(() =>

); + const ref = await res.findByTestId('editor'); + + // Act + const actual = createEditor( + () => ref, + () => '

this is a string

' + ); + + // Assert + expect(actual).toBeTruthy(); + }); + + it('should update after a change has taken place', async () => { + // Arrange + const [value, setValue] = createSignal('

this is a string

'); + + const res = render(() => { + const [ref, setRef] = createSignal(); + + const [text] = createEditor(ref, value); + + return
; + }); + const ref = await res.findByTestId('editor'); + + // Act + setValue('

this is another totally different string

'); + + // Assert + expect(ref.innerHTML).toBe('

this is another totally different string

'); + }); + }); + + describe('selection', () => { + it('should not fail if there are no selection ranges', async () => { + // Arrange + const res = render(() => { + const [ref, setRef] = createSignal(); + + const [text] = createEditor(ref, () => '

paragraph 1

\n

paragraph 2

\n

paragraph 3

'); + + return
; + }); + + const ref = await res.findByTestId('editor'); + + // Act + window.getSelection()!.removeAllRanges(); + + // Assert + expect(true).toBeTruthy(); + }); + + it('should react to changes in selection', async () => { + // Arrange + const res = render(() => { + const [ref, setRef] = createSignal(); + + const [text] = createEditor(ref, () => '

paragraph 1

\n

paragraph 2

\n

paragraph 3

'); + + return
; + }); + + const ref = await res.findByTestId('editor'); + + // Act + ref.focus(); + window.getSelection()!.setBaseAndExtent(ref.childNodes[0].childNodes[0], 0, ref.childNodes[0].childNodes[0], 10); + + console.log(window.getSelection()!.rangeCount); + + // Assert + expect(true).toBeTruthy(); + }); + }); +}); \ No newline at end of file diff --git a/src/features/edit-context/context.ts b/src/features/editor/context.ts similarity index 57% rename from src/features/edit-context/context.ts rename to src/features/editor/context.ts index cbebf4b..9a80f65 100644 --- a/src/features/edit-context/context.ts +++ b/src/features/editor/context.ts @@ -1,18 +1,17 @@ import { createEventListenerMap, DocumentEventListener, WindowEventListener } from "@solid-primitives/event-listener"; -import { Accessor, createEffect, createMemo, onMount } from "solid-js"; +import { Accessor, createEffect, createMemo, onMount, untrack } from "solid-js"; import { createStore } from "solid-js/store"; import { isServer } from "solid-js/web"; -import { createSelection, getTextNodes } from "@solid-primitives/selection"; -import { visit } from "unist-util-visit"; -import type { Root, Text } from 'hast'; import { unified } from "unified"; +import { createMap } from './map'; +import { splice } from "~/utilities"; import rehypeParse from "rehype-parse"; -type EditContext = [Accessor]; +type Editor = [Accessor]; -export function createEditContext(ref: Accessor, value: Accessor): EditContext { +export function createEditor(ref: Accessor, value: Accessor): Editor { if (isServer) { - return [createMemo(() => value())]; + return [value]; } if (!("EditContext" in window)) { @@ -34,51 +33,15 @@ export function createEditContext(ref: Accessor, value: }); const ast = createMemo(() => unified().use(rehypeParse).parse(store.text)); - const indices = createMemo(() => { - const root = ref(); - - if (!root) { - return []; - } - - const nodes = getTextNodes(root); - const indices: { node: Node, text: { start: number, end: number }, html: { start: number, end: number } }[] = []; - - let index = 0; - visit(ast(), n => n.type === 'text', (node) => { - const { position, value } = node as Text; - const end = index + value.length; - - if (position) { - indices.push({ node: nodes.shift()!, text: { start: index, end }, html: { start: position.start.offset!, end: position.end.offset! } }); - } - - index = end; - }); - - return indices; - }); - const [selection, setSelection] = createSelection(); - - createEffect(() => { - console.log(indices()); - }); + const indexMap = createMap(() => ref()!, ast); createEventListenerMap(context, { textupdate(e: TextUpdateEvent) { - const { updateRangeStart: start, updateRangeEnd: end } = e; + const { updateRangeStart: start, updateRangeEnd: end, text } = e; - setStore('text', `${store.text.slice(0, start)}${e.text}${store.text.slice(end)}`); + setStore('text', `${store.text.slice(0, start)}${text}${store.text.slice(end)}`); - updateSelection(toRange(ref()!, start, end)); - - setTimeout(() => { - console.log('hmmm', e, start, end); - context.updateSelection(start, end); - - - setSelection([ref()!, start, end]); - }, 1000); + context.updateSelection(start + text.length, start + text.length); }, compositionstart() { @@ -102,37 +65,43 @@ export function createEditContext(ref: Accessor, value: }, }); + function updateText(start: number, end: number, text: string) { + context.updateText(start, end, text); + + setStore('text', splice(store.text, start, end, text)); + + context.updateSelection(start + text.length, start + text.length); + } + function updateControlBounds() { context.updateControlBounds(ref()!.getBoundingClientRect()); } function updateSelection(range: Range) { - const [start, end] = toIndices(ref()!, range); - - let index = 0; - let mappedStart = -1; - let mappedEnd = -1; - - visit(ast(), n => n.type === 'text', (node) => { - const { position, value } = node as Text; - - if (position) { - if (index <= start && (index + value.length) >= start) { - mappedStart = position.start.offset! + range.startOffset; - } - - if (index <= end && (index + value.length) >= end) { - mappedEnd = position.start.offset! + range.endOffset; - } - } - - index += value.length; - }); - - context.updateSelection(mappedStart, mappedEnd); + context.updateSelection(...indexMap.toHtmlIndices(range)); context.updateSelectionBounds(range.getBoundingClientRect()); - setSelection([ref()!, start, end]); + queueMicrotask(() => { + const selection = window.getSelection(); + + if (selection === null) { + return; + } + + if (selection.rangeCount !== 0) { + const existingRange = selection.getRangeAt(0); + + if (equals(range, existingRange)) { + return; + } + + selection.removeAllRanges(); + } + + console.log('is it me?'); + + selection.addRange(range); + }); } WindowEventListener({ @@ -149,27 +118,28 @@ export function createEditContext(ref: Accessor, value: return; } - const start = context.selectionStart; - const end = context.selectionEnd; + const start = Math.min(context.selectionStart, context.selectionEnd); + let end = Math.max(context.selectionStart, context.selectionEnd); if (e.key === 'Tab') { e.preventDefault(); - context.updateText(start, end, '\t'); - // updateSelection(start + 1, start + 1); + updateText(start, end, '    '); } else if (e.key === 'Enter') { - context.updateText(start, end, '\n'); - - // updateSelection(start + 1, start + 1); + updateText(start, end, '\n'); } }, }); DocumentEventListener({ onSelectionchange(e) { - const selection = document.getSelection()!; + const selection = document.getSelection(); - if (selection.rangeCount < 1) { + if (selection === null) { + return; + } + + if (selection.rangeCount === 0) { return; } @@ -185,7 +155,7 @@ export function createEditContext(ref: Accessor, value: updateControlBounds(); }); - createEffect((last?: HTMLElement) => { + createEffect((last?: Element) => { if (last !== undefined) { last.editContext = undefined; } @@ -202,14 +172,31 @@ export function createEditContext(ref: Accessor, value: }); createEffect(() => { - context.updateText(0, 0, value()); + updateText(0, -0, value()); + }); + + createEffect(() => { + store.text; + + if (document.activeElement === untrack(ref)) { + queueMicrotask(() => { + console.log(); + + updateSelection(indexMap.toRange(context.selectionStart, context.selectionEnd)); + }); + } }); return [createMemo(() => store.text)]; } +const equals = (a: Range, b: Range): boolean => { + const keys: (keyof Range)[] = ['startOffset', 'endOffset', 'commonAncestorContainer', 'startContainer', 'endContainer']; + return keys.every(key => a[key] === b[key]); +} + declare global { - interface HTMLElement { + interface Element { editContext?: EditContext; } @@ -275,50 +262,4 @@ declare global { } var EditContext: EditContextConstructor; -} - -const offsetOf = (node: Node, nodes: Node[]) => nodes.slice(0, nodes.indexOf(node)).reduce((t, n) => t + n.textContent!.length, 0); - -const toRange = (root: Node, start: number, end: number): Range => { - let index = 0; - let startNode = null; - let endNode = null; - - for (const node of getTextNodes(root)) { - const length = node.textContent!.length; - - if (index <= start && (index + length) >= start) { - startNode = [node, Math.abs(end - index)] as const; - } - - if (index <= end && (index + length) >= end) { - endNode = [node, Math.abs(end - index)] as const; - } - - if (startNode !== null && endNode !== null) { - break; - } - - index += length; - } - - const range = new Range(); - - if (startNode !== null) { - range.setStart(...startNode); - } - - if (endNode !== null) { - range.setEnd(...endNode); - } - - return range; -}; - -const toIndices = (node: Node, range: Range): [number, number] => { - const nodes = getTextNodes(node); - const start = offsetOf(range.startContainer, nodes) + range.startOffset; - const end = offsetOf(range.endContainer, nodes) + range.endOffset; - - return [start, end]; -}; \ No newline at end of file +} \ No newline at end of file diff --git a/src/features/editor/editor.tsx b/src/features/editor/editor.tsx new file mode 100644 index 0000000..870e72e --- /dev/null +++ b/src/features/editor/editor.tsx @@ -0,0 +1,20 @@ +import { createContextProvider } from "@solid-primitives/context"; +import { createEffect, ParentProps } from "solid-js"; +import { createEditor } from "./context"; + + +const [EditorProvider, useEditor] = createContextProvider((props: { ref: Element, value: string }) => { + const [text] = createEditor(() => props.ref, () => props.value); + + createEffect(() => { + console.log(text()); + }); + + return { text }; +}); + +export { useEditor }; + +export function Editor(props: ParentProps<{ ref: Element, value: string }>) { + return {props.children}; +} \ No newline at end of file diff --git a/src/features/editor/index.tsx b/src/features/editor/index.tsx new file mode 100644 index 0000000..dd45223 --- /dev/null +++ b/src/features/editor/index.tsx @@ -0,0 +1,4 @@ + + +export { createEditor as createEditContext } from './context'; +export { Editor, useEditor } from './editor'; \ No newline at end of file diff --git a/src/features/editor/map.ts b/src/features/editor/map.ts new file mode 100644 index 0000000..981fc9b --- /dev/null +++ b/src/features/editor/map.ts @@ -0,0 +1,114 @@ +import type { Root, Text } from 'hast'; +import { getTextNodes } from '@solid-primitives/selection'; +import { Accessor, createEffect, createMemo, createSignal, onCleanup } from "solid-js"; +import { visit } from 'unist-util-visit'; + +type IndexNode = { node: Node, text: { start: number, end: number }, html: { start: number, end: number } }; +type IndexMap = IndexNode[]; + +export function createMap(root: Accessor, ast: Accessor) { + // Observe the element so that the references to the nodes in the indices are updated if the DOM is changed + const latestMutations = observe(root); + + const indices = createMemo(() => { + latestMutations(); + + const node = root(); + + if (node === undefined) { + return []; + } + + return createIndices(node, ast()); + }); + + return { + atHtmlPosition(index: number) { + return indices().find(({ html }) => html.start <= index && html.end >= index); + }, + + toTextIndices(range: Range): [number, number] { + const startNode = indices().find(({ node }) => node === range.startContainer); + const endNode = indices().find(({ node }) => node === range.endContainer); + + return [ + startNode ? (startNode.text.start + range.startOffset) : -1, + endNode ? (endNode.text.start + range.endOffset) : -1 + ]; + }, + + toHtmlIndices(range: Range): [number, number] { + const startNode = indices().find(({ node }) => node === range.startContainer); + const endNode = indices().find(({ node }) => node === range.endContainer); + + return [ + startNode ? (startNode.html.start + range.startOffset) : -1, + endNode ? (endNode.html.start + range.endOffset) : -1 + ]; + }, + + toRange(start: number, end: number): Range { + const startNode = indices().find(({ html }) => html.start <= start && html.end >= start); + const endNode = indices().find(({ html }) => html.start <= end && html.end >= end); + + const range = new Range(); + + if (startNode) { + const offset = start - startNode.html.start; + + range.setStart(startNode.node, offset); + } + + if (endNode) { + const offset = end - endNode.html.start; + + range.setEnd(endNode.node, offset); + } + + return range; + }, + }; +} + +const createIndices = (root: Node, ast: Root): IndexMap => { + const nodes = getTextNodes(root); + const indices: IndexMap = []; + + let index = 0; + visit(ast, n => n.type === 'text', (node) => { + const { position, value } = node as Text; + const end = index + value.length; + + if (position) { + indices.push({ node: nodes.shift()!, text: { start: index, end }, html: { start: position.start.offset!, end: position.end.offset! } }); + } + + index = end; + }); + + return indices; +}; + +const observe = (node: Accessor): Accessor => { + const [mutations, setMutations] = createSignal([]); + + const observer = new MutationObserver(records => { + setMutations(records); + }); + + createEffect(() => { + const n = node(); + + observer.disconnect(); + + if (n) { + observer.observe(n, { characterData: true, subtree: true, childList: true }); + } + }); + + onCleanup(() => { + observer.disconnect(); + }); + + return mutations; +}; \ No newline at end of file diff --git a/src/features/source/source.spec.ts b/src/features/source/source.spec.ts index 5d5a4a4..59a7cc4 100644 --- a/src/features/source/source.spec.ts +++ b/src/features/source/source.spec.ts @@ -10,7 +10,7 @@ describe('Source', () => { // Arrange // Act - const actual = createSource(''); + const actual = createSource(() => ''); // Assert expect(actual.out).toBe(''); @@ -22,7 +22,7 @@ describe('Source', () => { const expected = '

text

'; // Act - const actual = createSource(given); + const actual = createSource(() => given); // Assert expect(actual.out).toBe(expected); @@ -31,7 +31,7 @@ describe('Source', () => { it('should contain query results', () => { // Arrange const expected: [number, number][] = [[8, 9], [12, 13], [15, 16]]; - const source = createSource('this is a seachable string'); + const source = createSource(() => 'this is a seachable string'); // Act source.query = 'a'; diff --git a/src/routes/(editor)/experimental/formatter.tsx b/src/routes/(editor)/experimental/formatter.tsx index ce40a6d..a42441a 100644 --- a/src/routes/(editor)/experimental/formatter.tsx +++ b/src/routes/(editor)/experimental/formatter.tsx @@ -2,6 +2,7 @@ import { createSignal } from "solid-js"; import { debounce } from "@solid-primitives/scheduled"; import { Textarea } from "~/components/textarea"; import css from './formatter.module.css'; +import { Editor } from "~/features/editor"; const tempVal = ` # Header @@ -37,7 +38,7 @@ export default function Formatter(props: {}) { }, 300); return
- - +