diff --git a/ROADMAP.md b/ROADMAP.md index e087f1a..67592b0 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -51,9 +51,12 @@ the complete web/PWA experience; it does not reduce the product scope. The repository is an Ionic Vue app using Vue 3, TypeScript, Vite 5, Vue Router, Ionic 8, Capacitor 8, Vitest, Cypress, and ESLint. It has a typed Bobbin read boundary, shared unit and browser-test fixtures, live Hurl contract checks, a -Base16 theme engine, and the responsive application shell. The Bobbin boundary -deduplicates concurrent reads with explicit stale times, and shared route state -handles cancellation, retries, incomplete coverage, and distinct failures. +Base16 theme engine, and a responsive application shell with persistent desktop +navigation and mobile tabs. The Bobbin boundary deduplicates concurrent reads +with explicit stale times, and shared route state handles cancellation, retries, +incomplete coverage, and distinct failures. Shared content components compile +plain Markdown with Satteri, sanitize it with DOMPurify, route supported record +identifiers locally, and keep unknown validated records inspectable as text. Every planned domain has a stable deep-link route; later feature tickets replace the shell's route notices with live data. Capacitor has a starter app identifier and no checked-in Android or iOS project. @@ -209,8 +212,12 @@ a useful shareable URL. Do not expose opaque cursors as human identifiers. ### Content safety -- Render Markdown through `marked` `18.0.7`, sanitize the result with DOMPurify - `3.4.12`, and restrict URL schemes before inserting HTML. +- Compile plain Markdown through Satteri `0.9.5`, sanitize the result with + DOMPurify `3.4.12`, and restrict URL schemes before inserting HTML. Do not + compile or evaluate untrusted MDX. +- Serve the application with cross-origin isolation headers because Satteri's + browser WASI build uses shared memory. Target modern browser modules; do not + emit a legacy bundle that cannot run the WASI module. - Treat repository blobs as untrusted text or bytes. Never execute HTML, JavaScript, SVG scripts, or repository-provided styles. - Open external links with an explicit external-browser policy and safe opener diff --git a/TODO.md b/TODO.md index 6b9d456..fe5cad2 100644 --- a/TODO.md +++ b/TODO.md @@ -120,6 +120,8 @@ cursor guards, coverage notices, and shared loading/error/empty components. ### T07 - Render Markdown and record links safely +**Status:** Complete + **What to build:** Add sanitized Markdown, safe link handling, common record headers, identifier copying, and canonical Tangled links. @@ -127,10 +129,10 @@ headers, identifier copying, and canonical Tangled links. **Acceptance criteria:** -- [ ] Markdown uses Marked and DOMPurify with restricted URL schemes. -- [ ] Scriptable HTML, SVG, styles, and unsafe links are removed in security tests. -- [ ] Mentions, references, AT-URIs, DIDs, and known Tangled URLs link to local views. -- [ ] Unknown record types remain inspectable without unsafe generic HTML. +- [x] Markdown uses Satteri and DOMPurify with restricted URL schemes. +- [x] Scriptable HTML, SVG, styles, and unsafe links are removed in security tests. +- [x] Mentions, references, AT-URIs, DIDs, and known Tangled URLs link to local views. +- [x] Unknown record types remain inspectable without unsafe generic HTML. **Verification:** `bun run test:unit --run && bun run build` diff --git a/bun.lock b/bun.lock index 5c6abfd..8313530 100644 --- a/bun.lock +++ b/bun.lock @@ -9,6 +9,7 @@ "@atcute/lexicons": "2.0.3", "@atcute/microcosm": "2.0.2", "@atcute/tangled": "2.0.13", + "@bruits/satteri-wasm32-wasi": "0.9.5", "@capacitor/app": "8.1.1", "@capacitor/core": "8.5.0", "@capacitor/haptics": "8.0.2", @@ -18,14 +19,15 @@ "@fontsource-variable/commissioner": "^5.3.0", "@ionic/vue": "^8.0.0", "@ionic/vue-router": "^8.0.0", + "dompurify": "3.4.12", "ionicons": "^7.0.0", + "satteri": "0.9.5", "vue": "^3.3.0", "vue-router": "^4.2.0", }, "devDependencies": { "@capacitor/cli": "8.5.0", "@eslint/js": "10.0.1", - "@vitejs/plugin-legacy": "^5.0.0", "@vitejs/plugin-vue": "^4.0.0", "@vue/eslint-config-typescript": "14.9.0", "@vue/test-utils": "^2.3.0", @@ -62,185 +64,31 @@ "@atcute/util-text": ["@atcute/util-text@1.3.4", "", { "dependencies": { "unicode-segmenter": "^0.17.0" } }, "sha512-u2UAM7iSM09sQaSG9jtxWFSPgB8boVj50/BoyMvYnhVgGBu+nXIuAcdDUQCsZA44YZgTPPhN/b86JX+jH7SPzQ=="], - "@babel/code-frame": ["@babel/code-frame@7.29.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw=="], - - "@babel/compat-data": ["@babel/compat-data@7.29.7", "", {}, "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg=="], - - "@babel/core": ["@babel/core@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-module-transforms": "^7.29.7", "@babel/helpers": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/template": "^7.29.7", "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA=="], - - "@babel/generator": ["@babel/generator@7.29.8", "", { "dependencies": { "@babel/parser": "^7.29.8", "@babel/types": "^7.29.8", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg=="], - - "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.29.7", "", { "dependencies": { "@babel/types": "^7.29.7" } }, "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw=="], - - "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.29.7", "", { "dependencies": { "@babel/compat-data": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g=="], - - "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-member-expression-to-functions": "^7.29.7", "@babel/helper-optimise-call-expression": "^7.29.7", "@babel/helper-replace-supers": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", "@babel/traverse": "^7.29.7", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg=="], - - "@babel/helper-create-regexp-features-plugin": ["@babel/helper-create-regexp-features-plugin@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg=="], - - "@babel/helper-define-polyfill-provider": ["@babel/helper-define-polyfill-provider@0.6.8", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "debug": "^4.4.3", "lodash.debounce": "^4.0.8", "resolve": "^1.22.11" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA=="], - - "@babel/helper-globals": ["@babel/helper-globals@7.29.7", "", {}, "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA=="], - - "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg=="], - - "@babel/helper-module-imports": ["@babel/helper-module-imports@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g=="], - - "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.29.7", "", { "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg=="], - - "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.29.7", "", { "dependencies": { "@babel/types": "^7.29.7" } }, "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong=="], - - "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.29.7", "", {}, "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw=="], - - "@babel/helper-remap-async-to-generator": ["@babel/helper-remap-async-to-generator@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-wrap-function": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og=="], - - "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.29.7", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.29.7", "@babel/helper-optimise-call-expression": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ=="], - - "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ=="], - "@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="], - "@babel/helper-validator-option": ["@babel/helper-validator-option@7.29.7", "", {}, "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw=="], - - "@babel/helper-wrap-function": ["@babel/helper-wrap-function@7.29.7", "", { "dependencies": { "@babel/template": "^7.29.7", "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw=="], - - "@babel/helpers": ["@babel/helpers@7.29.7", "", { "dependencies": { "@babel/template": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg=="], - "@babel/parser": ["@babel/parser@7.29.8", "", { "dependencies": { "@babel/types": "^7.29.8" }, "bin": { "parser": "bin/babel-parser.js" } }, "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA=="], - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": ["@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w=="], - - "@babel/plugin-bugfix-safari-class-field-initializer-scope": ["@babel/plugin-bugfix-safari-class-field-initializer-scope@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ=="], - - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ["@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ=="], - - "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": ["@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA=="], - - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ["@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", "@babel/plugin-transform-optional-chaining": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.13.0" } }, "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw=="], - - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ["@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw=="], - - "@babel/plugin-proposal-private-property-in-object": ["@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2", "", { "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w=="], - - "@babel/plugin-syntax-import-assertions": ["@babel/plugin-syntax-import-assertions@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw=="], - - "@babel/plugin-syntax-import-attributes": ["@babel/plugin-syntax-import-attributes@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg=="], - - "@babel/plugin-syntax-unicode-sets-regex": ["@babel/plugin-syntax-unicode-sets-regex@7.18.6", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg=="], - - "@babel/plugin-transform-arrow-functions": ["@babel/plugin-transform-arrow-functions@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ=="], - - "@babel/plugin-transform-async-generator-functions": ["@babel/plugin-transform-async-generator-functions@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-remap-async-to-generator": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA=="], - - "@babel/plugin-transform-async-to-generator": ["@babel/plugin-transform-async-to-generator@7.29.7", "", { "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-remap-async-to-generator": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w=="], - - "@babel/plugin-transform-block-scoped-functions": ["@babel/plugin-transform-block-scoped-functions@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA=="], - - "@babel/plugin-transform-block-scoping": ["@babel/plugin-transform-block-scoping@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ=="], - - "@babel/plugin-transform-class-properties": ["@babel/plugin-transform-class-properties@7.29.7", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA=="], - - "@babel/plugin-transform-class-static-block": ["@babel/plugin-transform-class-static-block@7.29.7", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.12.0" } }, "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A=="], - - "@babel/plugin-transform-classes": ["@babel/plugin-transform-classes@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-globals": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-replace-supers": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g=="], - - "@babel/plugin-transform-computed-properties": ["@babel/plugin-transform-computed-properties@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/template": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA=="], - - "@babel/plugin-transform-destructuring": ["@babel/plugin-transform-destructuring@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg=="], - - "@babel/plugin-transform-dotall-regex": ["@babel/plugin-transform-dotall-regex@7.29.7", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ=="], - - "@babel/plugin-transform-duplicate-keys": ["@babel/plugin-transform-duplicate-keys@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ=="], - - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": ["@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.7", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA=="], - - "@babel/plugin-transform-dynamic-import": ["@babel/plugin-transform-dynamic-import@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg=="], - - "@babel/plugin-transform-explicit-resource-management": ["@babel/plugin-transform-explicit-resource-management@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/plugin-transform-destructuring": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw=="], - - "@babel/plugin-transform-exponentiation-operator": ["@babel/plugin-transform-exponentiation-operator@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ=="], - - "@babel/plugin-transform-export-namespace-from": ["@babel/plugin-transform-export-namespace-from@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA=="], - - "@babel/plugin-transform-for-of": ["@babel/plugin-transform-for-of@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ=="], - - "@babel/plugin-transform-function-name": ["@babel/plugin-transform-function-name@7.29.7", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg=="], - - "@babel/plugin-transform-json-strings": ["@babel/plugin-transform-json-strings@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg=="], - - "@babel/plugin-transform-literals": ["@babel/plugin-transform-literals@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw=="], - - "@babel/plugin-transform-logical-assignment-operators": ["@babel/plugin-transform-logical-assignment-operators@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q=="], - - "@babel/plugin-transform-member-expression-literals": ["@babel/plugin-transform-member-expression-literals@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg=="], - - "@babel/plugin-transform-modules-amd": ["@babel/plugin-transform-modules-amd@7.29.7", "", { "dependencies": { "@babel/helper-module-transforms": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew=="], - - "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.29.7", "", { "dependencies": { "@babel/helper-module-transforms": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ=="], - - "@babel/plugin-transform-modules-systemjs": ["@babel/plugin-transform-modules-systemjs@7.29.8", "", { "dependencies": { "@babel/helper-module-transforms": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7", "@babel/traverse": "^7.29.8" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6iSnEK0zlkLKU4heofK/AdmRD4e2SHVpJMtrwnTCzhnaM98ria4rTrOXBBi45BTTYnJtO8txnPsX4fChYXkmeA=="], - - "@babel/plugin-transform-modules-umd": ["@babel/plugin-transform-modules-umd@7.29.7", "", { "dependencies": { "@babel/helper-module-transforms": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA=="], - - "@babel/plugin-transform-named-capturing-groups-regex": ["@babel/plugin-transform-named-capturing-groups-regex@7.29.7", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ=="], - - "@babel/plugin-transform-new-target": ["@babel/plugin-transform-new-target@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A=="], - - "@babel/plugin-transform-nullish-coalescing-operator": ["@babel/plugin-transform-nullish-coalescing-operator@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg=="], - - "@babel/plugin-transform-numeric-separator": ["@babel/plugin-transform-numeric-separator@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw=="], - - "@babel/plugin-transform-object-rest-spread": ["@babel/plugin-transform-object-rest-spread@7.29.7", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/plugin-transform-destructuring": "^7.29.7", "@babel/plugin-transform-parameters": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A=="], - - "@babel/plugin-transform-object-super": ["@babel/plugin-transform-object-super@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-replace-supers": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA=="], - - "@babel/plugin-transform-optional-catch-binding": ["@babel/plugin-transform-optional-catch-binding@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng=="], - - "@babel/plugin-transform-optional-chaining": ["@babel/plugin-transform-optional-chaining@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ=="], - - "@babel/plugin-transform-parameters": ["@babel/plugin-transform-parameters@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g=="], - - "@babel/plugin-transform-private-methods": ["@babel/plugin-transform-private-methods@7.29.7", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug=="], - - "@babel/plugin-transform-private-property-in-object": ["@babel/plugin-transform-private-property-in-object@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA=="], - - "@babel/plugin-transform-property-literals": ["@babel/plugin-transform-property-literals@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA=="], - - "@babel/plugin-transform-regenerator": ["@babel/plugin-transform-regenerator@7.29.8", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0UpIXPtdDtMXfnV2OJAVMLpj3H/92vmkA6lpSRakmycJvj3VUy6Xs1dM8tXRugupykr5WB+LpiVl0J8LMVg2mg=="], - - "@babel/plugin-transform-regexp-modifiers": ["@babel/plugin-transform-regexp-modifiers@7.29.7", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ=="], - - "@babel/plugin-transform-reserved-words": ["@babel/plugin-transform-reserved-words@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA=="], - - "@babel/plugin-transform-shorthand-properties": ["@babel/plugin-transform-shorthand-properties@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg=="], - - "@babel/plugin-transform-spread": ["@babel/plugin-transform-spread@7.29.8", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-4S9ksMGVWUshvgK0mKfvZky7leuG5/uoFVwMpAomJ8bMoDJiNHRVmc1EglwW/CmGVSqqWpEbXm9FmbRit22qoA=="], - - "@babel/plugin-transform-sticky-regex": ["@babel/plugin-transform-sticky-regex@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA=="], - - "@babel/plugin-transform-template-literals": ["@babel/plugin-transform-template-literals@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA=="], - - "@babel/plugin-transform-typeof-symbol": ["@babel/plugin-transform-typeof-symbol@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A=="], + "@babel/types": ["@babel/types@7.29.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg=="], - "@babel/plugin-transform-unicode-escapes": ["@babel/plugin-transform-unicode-escapes@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA=="], + "@bruits/satteri-darwin-arm64": ["@bruits/satteri-darwin-arm64@0.9.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-iw4nZgx9v30lWo/MTngQqi1pI78KI0DnkSm+lVJGYdmPLgAyDNJigVhpG42/Iq55A6c1Ll8q66ljyyRiQUxwow=="], - "@babel/plugin-transform-unicode-property-regex": ["@babel/plugin-transform-unicode-property-regex@7.29.7", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw=="], + "@bruits/satteri-darwin-x64": ["@bruits/satteri-darwin-x64@0.9.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-6T26Z5Kf3cFW2PSlk9p7zT7yVxvuBSiJvYyz9u8KjYwMTqZyIDOj2wDyNpxKV4+6yUVG7rddq2QwvG/8LJA2+Q=="], - "@babel/plugin-transform-unicode-regex": ["@babel/plugin-transform-unicode-regex@7.29.7", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA=="], + "@bruits/satteri-linux-arm64-gnu": ["@bruits/satteri-linux-arm64-gnu@0.9.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-u51id17uJwNEMK9nBlICsq6U31c+XVqQueVBkwRIzZG+gMpS8TOJctt5h5Wz33Z8xnMdTd+adtACVz0yHgGuOA=="], - "@babel/plugin-transform-unicode-sets-regex": ["@babel/plugin-transform-unicode-sets-regex@7.29.7", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg=="], + "@bruits/satteri-linux-arm64-musl": ["@bruits/satteri-linux-arm64-musl@0.9.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-v39HxiwGC5Rqm01HksP6+5Y+xKLPlsuVFgIgpEAo+SiQ22c+mJVhS3u7Z6ePAKdhL5NJoK1xq70kLz3L13AhpQ=="], - "@babel/preset-env": ["@babel/preset-env@7.29.7", "", { "dependencies": { "@babel/compat-data": "^7.29.7", "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.29.7", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.29.7", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.29.7", "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.7", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.29.7", "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.29.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-import-assertions": "^7.29.7", "@babel/plugin-syntax-import-attributes": "^7.29.7", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.29.7", "@babel/plugin-transform-async-generator-functions": "^7.29.7", "@babel/plugin-transform-async-to-generator": "^7.29.7", "@babel/plugin-transform-block-scoped-functions": "^7.29.7", "@babel/plugin-transform-block-scoping": "^7.29.7", "@babel/plugin-transform-class-properties": "^7.29.7", "@babel/plugin-transform-class-static-block": "^7.29.7", "@babel/plugin-transform-classes": "^7.29.7", "@babel/plugin-transform-computed-properties": "^7.29.7", "@babel/plugin-transform-destructuring": "^7.29.7", "@babel/plugin-transform-dotall-regex": "^7.29.7", "@babel/plugin-transform-duplicate-keys": "^7.29.7", "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.7", "@babel/plugin-transform-dynamic-import": "^7.29.7", "@babel/plugin-transform-explicit-resource-management": "^7.29.7", "@babel/plugin-transform-exponentiation-operator": "^7.29.7", "@babel/plugin-transform-export-namespace-from": "^7.29.7", "@babel/plugin-transform-for-of": "^7.29.7", "@babel/plugin-transform-function-name": "^7.29.7", "@babel/plugin-transform-json-strings": "^7.29.7", "@babel/plugin-transform-literals": "^7.29.7", "@babel/plugin-transform-logical-assignment-operators": "^7.29.7", "@babel/plugin-transform-member-expression-literals": "^7.29.7", "@babel/plugin-transform-modules-amd": "^7.29.7", "@babel/plugin-transform-modules-commonjs": "^7.29.7", "@babel/plugin-transform-modules-systemjs": "^7.29.7", "@babel/plugin-transform-modules-umd": "^7.29.7", "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.7", "@babel/plugin-transform-new-target": "^7.29.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7", "@babel/plugin-transform-numeric-separator": "^7.29.7", "@babel/plugin-transform-object-rest-spread": "^7.29.7", "@babel/plugin-transform-object-super": "^7.29.7", "@babel/plugin-transform-optional-catch-binding": "^7.29.7", "@babel/plugin-transform-optional-chaining": "^7.29.7", "@babel/plugin-transform-parameters": "^7.29.7", "@babel/plugin-transform-private-methods": "^7.29.7", "@babel/plugin-transform-private-property-in-object": "^7.29.7", "@babel/plugin-transform-property-literals": "^7.29.7", "@babel/plugin-transform-regenerator": "^7.29.7", "@babel/plugin-transform-regexp-modifiers": "^7.29.7", "@babel/plugin-transform-reserved-words": "^7.29.7", "@babel/plugin-transform-shorthand-properties": "^7.29.7", "@babel/plugin-transform-spread": "^7.29.7", "@babel/plugin-transform-sticky-regex": "^7.29.7", "@babel/plugin-transform-template-literals": "^7.29.7", "@babel/plugin-transform-typeof-symbol": "^7.29.7", "@babel/plugin-transform-unicode-escapes": "^7.29.7", "@babel/plugin-transform-unicode-property-regex": "^7.29.7", "@babel/plugin-transform-unicode-regex": "^7.29.7", "@babel/plugin-transform-unicode-sets-regex": "^7.29.7", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.15", "babel-plugin-polyfill-corejs3": "^0.14.0", "babel-plugin-polyfill-regenerator": "^0.6.6", "core-js-compat": "^3.48.0", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA=="], + "@bruits/satteri-linux-x64-gnu": ["@bruits/satteri-linux-x64-gnu@0.9.5", "", { "os": "linux", "cpu": "x64" }, "sha512-F3uO8uFp3pAP5ZGXttwvh57GS7s0lL953tnNdyI2gRyP4kOOkp6pyGojNJzCjkDvWI2Cvb9iNrKok3aqQPauAw=="], - "@babel/preset-modules": ["@babel/preset-modules@0.1.6-no-external-plugins", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", "esutils": "^2.0.2" }, "peerDependencies": { "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA=="], + "@bruits/satteri-linux-x64-musl": ["@bruits/satteri-linux-x64-musl@0.9.5", "", { "os": "linux", "cpu": "x64" }, "sha512-bicEqglLlz++mWyADaZoP0JY20s4vDfLjaPYgQqC+NI4zZLTOOg1T4GB8aqtc822Pqji8SQBmSrTb7CrP8i08Q=="], - "@babel/template": ["@babel/template@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg=="], + "@bruits/satteri-wasm32-wasi": ["@bruits/satteri-wasm32-wasi@0.9.5", "", { "dependencies": { "@emnapi/core": "1.11.1", "@emnapi/runtime": "1.11.1", "@napi-rs/wasm-runtime": "^1.1.6" } }, "sha512-zauAuMwfPnKPUkd4AFixRFpXdgKwP2mKgxrIIo2gJzW0/ZneF9dbHnLkojSpaBnCCp7VUL1hIi5WWZvB1CqmAQ=="], - "@babel/traverse": ["@babel/traverse@7.29.8", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.8", "@babel/helper-globals": "^7.29.7", "@babel/parser": "^7.29.8", "@babel/template": "^7.29.7", "@babel/types": "^7.29.8", "debug": "^4.3.1" } }, "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg=="], + "@bruits/satteri-win32-arm64-msvc": ["@bruits/satteri-win32-arm64-msvc@0.9.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-SrfE7NEsgZjBvU3c+RR6oQRu0ToXY5uVJEbieXEF0YTctIV2zAVlbaMjWLts074QCgh3a+XHWkR/lWh2VH2LUg=="], - "@babel/types": ["@babel/types@7.29.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg=="], + "@bruits/satteri-win32-x64-msvc": ["@bruits/satteri-win32-x64-msvc@0.9.5", "", { "os": "win32", "cpu": "x64" }, "sha512-5Kw9ZAtTGS8WHizyn+CJhjjfIQrw+7jcZodpmpXJjefnO15M8UexIi6JR2E5thyvsmHyhL6ZDDMUNR4bKJPd4g=="], "@capacitor/app": ["@capacitor/app@8.1.1", "", { "peerDependencies": { "@capacitor/core": ">=8.0.0" } }, "sha512-xM2ZTX5jK60tFtmjsmJv+Cdj1Qsb6NcavkqmdEnCPQBeya9oKhamZJxYOnQNj1ZvcJM7sWfG6BEtSLx42pisbA=="], @@ -260,6 +108,12 @@ "@cypress/xvfb": ["@cypress/xvfb@1.2.4", "", { "dependencies": { "debug": "^3.1.0", "lodash.once": "^4.1.1" } }, "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q=="], + "@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="], + + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], "@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="], @@ -368,8 +222,6 @@ "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], - "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], - "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], "@jridgewell/source-map": ["@jridgewell/source-map@0.3.11", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA=="], @@ -380,6 +232,8 @@ "@napi-rs/lzma-linux-x64-gnu": ["@napi-rs/lzma-linux-x64-gnu@1.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ=="], + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.2.2", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.3", "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.3" } }, "sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw=="], + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], @@ -450,6 +304,8 @@ "@tootallnate/once": ["@tootallnate/once@2.0.1", "", {}, "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ=="], + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="], + "@types/chai": ["@types/chai@4.3.20", "", {}, "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ=="], "@types/chai-subset": ["@types/chai-subset@1.3.6", "", { "peerDependencies": { "@types/chai": "<5.2.0" } }, "sha512-m8lERkkQj+uek18hXOZuec3W/fCRTrU4hrnXjH3qhHy96ytuPaPiWGgu7sJb7tZxZonO75vYAjCvpe/e4VUwRw=="], @@ -458,10 +314,16 @@ "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], + "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="], + "@types/fs-extra": ["@types/fs-extra@8.1.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ=="], + "@types/hast": ["@types/hast@3.0.5", "", { "dependencies": { "@types/unist": "*" } }, "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g=="], + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], + "@types/node": ["@types/node@26.1.2", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg=="], "@types/sinonjs__fake-timers": ["@types/sinonjs__fake-timers@8.1.1", "", {}, "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g=="], @@ -470,6 +332,10 @@ "@types/slice-ansi": ["@types/slice-ansi@4.0.0", "", {}, "sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ=="], + "@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=="], + "@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="], "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.65.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.65.0", "@typescript-eslint/type-utils": "8.65.0", "@typescript-eslint/utils": "8.65.0", "@typescript-eslint/visitor-keys": "8.65.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.65.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-IEgob78X12rHpUmtcwFsXhZdVGJtwTVP8FiCLZkR6GlYVrl2PcuB+KhCE5BlVC/eQpQnu8WXRtkHZuPar+gCRA=="], @@ -492,8 +358,6 @@ "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.65.0", "", { "dependencies": { "@typescript-eslint/types": "8.65.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A=="], - "@vitejs/plugin-legacy": ["@vitejs/plugin-legacy@5.4.3", "", { "dependencies": { "@babel/core": "^7.25.8", "@babel/preset-env": "^7.25.8", "browserslist": "^4.24.0", "browserslist-to-esbuild": "^2.1.1", "core-js": "^3.38.1", "magic-string": "^0.30.12", "regenerator-runtime": "^0.14.1", "systemjs": "^6.15.1" }, "peerDependencies": { "terser": "^5.4.0", "vite": "^5.0.0" } }, "sha512-wsyXK9mascyplcqvww1gA1xYiy29iRHfyciw+a0t7qRNdzX6PdfSWmOoCi74epr87DujM+5J+rnnSv+4PazqVg=="], - "@vitejs/plugin-vue": ["@vitejs/plugin-vue@4.6.2", "", { "peerDependencies": { "vite": "^4.0.0 || ^5.0.0", "vue": "^3.2.25" } }, "sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw=="], "@vitest/expect": ["@vitest/expect@0.34.6", "", { "dependencies": { "@vitest/spy": "0.34.6", "@vitest/utils": "0.34.6", "chai": "^4.3.10" } }, "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw=="], @@ -588,12 +452,6 @@ "aws4": ["aws4@1.13.2", "", {}, "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw=="], - "babel-plugin-polyfill-corejs2": ["babel-plugin-polyfill-corejs2@0.4.17", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-define-polyfill-provider": "^0.6.8", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w=="], - - "babel-plugin-polyfill-corejs3": ["babel-plugin-polyfill-corejs3@0.14.2", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.8", "core-js-compat": "^3.48.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g=="], - - "babel-plugin-polyfill-regenerator": ["babel-plugin-polyfill-regenerator@0.6.8", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.8" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg=="], - "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], @@ -620,8 +478,6 @@ "browserslist": ["browserslist@4.28.7", "", { "dependencies": { "baseline-browser-mapping": "^2.10.44", "caniuse-lite": "^1.0.30001806", "electron-to-chromium": "^1.5.393", "node-releases": "^2.0.51", "update-browserslist-db": "^1.2.3" }, "bin": "cli.js" }, "sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw=="], - "browserslist-to-esbuild": ["browserslist-to-esbuild@2.1.1", "", { "dependencies": { "meow": "^13.0.0" }, "peerDependencies": { "browserslist": "*" }, "bin": "cli/index.js" }, "sha512-KN+mty6C3e9AN8Z5dI1xeN15ExcRNeISoC3g7V0Kax/MMF9MSoYA2G7lkTTcVUFntiEjkpI0HNgqJC1NjdyNUw=="], - "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="], @@ -682,10 +538,6 @@ "convert-hrtime": ["convert-hrtime@5.0.0", "", {}, "sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg=="], - "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], - - "core-js": ["core-js@3.49.0", "", {}, "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg=="], - "core-js-compat": ["core-js-compat@3.49.0", "", { "dependencies": { "browserslist": "^4.28.1" } }, "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA=="], "core-util-is": ["core-util-is@1.0.2", "", {}, "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="], @@ -726,6 +578,8 @@ "domexception": ["domexception@4.0.0", "", { "dependencies": { "webidl-conversions": "^7.0.0" } }, "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw=="], + "dompurify": ["dompurify@3.4.12", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg=="], + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], @@ -842,8 +696,6 @@ "function-timeout": ["function-timeout@1.0.2", "", {}, "sha512-939eZS4gJ3htTHAldmyyuzlrD58P03fHG49v2JfFXbV6OhvZKRC9j2yAtdHw/zrp2zXHuv05zMIy40F0ge7spA=="], - "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], - "get-func-name": ["get-func-name@2.0.2", "", {}, "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ=="], "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], @@ -908,8 +760,6 @@ "is-builtin-module": ["is-builtin-module@5.0.0", "", { "dependencies": { "builtin-modules": "^5.0.0" } }, "sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA=="], - "is-core-module": ["is-core-module@2.16.2", "", { "dependencies": { "hasown": "^2.0.3" } }, "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA=="], - "is-docker": ["is-docker@2.2.1", "", { "bin": "cli.js" }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], @@ -946,8 +796,6 @@ "js-cookie": ["js-cookie@3.0.8", "", {}, "sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw=="], - "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], - "jsbn": ["jsbn@0.1.1", "", {}, "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="], "jsdom": ["jsdom@22.1.0", "", { "dependencies": { "abab": "^2.0.6", "cssstyle": "^3.0.0", "data-urls": "^4.0.0", "decimal.js": "^10.4.3", "domexception": "^4.0.0", "form-data": "^4.0.0", "html-encoding-sniffer": "^3.0.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.1", "is-potential-custom-element-name": "^1.0.1", "nwsapi": "^2.2.4", "parse5": "^7.1.2", "rrweb-cssom": "^0.6.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^4.1.2", "w3c-xmlserializer": "^4.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^2.0.0", "whatwg-mimetype": "^3.0.0", "whatwg-url": "^12.0.1", "ws": "^8.13.0", "xml-name-validator": "^4.0.0" }, "peerDependencies": { "canvas": "^2.5.0" }, "optionalPeers": ["canvas"] }, "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw=="], @@ -964,8 +812,6 @@ "json-stringify-safe": ["json-stringify-safe@5.0.1", "", {}, "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="], - "json5": ["json5@2.2.3", "", { "bin": "lib/cli.js" }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], - "jsonfile": ["jsonfile@6.2.1", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q=="], "jsprim": ["jsprim@2.0.2", "", { "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", "json-schema": "0.4.0", "verror": "1.10.0" } }, "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ=="], @@ -986,8 +832,6 @@ "lodash": ["lodash@4.18.1", "", {}, "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="], - "lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="], - "lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="], "log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="], @@ -996,7 +840,7 @@ "loupe": ["loupe@2.3.7", "", { "dependencies": { "get-func-name": "^2.0.1" } }, "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA=="], - "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], + "lru-cache": ["lru-cache@11.5.2", "", {}, "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g=="], "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], @@ -1006,8 +850,6 @@ "mdn-data": ["mdn-data@2.29.0", "", {}, "sha512-pVxQFCcaYUEAH853+v7yoI/qzhxXSq1bTb9obMYGYAN1c3Hen+XDCEvr296XhstrwlSTNgOR7mCSD4JPjbJe5A=="], - "meow": ["meow@13.2.0", "", {}, "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA=="], - "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], @@ -1082,8 +924,6 @@ "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], - "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], - "path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], "pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], @@ -1144,16 +984,6 @@ "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], - "regenerate": ["regenerate@1.4.2", "", {}, "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="], - - "regenerate-unicode-properties": ["regenerate-unicode-properties@10.2.2", "", { "dependencies": { "regenerate": "^1.4.2" } }, "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g=="], - - "regenerator-runtime": ["regenerator-runtime@0.14.1", "", {}, "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="], - - "regexpu-core": ["regexpu-core@6.4.0", "", { "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.2", "regjsgen": "^0.8.0", "regjsparser": "^0.13.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.2.1" } }, "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA=="], - - "regjsgen": ["regjsgen@0.8.0", "", {}, "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q=="], - "regjsparser": ["regjsparser@0.13.2", "", { "dependencies": { "jsesc": "~3.1.0" }, "bin": "bin/parser" }, "sha512-NgRBy2Nx/bE+9F27nVHnqcN5HjyLmecqsqx2PJHu3/IEtADD4WuxuXIVExD5PoSDFVrl78dOonfcOe5O+5nbzQ=="], "request-progress": ["request-progress@3.0.0", "", { "dependencies": { "throttleit": "^1.0.0" } }, "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg=="], @@ -1162,8 +992,6 @@ "reserved-identifiers": ["reserved-identifiers@1.2.0", "", {}, "sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw=="], - "resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="], - "restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="], "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], @@ -1184,6 +1012,8 @@ "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + "satteri": ["satteri@0.9.5", "", { "dependencies": { "@types/estree-jsx": "^1.0.5", "@types/hast": "^3.0.4", "@types/mdast": "^4.0.4", "@types/unist": "^3.0.3" }, "optionalDependencies": { "@bruits/satteri-darwin-arm64": "0.9.5", "@bruits/satteri-darwin-x64": "0.9.5", "@bruits/satteri-linux-arm64-gnu": "0.9.5", "@bruits/satteri-linux-arm64-musl": "0.9.5", "@bruits/satteri-linux-x64-gnu": "0.9.5", "@bruits/satteri-linux-x64-musl": "0.9.5", "@bruits/satteri-wasm32-wasi": "0.9.5", "@bruits/satteri-win32-arm64-msvc": "0.9.5", "@bruits/satteri-win32-x64-msvc": "0.9.5" } }, "sha512-ZuWVl+vnM64y+/TtX8Kosv2c00W+hLQiiwnEL6H0UKVVrxFqMw4D2CJHHQaouVd89OAhtBBfjWLqhKi3TVUV4w=="], + "sax": ["sax@1.1.4", "", {}, "sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg=="], "saxes": ["saxes@6.0.0", "", { "dependencies": { "xmlchars": "^2.2.0" } }, "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA=="], @@ -1248,12 +1078,8 @@ "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], - "symbol-tree": ["symbol-tree@3.2.4", "", {}, "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="], - "systemjs": ["systemjs@6.15.1", "", {}, "sha512-Nk8c4lXvMB98MtbmjX7JwJRgJOL8fluecYCfCeYBznwmpOs8Bf15hLM6z4z71EDAhQVrQrI+wt1aLWSXZq+hXA=="], - "tar": ["tar@7.5.22", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA=="], "terser": ["terser@5.49.0", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": "bin/terser" }, "sha512-SNiDnXyHSrxVcIOtVbULzcTmniUiwcV7Nwdyj1twVubeTmbjoa8p69KKDpfkdoOavuM4/GRm1+ykI8qqnavHoA=="], @@ -1310,14 +1136,6 @@ "undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], - "unicode-canonical-property-names-ecmascript": ["unicode-canonical-property-names-ecmascript@2.0.1", "", {}, "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg=="], - - "unicode-match-property-ecmascript": ["unicode-match-property-ecmascript@2.0.0", "", { "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" } }, "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q=="], - - "unicode-match-property-value-ecmascript": ["unicode-match-property-value-ecmascript@2.2.1", "", {}, "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg=="], - - "unicode-property-aliases-ecmascript": ["unicode-property-aliases-ecmascript@2.2.0", "", {}, "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ=="], - "unicode-segmenter": ["unicode-segmenter@0.17.3", "", {}, "sha512-hKZwqBjJDmqNrq1+LjDxck1qLzJFcLLJM2Xq92ORRHOuau6GSHeELmn+uyk6zNH1CK9mogrUJGP9WJCJUQXMAw=="], "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], @@ -1400,16 +1218,6 @@ "yocto-queue": ["yocto-queue@1.2.2", "", {}, "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ=="], - "@babel/core/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@babel/helper-create-regexp-features-plugin/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "@babel/preset-env/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - "@cypress/request/tough-cookie": ["tough-cookie@5.1.2", "", { "dependencies": { "tldts": "^6.1.32" } }, "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A=="], "@cypress/request/uuid": ["uuid@8.3.2", "", { "bin": "dist/bin/uuid" }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], @@ -1454,8 +1262,6 @@ "aggregate-error/indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], - "babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - "chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "cli-truncate/slice-ansi": ["slice-ansi@3.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ=="], @@ -1484,8 +1290,6 @@ "log-update/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=="], - "lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], - "make-asynchronous/type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], "mlly/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], @@ -1494,8 +1298,6 @@ "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], - "path-scurry/lru-cache": ["lru-cache@11.5.2", "", {}, "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g=="], - "pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], "pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], diff --git a/package.json b/package.json index 9fa64b1..763a106 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@atcute/lexicons": "2.0.3", "@atcute/microcosm": "2.0.2", "@atcute/tangled": "2.0.13", + "@bruits/satteri-wasm32-wasi": "0.9.5", "@capacitor/app": "8.1.1", "@capacitor/core": "8.5.0", "@capacitor/haptics": "8.0.2", @@ -29,14 +30,15 @@ "@fontsource-variable/commissioner": "^5.3.0", "@ionic/vue": "^8.0.0", "@ionic/vue-router": "^8.0.0", + "dompurify": "3.4.12", "ionicons": "^7.0.0", + "satteri": "0.9.5", "vue": "^3.3.0", "vue-router": "^4.2.0" }, "devDependencies": { "@capacitor/cli": "8.5.0", "@eslint/js": "10.0.1", - "@vitejs/plugin-legacy": "^5.0.0", "@vitejs/plugin-vue": "^4.0.0", "@vue/eslint-config-typescript": "14.9.0", "@vue/test-utils": "^2.3.0", diff --git a/public/favicon.png b/public/favicon.png index 51888a7bbdb59f04c29c548523eb2638c1c954f5..40e8ec834c7a8262c5c71826a099518d2bde2c99 100644 GIT binary patch literal 17053 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 literal 930 zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4rT@hhPm4t-!L#RbOrc?xVjhkxOe>@3@B{k zjv@vI2Hlb%zhH)!AAhdBqt2wre)-wk21k~b_V_6$`}strw)7Ot%?vlVS}Ne}vCM4o z{_AJ7mxk!)r86)v&GK|{42d|rHvHwRRR%n)%hs@_h~6x@aIrA$$=~?*NvAJO+w|>O z`+Rv5MO#ZtU)9e1U1i@KmpI*S%VPPnd6~ELn+M0Px%=L17v0@H_1*GQt9GV^E*E{* zseXNOTKaL;^1Urz=Nx^u=l}i5_jas_nx@5HVDa8HN;19i;8*@B2PK>Cn66v4Zg%+L zvy5Ikxz}R2Mf^Wn?o8Rc{ZnnSS@oV;?XA~-xZj;Mr8nVT^@^IjrdvCIR`Oc@>al+j zCvwchgI`E7Ywo?;_`PQrzL_X7eb3+JpJNz9d_Di%PJhVsbR~mgqkr`NoX+Kvk_z$+ z6@5;AGrXHteCgCQ2NiXE@*kx^6be(7G=l*p$x%=EU6>!cmC~4x>WO18) zIQvITlCk7g?YVJcI_*z-W-~spz4yQ9&yGW1mUAXpnW?hyEia$5%gNi`^2{}*Fixf3 z+`nzY^V8xbts2?g!yYuB5-8t#`%kZ-+LiA+H?gdgxzu-dm#J3c&(qg8#|yRV^SpPw z6rlCNqtQ5#Z>7P8)W?#0nNt2vS;^34_-gg$C&smglNshZ-4o+yFXCjWTgLonMov7V zX42J{M&)`j9dngFC~=y$*T`gZUuR-+z0$O*yTu{bd2YL1T+2A8GrjPR`JZ`r%Zn5H=I$uC^3`eM zv~@PQUlRT=<^K5G|H-ZJ!$qB%o5lTaMqe&y3cvrq;OD)vzyH~NuW4w`byO{7U|?YI MboFyt=akR{016JplmGw# diff --git a/src/App.vue b/src/App.vue index e335e78..7c2860d 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,6 +5,7 @@ + @@ -15,6 +16,7 @@ import { IonApp, IonRouterOutlet, IonSplitPane } from '@ionic/vue' import { onBeforeUnmount, onMounted } from 'vue' import { useRouter } from 'vue-router' import AppMenu from './components/AppMenu.vue' +import MobileTabBar from './components/MobileTabBar.vue' import { links } from './router/links' const router = useRouter() diff --git a/src/components/MarkdownContent.vue b/src/components/MarkdownContent.vue new file mode 100644 index 0000000..acb4473 --- /dev/null +++ b/src/components/MarkdownContent.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/src/components/MobileTabBar.vue b/src/components/MobileTabBar.vue new file mode 100644 index 0000000..ac43396 --- /dev/null +++ b/src/components/MobileTabBar.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/src/components/PageHeader.vue b/src/components/PageHeader.vue index 6057d21..d5690c9 100644 --- a/src/components/PageHeader.vue +++ b/src/components/PageHeader.vue @@ -3,7 +3,7 @@ - + {{ title }} diff --git a/src/components/RecordHeader.vue b/src/components/RecordHeader.vue new file mode 100644 index 0000000..2394f21 --- /dev/null +++ b/src/components/RecordHeader.vue @@ -0,0 +1,124 @@ + + + + + diff --git a/src/components/UnknownRecord.vue b/src/components/UnknownRecord.vue new file mode 100644 index 0000000..1c7546d --- /dev/null +++ b/src/components/UnknownRecord.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/src/content/index.ts b/src/content/index.ts new file mode 100644 index 0000000..ef4ddf8 --- /dev/null +++ b/src/content/index.ts @@ -0,0 +1,4 @@ +export { localRecordLink, parseAtUri, safeCanonicalTangledUrl } from './links' +export type { RecordLinkContext } from './links' +export { renderMarkdown } from './markdown' +export type { MarkdownOptions } from './markdown' diff --git a/src/content/links.ts b/src/content/links.ts new file mode 100644 index 0000000..e8f8576 --- /dev/null +++ b/src/content/links.ts @@ -0,0 +1,55 @@ +import { links } from '@/router/links' +import type { RouteLocationRaw } from 'vue-router' + +export interface RecordLinkContext { + repo?: string +} + +const TANGLED_HOSTS = new Set(['tangled.org', 'www.tangled.org']) + +interface AtUriParts { + authority: string + collection: string + rkey: string +} + +export function parseAtUri(value: string): AtUriParts | undefined { + const match = /^at:\/\/([^/\s]+)\/([a-z][a-z0-9.-]+)\/([a-zA-Z0-9._~:%-]+)$/.exec(value) + if (!match) return undefined + + return { authority: match[1], collection: match[2], rkey: match[3] } +} + +/** Maps identifiers we understand to local views without constructing route strings. */ +export function localRecordLink(value: string, context: RecordLinkContext = {}): RouteLocationRaw | undefined { + const atUri = parseAtUri(value) + if (atUri) { + if (atUri.collection === 'sh.tangled.repo') return links.repository(value) + if (atUri.collection === 'sh.tangled.feed.string') return links.string(value) + return links.search(value) + } + + if (/^did:[a-z0-9]+:[^\s/]+$/i.test(value)) return links.profile(value) + if (/^@[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?\.[a-z]{2,}$/i.test(value)) return links.profile(value.slice(1)) + if (context.repo && /^#[a-zA-Z0-9._~:-]{1,512}$/.test(value)) return links.issue(context.repo, value.slice(1)) + + try { + const url = new URL(value) + if (url.protocol === 'https:' && TANGLED_HOSTS.has(url.hostname.toLowerCase())) return links.search(url.href) + } catch { + // Plain text is not a URL and needs no route. + } + + return undefined +} + +export function safeCanonicalTangledUrl(value: string | undefined): string | undefined { + if (!value) return undefined + + try { + const url = new URL(value) + return url.protocol === 'https:' && TANGLED_HOSTS.has(url.hostname.toLowerCase()) ? url.href : undefined + } catch { + return undefined + } +} diff --git a/src/content/markdown.ts b/src/content/markdown.ts new file mode 100644 index 0000000..bf989de --- /dev/null +++ b/src/content/markdown.ts @@ -0,0 +1,125 @@ +import type { RecordLinkContext } from '@/content/links' +import { localRecordLink } from '@/content/links' +import DOMPurify from 'dompurify' +import { markdownToHtml } from 'satteri' +import type { RouteLocationRaw } from 'vue-router' + +export interface MarkdownOptions extends RecordLinkContext { + resolveRoute?: (location: RouteLocationRaw) => string +} + +const ALLOWED_TAGS = [ + 'a', + 'blockquote', + 'br', + 'code', + 'del', + 'em', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'hr', + 'li', + 'ol', + 'p', + 'pre', + 'strong', + 'table', + 'tbody', + 'td', + 'th', + 'thead', + 'tr', + 'ul', +] + +const LINKABLE_TEXT = + /at:\/\/[^/\s]+\/[a-z][a-z0-9.-]+\/[a-zA-Z0-9._~:%-]+|did:[a-z0-9]+:[a-zA-Z0-9._:%-]+|@[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?\.[a-z]{2,}|#[a-zA-Z0-9._~:-]{1,512}/gi + +/** Compiles untrusted Markdown with Satteri, then applies a deliberately small HTML policy. */ +export function renderMarkdown(source: string, options: MarkdownOptions = {}): string { + const result = markdownToHtml(source, { features: { gfm: true } }) + const sanitized = DOMPurify.sanitize(result.html, { + ALLOWED_ATTR: ['href', 'title'], + ALLOWED_TAGS, + ALLOW_UNKNOWN_PROTOCOLS: false, + FORBID_ATTR: ['style'], + FORBID_TAGS: ['form', 'iframe', 'math', 'object', 'script', 'style', 'svg', 'template'], + ALLOWED_URI_REGEXP: /^(?:(?:https?|mailto|at|did):|#|\/|\.\.\/|\.\/)/i, + }) + + if (typeof document === 'undefined') return sanitized + + const template = document.createElement('template') + template.innerHTML = sanitized + linkExistingAnchors(template.content, options) + linkTextIdentifiers(template.content, options) + return template.innerHTML +} + +function linkExistingAnchors(root: DocumentFragment, options: MarkdownOptions): void { + for (const anchor of Array.from(root.querySelectorAll('a'))) { + const href = anchor.getAttribute('href') + if (!href) continue + + const local = localRecordLink(href, options) + if (local && options.resolveRoute) { + anchor.href = options.resolveRoute(local) + anchor.dataset.twistedLink = 'local' + continue + } + + if (/^https?:/i.test(href)) { + anchor.target = '_blank' + anchor.rel = 'noopener noreferrer' + continue + } + + if (!href.startsWith('#') && !href.startsWith('mailto:')) anchor.removeAttribute('href') + } +} + +function linkTextIdentifiers(root: DocumentFragment, options: MarkdownOptions): void { + const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT) + const nodes: Text[] = [] + let current = walker.nextNode() + while (current) { + const parent = current.parentElement + if (parent && !parent.closest('a, code, pre')) nodes.push(current as Text) + current = walker.nextNode() + } + + for (const node of nodes) { + const value = node.nodeValue ?? '' + const matches = [...value.matchAll(LINKABLE_TEXT)] + if (matches.length === 0) continue + + const fragment = document.createDocumentFragment() + let offset = 0 + for (const match of matches) { + const matchedText = match[0] + const text = matchedText.replace(/[.,!?;]+$/, '') + const trailingText = matchedText.slice(text.length) + const index = match.index ?? 0 + const local = localRecordLink(text, options) + if (!local || !options.resolveRoute) continue + + fragment.append(value.slice(offset, index)) + const anchor = document.createElement('a') + anchor.href = options.resolveRoute(local) + anchor.dataset.twistedLink = 'local' + anchor.textContent = text + fragment.append(anchor) + fragment.append(trailingText) + offset = index + matchedText.length + } + + if (offset > 0) { + fragment.append(value.slice(offset)) + node.replaceWith(fragment) + } + } +} diff --git a/src/theme/variables.css b/src/theme/variables.css index a1a12b7..66aa6fc 100644 --- a/src/theme/variables.css +++ b/src/theme/variables.css @@ -90,6 +90,9 @@ a { ion-split-pane { --border: 1px solid var(--app-border); + --side-max-width: 17.5rem; + --side-min-width: 17.5rem; + --side-width: 17.5rem; } ion-menu { @@ -110,6 +113,11 @@ ion-title { font-weight: 750; } +ion-menu-button, +ion-back-button { + --color: var(--app-text); +} + .page-frame { inline-size: min(100%, 84rem); margin-inline: auto; @@ -213,3 +221,13 @@ ion-title { animation-iteration-count: 1 !important; } } + +@media (max-width: 959px) { + ion-content { + --padding-bottom: calc(3.75rem + var(--safe-bottom)); + } + + .page-frame { + padding-block-end: calc(var(--space-10) + 3.75rem + var(--safe-bottom)); + } +} diff --git a/src/views/HomePage.vue b/src/views/HomePage.vue index 4e6b7f1..f23d72c 100644 --- a/src/views/HomePage.vue +++ b/src/views/HomePage.vue @@ -84,12 +84,12 @@ function search(): void { .home-page { display: grid; align-content: start; - gap: clamp(var(--space-10), 8vw, 7rem); + gap: clamp(var(--space-8), 6vw, 5rem); } .home-page__intro { max-inline-size: 52rem; - padding-block-start: clamp(var(--space-8), 8vh, 6rem); + padding-block-start: clamp(var(--space-6), 6vh, 4rem); } .home-page__eyebrow, @@ -105,10 +105,10 @@ function search(): void { max-inline-size: 10ch; margin: 0; font-family: var(--font-display); - font-size: clamp(3.25rem, 11vw, 7rem); + font-size: clamp(3rem, 7vw, 5.75rem); font-weight: 780; - letter-spacing: -0.07em; - line-height: 0.88; + letter-spacing: -0.06em; + line-height: 0.92; text-wrap: balance; } @@ -151,6 +151,7 @@ function search(): void { .home-page__search input { min-inline-size: 0; + min-block-size: 3rem; block-size: 100%; border: 0; padding: 0 var(--space-3); diff --git a/tests/e2e/specs/foundation.cy.ts b/tests/e2e/specs/foundation.cy.ts index 8bd38ae..26d7aa9 100644 --- a/tests/e2e/specs/foundation.cy.ts +++ b/tests/e2e/specs/foundation.cy.ts @@ -45,9 +45,28 @@ describe('Twisted foundation', () => { it('keeps recovery and navigation usable at a native-sized viewport', () => { cy.viewport(390, 844) cy.visit('/profiles/not%20valid') + cy.get('.mobile-tabs').should('be.visible') + cy.get('.mobile-tabs a').should('have.length', 4) + cy.get('ion-menu-button').should('be.visible') cy.contains('h2', 'This identifier is not supported') cy.contains('a', 'Return home').should('be.visible').click() cy.contains('h1', 'Follow the thread.') + cy.get('.mobile-tabs').contains('Search').click() + cy.location('pathname').should('equal', '/search') + cy.get('.mobile-tabs a[aria-current="page"]').should('contain.text', 'Search') + }) + + it('aligns the persistent desktop menu with the routed content', () => { + cy.viewport(1440, 900) + cy.visit('/') + cy.get('ion-menu').then(($menu) => { + cy.get('#main-content').then(($content) => { + const menuRight = $menu[0].getBoundingClientRect().right + const contentLeft = $content[0].getBoundingClientRect().left + expect(Math.abs(menuRight - contentLeft)).to.be.lessThan(2) + }) + }) + cy.get('.mobile-tabs').should('not.be.visible') }) it('offers recovery links for unknown deep links', () => { diff --git a/tests/unit/content/markdown.spec.ts b/tests/unit/content/markdown.spec.ts new file mode 100644 index 0000000..80a9bfb --- /dev/null +++ b/tests/unit/content/markdown.spec.ts @@ -0,0 +1,61 @@ +import router from '@/router' +import { renderMarkdown } from '@/content' +import { describe, expect, test } from 'vitest' + +const resolveRoute = (location: Parameters[0]) => router.resolve(location).href + +describe('renderMarkdown', () => { + test('removes executable HTML, SVG, styles, and unsafe links', () => { + const html = renderMarkdown(` +# Safe heading + + + + +

Text

+[unsafe](javascript:alert('link')) +![tracking pixel](https://tracker.example/pixel.png) + `) + const container = document.createElement('div') + container.innerHTML = html + + expect(html).toContain('

Safe heading

') + expect(html).toContain('

Text

') + expect(container.querySelector('script, svg, style, img')).toBeNull() + expect(container.querySelector('[style], [onclick]')).toBeNull() + expect(container.querySelector('a[href^="javascript:"]')).toBeNull() + }) + + test('routes identifiers, references, and Tangled links to local views', () => { + const repo = 'at://did:plc:owner/sh.tangled.repo/key' + const html = renderMarkdown( + `[Repository](${repo}) [Tangled](https://tangled.org/owner/repo)\n\nContact did:plc:reader or @reader.example about #3m.issue.`, + { repo, resolveRoute }, + ) + const container = document.createElement('div') + container.innerHTML = html + const anchors = [...container.querySelectorAll('a')] + + expect(anchors).toHaveLength(5) + expect(anchors.every((anchor) => anchor.dataset.twistedLink === 'local')).toBe(true) + expect(anchors.map((anchor) => anchor.getAttribute('href'))).toEqual([ + router.resolve({ name: 'repository', params: { repo } }).href, + router.resolve({ name: 'search', query: { q: 'https://tangled.org/owner/repo' } }).href, + router.resolve({ name: 'profile', params: { actor: 'did:plc:reader' } }).href, + router.resolve({ name: 'profile', params: { actor: 'reader.example' } }).href, + router.resolve({ name: 'issue', params: { repo, rkey: '3m.issue' } }).href, + ]) + }) + + test('opens ordinary web links safely and removes unsupported relative targets', () => { + const html = renderMarkdown('[docs](https://docs.tangled.org) [relative](../secrets) [section](#usage)') + const container = document.createElement('div') + container.innerHTML = html + const [external, relative, section] = [...container.querySelectorAll('a')] + + expect(external.getAttribute('target')).toBe('_blank') + expect(external.getAttribute('rel')).toBe('noopener noreferrer') + expect(relative.hasAttribute('href')).toBe(false) + expect(section.getAttribute('href')).toBe('#usage') + }) +}) diff --git a/tests/unit/content/record-components.spec.ts b/tests/unit/content/record-components.spec.ts new file mode 100644 index 0000000..5a0d7b4 --- /dev/null +++ b/tests/unit/content/record-components.spec.ts @@ -0,0 +1,76 @@ +import RecordHeader from '@/components/RecordHeader.vue' +import UnknownRecord from '@/components/UnknownRecord.vue' +import { flushPromises, mount } from '@vue/test-utils' +import { createMemoryHistory, createRouter } from 'vue-router' +import { beforeEach, describe, expect, test, vi } from 'vitest' + +const profile = { template: '
' } +const router = createRouter({ + history: createMemoryHistory(), + routes: [ + { path: '/', name: 'home', component: profile }, + { path: '/profiles/:actor', name: 'profile', component: profile }, + ], +}) + +describe('RecordHeader', () => { + beforeEach(async () => { + await router.push('/') + Object.defineProperty(navigator, 'clipboard', { + configurable: true, + value: { writeText: vi.fn().mockResolvedValue(undefined) }, + }) + }) + + test('copies the full identifier and exposes only canonical Tangled links', async () => { + const uri = 'at://did:plc:abc/sh.tangled.repo.issue/3m.test' + const wrapper = mount(RecordHeader, { + global: { plugins: [router] }, + props: { + uri, + collection: 'sh.tangled.repo.issue', + author: 'did:plc:abc', + canonicalUrl: 'https://tangled.org/owner/repo/issues/3m.test', + }, + }) + + await wrapper.get('button').trigger('click') + await flushPromises() + expect(navigator.clipboard.writeText).toHaveBeenCalledWith(uri) + expect(wrapper.get('button').text()).toContain('Copied') + expect(wrapper.get('.record-header__canonical').attributes()).toMatchObject({ + href: 'https://tangled.org/owner/repo/issues/3m.test', + rel: 'noopener noreferrer', + target: '_blank', + }) + }) + + test('does not render a non-Tangled canonical URL', () => { + const wrapper = mount(RecordHeader, { + global: { plugins: [router] }, + props: { + uri: 'at://did:plc:abc/example.record/key', + collection: 'example.record', + canonicalUrl: 'https://example.com/phishing', + }, + }) + + expect(wrapper.find('.record-header__canonical').exists()).toBe(false) + }) +}) + +describe('UnknownRecord', () => { + test('keeps unknown validated values inspectable as text', () => { + const wrapper = mount(UnknownRecord, { + global: { plugins: [router] }, + props: { + uri: 'at://did:plc:abc/example.record/key', + collection: 'example.record', + value: { content: '', count: 2 }, + }, + }) + + expect(wrapper.get('pre').text()).toContain('') + expect(wrapper.find('pre img').exists()).toBe(false) + }) +}) diff --git a/tests/unit/router.spec.ts b/tests/unit/router.spec.ts index 36ad2e0..f9c21b3 100644 --- a/tests/unit/router.spec.ts +++ b/tests/unit/router.spec.ts @@ -13,39 +13,42 @@ describe('application routes', () => { expect(resolved.params.repo).toBe(repo) }) - test('encodes handles, rkeys, and string AT-URIs through named routes', () => { - expect(router.resolve(links.profile('desertthunder.dev')).name).toBe('profile') - expect(router.resolve(links.issue('at://did:plc:abc/sh.tangled.repo/key', '3k.test')).name).toBe('issue') - expect(router.resolve(links.string('at://did:plc:abc/sh.tangled.feed.string/key')).name).toBe('string') - }) - - test('provides named builders for every opaque feature route', () => { - const actor = 'did:plc:abc' - const repo = 'at://did:plc:abc/sh.tangled.repo/key' - const locations = [ - [links.actorActivity(actor, 'issues'), 'actor-activity'], - [links.actorRelationships(actor, 'followers'), 'actor-relationships'], - [links.repository(repo), 'repository'], - [links.commits(repo, 'refs/heads/main', 'src/main.ts'), 'repository-commits'], - [links.commit(repo, 'abc123'), 'repository-commit'], - [links.branches(repo), 'repository-branches'], - [links.tags(repo), 'repository-tags'], - [links.diff(repo, 'refs/heads/main'), 'repository-diff'], - [links.compare(repo, 'main', 'feature/theme'), 'repository-compare'], - [links.issues(repo, { state: 'open' }), 'issues'], - [links.issue(repo, '3k.test'), 'issue'], - [links.pulls(repo, { status: 'open' }), 'pulls'], - [links.pull(repo, '3k.pull'), 'pull'], - [links.pipelines(repo, 'pipeline/key'), 'pipelines'], - [links.artifact(repo, 'artifact/key'), 'artifact'], - [links.string('at://did:plc:abc/sh.tangled.feed.string/key'), 'string'], - [links.knot('knot.example'), 'knot'], - [links.spindle('spindle/key'), 'spindle'], - [links.labels('at://did:plc:abc/sh.tangled.label.scope/key'), 'labels'], + test('round-trips opaque route values through shareable URLs', () => { + const repo = 'at://did:plc:abc/sh.tangled.repo/3mhø-%25-key' + const cases = [ + { + location: links.actorActivity('did:web:example.com', 'pull requests'), + params: { actor: 'did:web:example.com', activity: 'pull requests' }, + query: {}, + }, + { + location: links.diff(repo, 'refs/heads/feature/λ theme'), + params: { repo, ref: 'refs/heads/feature/λ theme' }, + query: {}, + }, + { + location: links.compare(repo, 'refs/tags/v1.0.0', 'feature/a b#c'), + params: { repo }, + query: { base: 'refs/tags/v1.0.0', head: 'feature/a b#c' }, + }, + { + location: links.issues(repo, { state: 'open', author: 'did:plc:a/b', label: 'good first issue' }), + params: { repo }, + query: { state: 'open', author: 'did:plc:a/b', label: 'good first issue' }, + }, + { + location: links.artifact(repo, 'build/linux arm64+debug.tgz'), + params: { repo, artifact: 'build/linux arm64+debug.tgz' }, + query: {}, + }, ] as const - for (const [location, name] of locations) { - expect(router.resolve(location).name).toBe(name) + for (const routeCase of cases) { + const href = router.resolve(routeCase.location).href + const shared = router.resolve(href) + + expect(shared.params).toEqual(routeCase.params) + expect(shared.query).toEqual(routeCase.query) } }) diff --git a/vite.config.ts b/vite.config.ts index a0808b0..49a487b 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,12 +1,14 @@ -import legacy from '@vitejs/plugin-legacy' import vue from '@vitejs/plugin-vue' import path from 'node:path' import { defineConfig } from 'vitest/config' /** Shared Vite application and Vitest unit-test configuration. */ const config = defineConfig({ - plugins: [vue(), legacy()], + plugins: [vue()], resolve: { alias: { '@': path.resolve(__dirname, './src') } }, + build: { target: 'esnext' }, + server: { headers: { 'Cross-Origin-Embedder-Policy': 'require-corp', 'Cross-Origin-Opener-Policy': 'same-origin' } }, + preview: { headers: { 'Cross-Origin-Embedder-Policy': 'require-corp', 'Cross-Origin-Opener-Policy': 'same-origin' } }, test: { clearMocks: true, globals: true,