From 01668ae06769ba930d025539e3f13a80d24cb7e6 Mon Sep 17 00:00:00 2001 From: Chee Aun Date: Fri, 22 May 2026 06:19:17 +0800 Subject: [PATCH 01/12] i18n updates (ca-ES,pt-BR) (#1520) * New translations (Catalan) * New translations (Portuguese, Brazilian) --- src/locales/ca-ES.po | 4 ++-- src/locales/pt-BR.po | 52 ++++++++++++++++++++++---------------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/locales/ca-ES.po b/src/locales/ca-ES.po index 1cb52e1dab..5ca9f6a2d3 100644 --- a/src/locales/ca-ES.po +++ b/src/locales/ca-ES.po @@ -8,7 +8,7 @@ msgstr "" "Language: ca\n" "Project-Id-Version: phanpy\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2026-05-19 09:37\n" +"PO-Revision-Date: 2026-05-21 20:52\n" "Last-Translator: \n" "Language-Team: Catalan\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" @@ -4200,7 +4200,7 @@ msgstr "Ajudeu a traduir" #: src/pages/settings.jsx:255 msgid "Keep navigation bars visible while scrolling" -msgstr "" +msgstr "Manté les barres de navegació visibles en desplaçar-se" #: src/pages/settings.jsx:263 msgid "Posting" diff --git a/src/locales/pt-BR.po b/src/locales/pt-BR.po index 1010a49ab9..e2c6616f15 100644 --- a/src/locales/pt-BR.po +++ b/src/locales/pt-BR.po @@ -8,7 +8,7 @@ msgstr "" "Language: pt\n" "Project-Id-Version: phanpy\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2026-05-19 15:00\n" +"PO-Revision-Date: 2026-05-21 22:18\n" "Last-Translator: \n" "Language-Team: Portuguese, Brazilian\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" @@ -118,7 +118,7 @@ msgstr "Seguindo" #: src/components/account-info-mini.jsx:106 #: src/components/account-info.jsx:879 msgid "{followingCount, plural, other {<0>{0} Following}}" -msgstr "{followingCount, plural, one {}other {<0>{0} seguindo}}" +msgstr "{followingCount, plural, other {<0>{0} seguindo}}" #. placeholder {0}: shortenNumber(statusesCount) #. placeholder {1}: shortenNumber(statusesCount) @@ -203,7 +203,7 @@ msgstr "Em memória" #. placeholder {3}: ( postingStats.boosts / postingStats.total ).toLocaleString(i18n.locale || undefined, { style: 'percent', }) #: src/components/account-info.jsx:960 msgid "{0} original posts, {1} replies, {2} quotes, {3} boosts" -msgstr "{0} posts originais, {1} respostas, {2} citações, {3} impulsos" +msgstr "{0} publicações originais, {1} respostas, {2} citações, {3} impulsos" #. placeholder {0}: ( postingStats.originals / postingStats.total ).toLocaleString(i18n.locale || undefined, { style: 'percent', }) #. placeholder {1}: ( postingStats.replies / postingStats.total ).toLocaleString(i18n.locale || undefined, { style: 'percent', }) @@ -418,7 +418,7 @@ msgstr "Adicionar" #: src/components/compose-poll.jsx:96 msgid "Multiple choice" -msgstr "Múltipla escolha" +msgstr "Múltiplas opções" #: src/components/compose-poll.jsx:99 msgid "Duration" @@ -1084,7 +1084,7 @@ msgstr "Detalhes da publicação" #: src/components/keyboard-shortcuts-help.jsx:101 msgid "Open media or post details" -msgstr "Abrir detalhes do post ou mídia" +msgstr "Abrir detalhes da publicação ou mídia" #: src/components/keyboard-shortcuts-help.jsx:106 msgid "Expand content warning or<0/>toggle expanded/collapsed thread" @@ -1188,23 +1188,23 @@ msgstr "<0>Shift + <1>Alt + <2>k" #: src/components/keyboard-shortcuts-help.jsx:210 msgid "Go to Home" -msgstr "Ir para página inicial" +msgstr "Página inicial" #: src/components/keyboard-shortcuts-help.jsx:214 msgid "Go to Notifications" -msgstr "Ir para notificações" +msgstr "Notificações" #: src/components/keyboard-shortcuts-help.jsx:218 msgid "Go to Settings" -msgstr "Ir para configurações" +msgstr "Opções" #: src/components/keyboard-shortcuts-help.jsx:222 msgid "Go to Profile" -msgstr "Ir para perfil" +msgstr "Perfil" #: src/components/keyboard-shortcuts-help.jsx:226 msgid "Go to Bookmarks" -msgstr "Ir aos Favoritos" +msgstr "Favoritos" #: src/components/list-add-edit.jsx:41 msgid "Edit list" @@ -1664,7 +1664,7 @@ msgstr "A enquete que você votou já acabou." #: src/components/notification.jsx:204 msgid "{account} edited a post." -msgstr "{account} editou um post." +msgstr "{account} editou uma publicação." #: src/components/notification.jsx:206 msgid "A post you interacted with has been edited." @@ -1678,12 +1678,12 @@ msgstr "{count, plural, =1 {{postsCount, plural, =1 {{postType, select, reply {{ #: src/components/notification.jsx:258 msgid "{account} edited a post you have quoted." -msgstr "{account} editou um post que você citou." +msgstr "{account} editou uma publicação citada." #. placeholder {0}: shortenNumber(count) #: src/components/notification.jsx:261 msgid "{count, plural, =1 {{account} signed up.} other {<0><1>{0} people signed up.}}" -msgstr "{count, plural, one {}=1 {{account} signed up.} other {<0><1>{0} people signed up.}}" +msgstr "{count, plural, =1 {{account} registrou-se.} other {<0><1>{0}pessoas registraram-se.}}" #: src/components/notification.jsx:275 msgid "{account} reported {targetAccount}" @@ -1793,7 +1793,7 @@ msgstr "Impossível copiar o link" #: src/components/open-link-sheet.jsx:56 msgid "Open link?" -msgstr "Abrir link?" +msgstr "Acessar link?" #: src/components/open-link-sheet.jsx:78 #: src/components/post-embed-modal.jsx:232 @@ -1811,7 +1811,7 @@ msgstr "Compartilhar…" #: src/components/open-link-sheet.jsx:92 msgid "Open" -msgstr "Abrir" +msgstr "Acessar" #: src/components/poll.jsx:160 msgid "{optionVotesCount, plural, one {# vote} other {# votes}}" @@ -1832,11 +1832,11 @@ msgstr "Ocultar resultado" #: src/components/poll.jsx:290 #: src/components/poll.jsx:306 msgid "{0, plural, one {# choice} other {# choices}}" -msgstr "{0, plural, one {# choice} other {# choices}}" +msgstr "{0, plural, one {# opção} other {# opções}}" #: src/components/poll.jsx:222 msgid "Unable to vote in poll" -msgstr "Incapaz de votar na enquete" +msgstr "Não foi possível votar na enquete" #: src/components/poll.jsx:279 msgid "Vote" @@ -1948,11 +1948,11 @@ msgstr "Nota: Esta prévia tem um estilo levemente padronizado." #: src/components/private-note-sheet.jsx:41 #: src/components/related-actions.jsx:232 msgid "Notes" -msgstr "Anotações" +msgstr "Notas" #: src/components/private-note-sheet.jsx:44 msgid "Only visible to you" -msgstr "Apenas visível para você" +msgstr "Somente visível para você" #: src/components/private-note-sheet.jsx:69 msgid "Unable to update private note." @@ -1965,33 +1965,33 @@ msgstr "Salvar e fechar" #: src/components/qr-code-modal.jsx:26 #: src/components/shortcuts-settings.jsx:849 msgid "Scan QR code" -msgstr "Escanear código QR" +msgstr "Escanear QR code" #: src/components/qr-scanner-modal.jsx:263 msgid "Unable to access camera. Please check permissions." -msgstr "Incapaz de acessar a câmera. Por favor, cheque as permissões." +msgstr "Não foi possível abrir a câmera. Verifique as permissões." #: src/components/quote-chain-modal.jsx:107 msgid "Quote chain" -msgstr "Sequência de citações" +msgstr "Cadeia de citações" #: src/components/quote-chain-modal.jsx:151 msgid "Failed to unwrap quote chain" -msgstr "Falha ao desenrolar sequência de citações" +msgstr "Falhou ao expandir cadeia de citações" #: src/components/quote-chain-modal.jsx:165 msgid "Continue unwrapping…" -msgstr "Continuar desenrolando…" +msgstr "Expandir…" #: src/components/quote-settings-sheet.jsx:37 #: src/pages/settings.jsx:341 msgid "Quote settings updated" -msgstr "Configurações de citação atualizadas" +msgstr "Opções de citação atualizadas" #: src/components/quote-settings-sheet.jsx:47 #: src/pages/settings.jsx:343 msgid "Failed to update quote settings" -msgstr "Falha na atualização de configurações de citação" +msgstr "Falhou ao atualizar opções de citação" #: src/components/quote-settings-sheet.jsx:66 msgid "Quote settings for this post" From 5b31274e13772f4fa155e4994046458b59fe9d0f Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Sat, 23 May 2026 10:12:09 +0800 Subject: [PATCH 02/12] Upgrade deps --- package-lock.json | 485 +++++++++++++++++++++++----------------------- package.json | 32 +-- 2 files changed, 259 insertions(+), 258 deletions(-) diff --git a/package-lock.json b/package-lock.json index daa61fd942..2df720198e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,33 +10,33 @@ "hasInstallScript": true, "dependencies": { "@formatjs/intl-localematcher": "~0.8.8", - "@formatjs/intl-segmenter": "~12.2.7", + "@formatjs/intl-segmenter": "~12.2.8", "@formkit/auto-animate": "~0.9.0", "@github/text-expander-element": "~2.9.4", "@iconify-json/mingcute": "~1.2.7", "@justinribeiro/lite-youtube": "~1.9.0", - "@lingui/detect-locale": "~6.0.1", - "@lingui/react": "~6.0.1", + "@lingui/detect-locale": "~6.1.0", + "@lingui/react": "~6.1.0", "@szhsin/react-menu": "~4.5.1", "chroma-js": "~3.2.0", "compare-versions": "~6.1.1", - "exifreader": "~4.38.1", + "exifreader": "~4.39.1", "fast-blurhash": "~1.1.4", "fast-equals": "~6.0.0", "flexsearch": "~0.8.212", "fuse.js": "~7.3.0", "gifuct-js": "~2.1.2", "html-prettify": "~1.0.7", - "idb-keyval": "~6.2.2", + "idb-keyval": "~6.2.4", "intl-locale-textinfo-polyfill": "~3.0.0", - "js-cookie": "~3.0.5", + "js-cookie": "~3.0.7", "just-debounce-it": "~3.2.0", "lz-string": "~1.5.0", "masto": "~7.11.1", "micro-memoize": "~5.1.1", - "p-queue": "~9.2.0", + "p-queue": "~9.3.0", "p-retry": "~8.0.0", - "preact": "10.29.1", + "preact": "10.29.2", "punycode": "~2.3.1", "qr": "~0.6.0", "react-hotkeys-hook": "~5.2.4", @@ -44,7 +44,7 @@ "react-quick-pinch-zoom": "~5.1.1", "react-router-dom": "6.6.2", "swiped-events": "~1.2.0", - "temml": "~0.13.2", + "temml": "~0.13.3", "tinyld": "~1.3.4", "toastify-js": "~1.12.0", "uid": "~2.0.2", @@ -58,20 +58,20 @@ "@emnapi/core": "~1.10.0", "@emnapi/runtime": "~1.10.0", "@iconify/utils": "~3.1.3", - "@lingui/babel-plugin-lingui-macro": "~6.0.1", - "@lingui/cli": "~6.0.1", - "@lingui/vite-plugin": "~6.0.1", + "@lingui/babel-plugin-lingui-macro": "~6.1.0", + "@lingui/cli": "~6.1.0", + "@lingui/vite-plugin": "~6.1.0", "@playwright/test": "~1.60.0", "@preact/preset-vite": "~2.10.5", - "@types/node": "~25.8.0", - "oxfmt": "~0.49.0", - "postcss": "~8.5.14", + "@types/node": "~25.9.1", + "oxfmt": "~0.51.0", + "postcss": "~8.5.15", "postcss-dark-theme-class": "~2.0.0", "postcss-preset-env": "~11.3.0", "prop-types": "^15.8.1", "sonda": "~0.11.1", "twitter-text": "~3.1.0", - "vite": "~8.0.13", + "vite": "~8.0.14", "vite-plugin-generate-file": "~0.3.1", "vite-plugin-html-config": "~2.0.2", "vite-plugin-pwa": "~1.3.0", @@ -85,6 +85,7 @@ "workbox-strategies": "~7.4.1" }, "engines": { + "node": ">=22.19.0", "npm": ">=10.3.0 <11.5.0" } }, @@ -3201,9 +3202,9 @@ } }, "node_modules/@formatjs/intl-segmenter": { - "version": "12.2.7", - "resolved": "https://registry.npmjs.org/@formatjs/intl-segmenter/-/intl-segmenter-12.2.7.tgz", - "integrity": "sha512-fukQs4CP7pUM2km4mn7laHNNJewS3RB0v0wP50gV43THf1I3yRECyehDqQHxpj/kmOAYOdCmJs8Tw60grmSs+w==", + "version": "12.2.8", + "resolved": "https://registry.npmjs.org/@formatjs/intl-segmenter/-/intl-segmenter-12.2.8.tgz", + "integrity": "sha512-zQPS2yENJA2Snpx3RmZd1eMt+gFc9y3IibtFxzhhXvcGA0oDr350eJZA+jMt18rEBZ2P5exEqhTA9xKEb1c7Ig==", "license": "MIT", "dependencies": { "@formatjs/intl-localematcher": "0.8.8" @@ -3366,9 +3367,9 @@ "license": "MIT" }, "node_modules/@lingui/babel-plugin-extract-messages": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-6.0.1.tgz", - "integrity": "sha512-E9quPJxYZFz2f1t8lRyPILWKrqrUI32EYBQMjC9CcneKh9ZLtvm7K1IAM+tPMYW5BDDqlXIVr8XHhGrkv/3OSA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-6.1.0.tgz", + "integrity": "sha512-CRlWvISWj9WTS42j0Kz4suNSC8yP45kcmlnaes9vL2Y3hKeh1Uds74KZVIblHpEDSKxxQTQJdgGG37xxKfKcYw==", "dev": true, "license": "MIT", "engines": { @@ -3376,24 +3377,24 @@ } }, "node_modules/@lingui/babel-plugin-lingui-macro": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-lingui-macro/-/babel-plugin-lingui-macro-6.0.1.tgz", - "integrity": "sha512-ZVsi04ZeqkvOfLn+fVZPEv6//SKHvrJlD+T0oJWDdymMKQVGsuFUSHFq3eFBpKilPMzYSCCj0wHgmljdUQionw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@lingui/babel-plugin-lingui-macro/-/babel-plugin-lingui-macro-6.1.0.tgz", + "integrity": "sha512-f0ZIdt4ia01fr3Zjn8b7z3+LLGArNudY/t4rLkz4nFWzDKaIRgv/dHABdSnjTU6w5DtGcwU8ijbPIv6dGG2rag==", "license": "MIT", "dependencies": { "@babel/core": "^7.20.12", "@babel/types": "^7.20.7", - "@lingui/conf": "6.0.1", - "@lingui/message-utils": "6.0.1" + "@lingui/conf": "6.1.0", + "@lingui/message-utils": "6.1.0" }, "engines": { "node": ">=22.19.0" } }, "node_modules/@lingui/cli": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@lingui/cli/-/cli-6.0.1.tgz", - "integrity": "sha512-xojK0f0JjgcZArNU4m3vydhG+ngQOxbovV8wDav3TT1R8PXSvKrmGfCoPffQczpbl86/0NOSdvteN8Da5MQlqg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@lingui/cli/-/cli-6.1.0.tgz", + "integrity": "sha512-v1YA86vZMUyFG7Gbo2dKBLY6HX2aAoKwCGdXbtscFD0rAhHbs3UkzMwa3lWxiZHY2LpgZK7CCI3npKiBUTgrOg==", "dev": true, "license": "MIT", "dependencies": { @@ -3401,12 +3402,12 @@ "@babel/generator": "^7.28.5", "@babel/parser": "^7.22.0", "@babel/types": "^7.21.2", - "@lingui/babel-plugin-extract-messages": "6.0.1", - "@lingui/babel-plugin-lingui-macro": "6.0.1", - "@lingui/conf": "6.0.1", - "@lingui/core": "6.0.1", - "@lingui/format-po": "6.0.1", - "@lingui/message-utils": "6.0.1", + "@lingui/babel-plugin-extract-messages": "6.1.0", + "@lingui/babel-plugin-lingui-macro": "6.1.0", + "@lingui/conf": "6.1.0", + "@lingui/core": "6.1.0", + "@lingui/format-po": "6.1.0", + "@lingui/message-utils": "6.1.0", "chokidar": "5.0.0", "cli-table3": "^0.6.5", "commander": "^14.0.2", @@ -3912,9 +3913,9 @@ } }, "node_modules/@lingui/conf": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-6.0.1.tgz", - "integrity": "sha512-6NJIOTh7Pt1MXMNkUsxjA6tlKX7LB1QLh/A5H3a1SmZTSZgcbes/BvF4lEh7zAfhNIU5A5Y8PljX+n4fBGO7Hg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@lingui/conf/-/conf-6.1.0.tgz", + "integrity": "sha512-GkgtaoersJxlTUsYLIHNbQIJuPEdtV/RcLAefT+0XZhVSn55CJRL9H0eYdOBNJtev0k7YuAKG+dPnFRaI7sYlg==", "license": "MIT", "dependencies": { "jest-validate": "^29.4.3", @@ -3927,13 +3928,13 @@ } }, "node_modules/@lingui/core": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@lingui/core/-/core-6.0.1.tgz", - "integrity": "sha512-3dtvQmPv7qpu6j4SwX8h/TQu3ADujdw9/ZV3qb6OwsYa0AhBUPaydVGOEDvkNA7v/fQh6CNUc6qqZrBbDBvdHA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@lingui/core/-/core-6.1.0.tgz", + "integrity": "sha512-5ZUR809ODdQ6DGyAyrIw/iPNCbhnknhWI/4w9S9BCtf1fx3LoqtBdb4ADSJ6OHz7kTvIgOZQPIAdPW/FtZui9w==", "license": "MIT", "dependencies": { - "@lingui/babel-plugin-lingui-macro": "6.0.1", - "@lingui/message-utils": "6.0.1" + "@lingui/babel-plugin-lingui-macro": "6.1.0", + "@lingui/message-utils": "6.1.0" }, "engines": { "node": ">=22.19.0" @@ -3948,23 +3949,23 @@ } }, "node_modules/@lingui/detect-locale": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@lingui/detect-locale/-/detect-locale-6.0.1.tgz", - "integrity": "sha512-pQS8Y2Ho09llqs9YvFXUkouxQZd7VNl9F77a7PpOWd/pKKrJZyCzgPu7Kw3mr+zcbg2owBTzdIfoXfv1BXQUmg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@lingui/detect-locale/-/detect-locale-6.1.0.tgz", + "integrity": "sha512-hkhBwwyxDJbsc2/iUzxj1acDMfBkiVJOLF+e1D1L/UhbtELx2eDwpgr2HMZ3pPzbgzZUDGymzgW6HDsZ4lJPzA==", "license": "MIT", "engines": { "node": ">=22.19.0" } }, "node_modules/@lingui/format-po": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@lingui/format-po/-/format-po-6.0.1.tgz", - "integrity": "sha512-kt3naP/2kpAPJ4dwwFnkhbvR5XkGaNdbK8W6ofpIJFhY3MvGZJ9rYY0KMp++3DAaXf7r6tHq0W0To3akSDejvg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@lingui/format-po/-/format-po-6.1.0.tgz", + "integrity": "sha512-oMpd7l82xxpMPAnfw8Hk8x/GG4IDSlonYlhlqIWhTWbV0lpAtrmlCDq0TXeTO43MvAm53jkpwWzIKBI14seZZw==", "dev": true, "license": "MIT", "dependencies": { - "@lingui/conf": "6.0.1", - "@lingui/message-utils": "6.0.1", + "@lingui/conf": "6.1.0", + "@lingui/message-utils": "6.1.0", "pofile": "^1.1.4" }, "engines": { @@ -3972,9 +3973,9 @@ } }, "node_modules/@lingui/message-utils": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@lingui/message-utils/-/message-utils-6.0.1.tgz", - "integrity": "sha512-cw1X5mqDODbYDkwvA9i6/4j7Ix0ptl+E9RfhBRLI2NsoLzHHX+ePryGkShFdUHYsDL+C9qkq8W0drgRVEl9LgA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@lingui/message-utils/-/message-utils-6.1.0.tgz", + "integrity": "sha512-AYbUVx/1CnLLFHQWAU/ljczknIqepUZuYChcNJCOd/LzFM0jASgXRmzieP156V8EctBXNNIR145rw0HtJ1jmew==", "license": "MIT", "dependencies": { "@messageformat/date-skeleton": "^1.1.0", @@ -3986,13 +3987,13 @@ } }, "node_modules/@lingui/react": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@lingui/react/-/react-6.0.1.tgz", - "integrity": "sha512-Pjj77gdZEINsqTvnNtHZTtU+xlgCK3lFKUd4fXMcIo8q7snkdmD8SB/EBJB28s+e5ZEcmFi5dfS4ekc5scQvPA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@lingui/react/-/react-6.1.0.tgz", + "integrity": "sha512-PKTMyXgIfcmjURONBQmWV7U3IwxWA9gSRqh9gxP2Pr84Kslcyly+4ov7uqJNg/sy3L0qegsjReAXc9bR7Q73Kw==", "license": "MIT", "dependencies": { - "@lingui/babel-plugin-lingui-macro": "6.0.1", - "@lingui/core": "6.0.1" + "@lingui/babel-plugin-lingui-macro": "6.1.0", + "@lingui/core": "6.1.0" }, "engines": { "node": ">=22.19.0" @@ -4008,14 +4009,14 @@ } }, "node_modules/@lingui/vite-plugin": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@lingui/vite-plugin/-/vite-plugin-6.0.1.tgz", - "integrity": "sha512-RgHkaC76p8NLj2DqA4JqC1/+pFIZWSkv4dJm/D8O+GSoJlst7WMl4h08qpPpAdTKgZpDZB8d22O6ejFohe6PTw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@lingui/vite-plugin/-/vite-plugin-6.1.0.tgz", + "integrity": "sha512-kIm8Z6QfYOQjbN+Gxx3JnGqR57VKq1xn/bD2ybtH8jtrzYqFJXOw2oAtXMl1Q+tOSkpOYNMB/w/OYCYpwXwgkQ==", "dev": true, "license": "MIT", "dependencies": { - "@lingui/cli": "6.0.1", - "@lingui/conf": "6.0.1" + "@lingui/cli": "6.1.0", + "@lingui/conf": "6.1.0" }, "engines": { "node": ">=22.19.0" @@ -4086,9 +4087,9 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.130.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.130.0.tgz", - "integrity": "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==", + "version": "0.132.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.132.0.tgz", + "integrity": "sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==", "dev": true, "license": "MIT", "funding": { @@ -4096,9 +4097,9 @@ } }, "node_modules/@oxfmt/binding-android-arm-eabi": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.49.0.tgz", - "integrity": "sha512-HbifJ84prIh9+55CTPAU35JdRQrwg47y16cGerCC+iejSKOuHXYo2WDql6l7cQlzrYVtc3f4UWY+dBj2lRmOeA==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.51.0.tgz", + "integrity": "sha512-Ni0sCqg5CIHaLIYFGj+ncbcumylvNC6FE4rfD0KfdmnWHbPJ+zev0qZCXKxy2hFVa0fYRK0yPzf5nzPbkZou7g==", "cpu": [ "arm" ], @@ -4113,9 +4114,9 @@ } }, "node_modules/@oxfmt/binding-android-arm64": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.49.0.tgz", - "integrity": "sha512-Ef7SKJqAaH2d7E6eXZZa2OffIShbhFMxnGK0zd93p4qiyTJr75B0qf7lrPD+qQOwcf04BrjYJ0JUxq8d5+yZwg==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.51.0.tgz", + "integrity": "sha512-eu5lAZjuo0KAkp+M24EhDqfOwA8owQ8d7wyBlOUUGRbDLHpU3IRlDHp8Dif+YqGlxs6jra7yS6WQu/NkPhAxeg==", "cpu": [ "arm64" ], @@ -4130,9 +4131,9 @@ } }, "node_modules/@oxfmt/binding-darwin-arm64": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.49.0.tgz", - "integrity": "sha512-8x5DN9CsFfb432sHa9NyqX5XisGUdA53LPEGSdv/VniS+v4uEOR8Orv7A9QSB98Xxgp0t6r31DzQA/wpIobGqQ==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.51.0.tgz", + "integrity": "sha512-6LsUNIdURhhcIfIn8+xsOb61mSTa9msAHTeSGx9Jf4rsP/gN8PGCF+SKWPAQZbND2w/WBkqQ6303jqEEIXzMdQ==", "cpu": [ "arm64" ], @@ -4147,9 +4148,9 @@ } }, "node_modules/@oxfmt/binding-darwin-x64": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.49.0.tgz", - "integrity": "sha512-e0+DSVzk4ewhMVKNYDaRTmP81jNMBWR1X9al0cVKWS+hDM/dElNqD5zjTOCuLOZc4oOdp2Gx2ldrVL+yYo9TZQ==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.51.0.tgz", + "integrity": "sha512-9aUMGmVxdHjYMsEAW1tNRoieTJXlVNDFkRvIR1J7LttJXWjVYCu2ekclLij2KJtxBxSQOYSHd12ME/adVGVbZg==", "cpu": [ "x64" ], @@ -4164,9 +4165,9 @@ } }, "node_modules/@oxfmt/binding-freebsd-x64": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.49.0.tgz", - "integrity": "sha512-W+mjtYtrQvFbXT/uNT+221OBhGRZ8UqNsLxjTWsjZ4GsQnRdvRC/N2NCK86BcamWr7lsTxwpwN3PULnr78sgcQ==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.51.0.tgz", + "integrity": "sha512-mkY1nhZTqYb+NHaAWxOCKISN6FwdrwMNsu17vTUA3wzUV2VJ+Paq15ZokRcsMU/2PUdHO73prxyeJpjXQ3MPpQ==", "cpu": [ "x64" ], @@ -4181,9 +4182,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm-gnueabihf": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.49.0.tgz", - "integrity": "sha512-Rtv6UevV7czDlLqil+NZUe4d8gs8jQo/zScSpumwyf7I+fSdLc+hc8AF3MQC7ymxSMMD9+vfiqQlsIf7wOAzXA==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.51.0.tgz", + "integrity": "sha512-wtFwNwE4+YCNuPaWoGDZeGsKvD6D1YSUNBJNn/rJBh7CrDBThFE+TBI5kY7vRW9rIOQRsbW2IpyyL3Du4Zqwiw==", "cpu": [ "arm" ], @@ -4198,9 +4199,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm-musleabihf": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.49.0.tgz", - "integrity": "sha512-sBi+8C/Q/MdKa5FL8ibAUCdhFBGFH7HFN/Qoyd5xQbZ/0ky3NMPpKfIBpaH0lhK2dXkGLczVQUoZ+xuNSerCdQ==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.51.0.tgz", + "integrity": "sha512-rnOaNx86G7iRKM6lsCIQMux0SMGNC/TEbFR+r7lpruJ12bnrIWgxd5w1PLqOvgR9r8ZJbpK/zfRKctJnh8/Jfg==", "cpu": [ "arm" ], @@ -4215,9 +4216,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm64-gnu": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.49.0.tgz", - "integrity": "sha512-JIfWenFhlzx+O8YygyZhoHFzTsdgDhxhbDRnE2iJLnnM5pWKScFvPECO2vOlA7JqJ/9S1g3uzEKuRCkHFwTjvA==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.51.0.tgz", + "integrity": "sha512-jOgDzSqWcICGRjsp4mc08FxKMN8vzP2Kgs4E0d2HUP99F+nJDQKklRV4Zuj+0gcBgjrzx2CbpqaIdUVPepCojA==", "cpu": [ "arm64" ], @@ -4235,9 +4236,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm64-musl": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.49.0.tgz", - "integrity": "sha512-iNzkMPG18jPkwBOZ4/HEjwqfzAjq4RrUQ0CgId/fC1ENvYD5jLVAaU/gWgpiqP1ys07kxSsSggDd1fp3E7mQHw==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.51.0.tgz", + "integrity": "sha512-KBUCdrH5bwVrAvI9gU/1S55oH6fzXjr++J/oVocdu7bYTks1l7DNNT+rLd/1TDdAEjObGwmfWamn7LC1m8A0DQ==", "cpu": [ "arm64" ], @@ -4255,9 +4256,9 @@ } }, "node_modules/@oxfmt/binding-linux-ppc64-gnu": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.49.0.tgz", - "integrity": "sha512-BPHA/NN3LvoIXiid+iz3BHt5V0Rzx0tXAqRUovwE1NsbDaLG9e8mtv7evDGRIkVQacqTDBv0XL25THHsxSJosQ==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.51.0.tgz", + "integrity": "sha512-NapfjYsABFqTJ1Dn9Efq6sN5esaHconVKwVLbDGNQLrwpOx/g17mkwErHzU72PutL67nf3wNAkbq122H+zLxag==", "cpu": [ "ppc64" ], @@ -4275,9 +4276,9 @@ } }, "node_modules/@oxfmt/binding-linux-riscv64-gnu": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.49.0.tgz", - "integrity": "sha512-3Eroshe+s69htC9JIL0+zLGQczLtRKezkMhwqQC21VC5Z/fuLvzLfbAOLgJLUq601H8gDYjy7deYycfOBjCvWg==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.51.0.tgz", + "integrity": "sha512-5dlDt1dUZCVi6elIhiK1PWg9wpTzTcIuj0IZnSurvIoMrhOWqqTcc1dSTxcSkNaBZhfsNqRZdINI1zAgbKkJNQ==", "cpu": [ "riscv64" ], @@ -4295,9 +4296,9 @@ } }, "node_modules/@oxfmt/binding-linux-riscv64-musl": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.49.0.tgz", - "integrity": "sha512-fnaERGgsxGm0lKAmO72EYR4BA3qBnzBTJBTi6EtUMq1D4R7EexRBMU4voXnx4TXla3SEDl9x4uNp/18SbkPjGg==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.51.0.tgz", + "integrity": "sha512-pgdWUJn0S5nulyiVdlFV8DzCUnGXkU99W5PSkkmbaZW+LrZBPxpezun4G0DDHbQaVYuJeCuKsXsGKGo77CkUTQ==", "cpu": [ "riscv64" ], @@ -4315,9 +4316,9 @@ } }, "node_modules/@oxfmt/binding-linux-s390x-gnu": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.49.0.tgz", - "integrity": "sha512-rBwasMl1Uul1MCCeTGEFKnOTL7VUxHf+634jWStrQAbzpBJgd5Yz5m4F7exVCsoI8PHn57dNjssXagXLCLB5yA==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.51.0.tgz", + "integrity": "sha512-2XTFUe97CbDGAI8vjwDfZ1HdakO0XIADyJ24idEg64SC4/K4in/OisXVnrW4NMK7I6TgC7EqRhC0Ln/nKhAemA==", "cpu": [ "s390x" ], @@ -4335,9 +4336,9 @@ } }, "node_modules/@oxfmt/binding-linux-x64-gnu": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.49.0.tgz", - "integrity": "sha512-BoC/F9xHe2y/deuBGA5Aw7bes07OD2gcL2wlpzTrfImR92vPP7S/k3LBTyspQZCNIVNdagkELcqKELwMLGIfAg==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.51.0.tgz", + "integrity": "sha512-kQ1OuCqqt/yyf0ZN9VFxW1/JnlgJgii3Dr7pWf9vNBvrX1hv6g39/+mc5oGRHRGJFZtl3zsGDWR9c5N2B/gwBw==", "cpu": [ "x64" ], @@ -4355,9 +4356,9 @@ } }, "node_modules/@oxfmt/binding-linux-x64-musl": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.49.0.tgz", - "integrity": "sha512-umY6jFADAo/oztFKl8D/S6vSrG6oBpEskcentiRuz42kZVU2kfDXMWCYavxyZR2bwPjqkHpcHZ6EZFiH3Qj9ZA==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.51.0.tgz", + "integrity": "sha512-ARTYqxHF475o96Gbn41hvSWSSRygPlRDXZZgZ9I2scU1y0qiWpCQyZCoefaQa0mwv+wwtZ+luS4YOzsRzM/izg==", "cpu": [ "x64" ], @@ -4375,9 +4376,9 @@ } }, "node_modules/@oxfmt/binding-openharmony-arm64": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.49.0.tgz", - "integrity": "sha512-J85zQMiw2pXiGPK+OusmDvSnJ/dgpgN7VgmB2zOBtgS8F+nsOUfSg9ZEBrwbQscjZ7tkPbm38CG4VF5f53MsiA==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.51.0.tgz", + "integrity": "sha512-QiC1XrCl6a6BmqMzduO8hdIRMf1m44hCkt2Q68KWkTvUB/E7fd2iomyNh6KnnRca5w6eBrRAAtLFqTh+xjsjJA==", "cpu": [ "arm64" ], @@ -4392,9 +4393,9 @@ } }, "node_modules/@oxfmt/binding-win32-arm64-msvc": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.49.0.tgz", - "integrity": "sha512-38K67XR++CoFFORDd4sMFwUVAnD6msYBdGTei+qvKGrRPO6S2PbrYPNL/eQQ1RgnnxOegNba0YQwg6uRkNcw6A==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.51.0.tgz", + "integrity": "sha512-NC/hJb9dtU23Zf8L7IVK95xnFjiQ7AfcLO2l5pb69TDEr958qxrtnB2CveeeNSCBFNIkgaTCfd/vHNSoG78l9g==", "cpu": [ "arm64" ], @@ -4409,9 +4410,9 @@ } }, "node_modules/@oxfmt/binding-win32-ia32-msvc": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.49.0.tgz", - "integrity": "sha512-rXVe0HICwQF0dBgbQtBCoYf8x/SidPIdhyQl+iPuJlV7suV+qDv7yUEB3wQ4qC3nOeNxz287SwFXKzyr0kWgEg==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.51.0.tgz", + "integrity": "sha512-2C45za4Rj36n8YIbhRL1PQbxmXJYf81WEcAgvj5I4ptRROG+A+81hREEN5bmCHADE1UfYaN312U6tkILoZZy6w==", "cpu": [ "ia32" ], @@ -4426,9 +4427,9 @@ } }, "node_modules/@oxfmt/binding-win32-x64-msvc": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.49.0.tgz", - "integrity": "sha512-gwWLwSEmBBfIK/Wh7GGd658161o4RKAvHWRaRQbJm571iQXGKfyr7UKsI1vsWvDlNLc30CxJDc8mMmCvJ/kczQ==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.51.0.tgz", + "integrity": "sha512-73RqdAuVKQTkjZIDw08JaDHUM4lav5Qu+CaPwg4QbbA7k8o7LEW0p3UsfZ/F8dsO/pwVYh3RzFcanwLRTTahbQ==", "cpu": [ "x64" ], @@ -4560,9 +4561,9 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.1.tgz", - "integrity": "sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.2.tgz", + "integrity": "sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ==", "cpu": [ "arm64" ], @@ -4577,9 +4578,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.1.tgz", - "integrity": "sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.2.tgz", + "integrity": "sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w==", "cpu": [ "arm64" ], @@ -4594,9 +4595,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.1.tgz", - "integrity": "sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.2.tgz", + "integrity": "sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA==", "cpu": [ "x64" ], @@ -4611,9 +4612,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.1.tgz", - "integrity": "sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.2.tgz", + "integrity": "sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA==", "cpu": [ "x64" ], @@ -4628,9 +4629,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.1.tgz", - "integrity": "sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.2.tgz", + "integrity": "sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w==", "cpu": [ "arm" ], @@ -4645,9 +4646,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.1.tgz", - "integrity": "sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.2.tgz", + "integrity": "sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig==", "cpu": [ "arm64" ], @@ -4665,9 +4666,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.1.tgz", - "integrity": "sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.2.tgz", + "integrity": "sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw==", "cpu": [ "arm64" ], @@ -4685,9 +4686,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.1.tgz", - "integrity": "sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.2.tgz", + "integrity": "sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA==", "cpu": [ "ppc64" ], @@ -4705,9 +4706,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.1.tgz", - "integrity": "sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.2.tgz", + "integrity": "sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ==", "cpu": [ "s390x" ], @@ -4725,9 +4726,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.1.tgz", - "integrity": "sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.2.tgz", + "integrity": "sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ==", "cpu": [ "x64" ], @@ -4745,9 +4746,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.1.tgz", - "integrity": "sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.2.tgz", + "integrity": "sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw==", "cpu": [ "x64" ], @@ -4765,9 +4766,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.1.tgz", - "integrity": "sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.2.tgz", + "integrity": "sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w==", "cpu": [ "arm64" ], @@ -4782,9 +4783,9 @@ } }, "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.1.tgz", - "integrity": "sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.2.tgz", + "integrity": "sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ==", "cpu": [ "wasm32" ], @@ -4801,9 +4802,9 @@ } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.1.tgz", - "integrity": "sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.2.tgz", + "integrity": "sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A==", "cpu": [ "arm64" ], @@ -4818,9 +4819,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.1.tgz", - "integrity": "sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.2.tgz", + "integrity": "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ==", "cpu": [ "x64" ], @@ -5428,9 +5429,9 @@ } }, "node_modules/@types/node": { - "version": "25.8.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.8.0.tgz", - "integrity": "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ==", + "version": "25.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", + "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", "license": "MIT", "dependencies": { "undici-types": ">=7.24.0 <7.24.7" @@ -6713,9 +6714,9 @@ "license": "MIT" }, "node_modules/exifreader": { - "version": "4.38.1", - "resolved": "https://registry.npmjs.org/exifreader/-/exifreader-4.38.1.tgz", - "integrity": "sha512-VUQ8pnWJHpnQXPQLgx4XBwjhj+eE0f5t4KhVFn6BnnTYKLf79DfjVRntR5061qE9NZgx2ohvE+JLXe/FWfCaAA==", + "version": "4.39.1", + "resolved": "https://registry.npmjs.org/exifreader/-/exifreader-4.39.1.tgz", + "integrity": "sha512-mQyOcAXK/mE+5rdzeqv/6tK431Vv8HCIVMYIJZJgJ+1ydd6nmg13awWcaEAzj/3M+Ii7A5v1gMokDOiK6RDcpw==", "hasInstallScript": true, "license": "MPL-2.0", "optionalDependencies": { @@ -7298,9 +7299,9 @@ "license": "ISC" }, "node_modules/idb-keyval": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.2.tgz", - "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==", + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.4.tgz", + "integrity": "sha512-D/NzHWUmYJGXi++z67aMSrnisb9A3621CyRK5G89JyTlN13C8xf0g04DLxUKMufPem3e3L2JAXR6Z00OWy183Q==", "license": "Apache-2.0" }, "node_modules/import-meta-resolve": { @@ -7955,12 +7956,12 @@ "license": "MIT" }, "node_modules/js-cookie": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", - "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.7.tgz", + "integrity": "sha512-z/wZZgDrkNV1eA0ULjM/F9/50Ya8fbzgKneSpoPsXSGd0KnpdtHfOZWK+GcwLk+EZbS4F9RBhU+K2RgzuDaItw==", "license": "MIT", "engines": { - "node": ">=14" + "node": ">=20" } }, "node_modules/js-sha256": { @@ -8810,9 +8811,9 @@ } }, "node_modules/oxfmt": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.49.0.tgz", - "integrity": "sha512-IAHFMdlJSWe+oAr65dx22UvjCtV9DBMisAuLnKpDqMQrctzCkGnj3QRwNHm0d+uwSWPalsDF8ZYLz9rh6nH2IQ==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.51.0.tgz", + "integrity": "sha512-l/AoAnaEOV7Q5/Z9kHOMDehVJnCgYN7wRoooWCTUMBMi16BJhLZqd9cmCnwcVFfVlzkt53zK2KLPFNp8vSsoDg==", "dev": true, "license": "MIT", "dependencies": { @@ -8828,25 +8829,25 @@ "url": "https://github.com/sponsors/Boshen" }, "optionalDependencies": { - "@oxfmt/binding-android-arm-eabi": "0.49.0", - "@oxfmt/binding-android-arm64": "0.49.0", - "@oxfmt/binding-darwin-arm64": "0.49.0", - "@oxfmt/binding-darwin-x64": "0.49.0", - "@oxfmt/binding-freebsd-x64": "0.49.0", - "@oxfmt/binding-linux-arm-gnueabihf": "0.49.0", - "@oxfmt/binding-linux-arm-musleabihf": "0.49.0", - "@oxfmt/binding-linux-arm64-gnu": "0.49.0", - "@oxfmt/binding-linux-arm64-musl": "0.49.0", - "@oxfmt/binding-linux-ppc64-gnu": "0.49.0", - "@oxfmt/binding-linux-riscv64-gnu": "0.49.0", - "@oxfmt/binding-linux-riscv64-musl": "0.49.0", - "@oxfmt/binding-linux-s390x-gnu": "0.49.0", - "@oxfmt/binding-linux-x64-gnu": "0.49.0", - "@oxfmt/binding-linux-x64-musl": "0.49.0", - "@oxfmt/binding-openharmony-arm64": "0.49.0", - "@oxfmt/binding-win32-arm64-msvc": "0.49.0", - "@oxfmt/binding-win32-ia32-msvc": "0.49.0", - "@oxfmt/binding-win32-x64-msvc": "0.49.0" + "@oxfmt/binding-android-arm-eabi": "0.51.0", + "@oxfmt/binding-android-arm64": "0.51.0", + "@oxfmt/binding-darwin-arm64": "0.51.0", + "@oxfmt/binding-darwin-x64": "0.51.0", + "@oxfmt/binding-freebsd-x64": "0.51.0", + "@oxfmt/binding-linux-arm-gnueabihf": "0.51.0", + "@oxfmt/binding-linux-arm-musleabihf": "0.51.0", + "@oxfmt/binding-linux-arm64-gnu": "0.51.0", + "@oxfmt/binding-linux-arm64-musl": "0.51.0", + "@oxfmt/binding-linux-ppc64-gnu": "0.51.0", + "@oxfmt/binding-linux-riscv64-gnu": "0.51.0", + "@oxfmt/binding-linux-riscv64-musl": "0.51.0", + "@oxfmt/binding-linux-s390x-gnu": "0.51.0", + "@oxfmt/binding-linux-x64-gnu": "0.51.0", + "@oxfmt/binding-linux-x64-musl": "0.51.0", + "@oxfmt/binding-openharmony-arm64": "0.51.0", + "@oxfmt/binding-win32-arm64-msvc": "0.51.0", + "@oxfmt/binding-win32-ia32-msvc": "0.51.0", + "@oxfmt/binding-win32-x64-msvc": "0.51.0" }, "peerDependencies": { "svelte": "^5.0.0" @@ -8858,9 +8859,9 @@ } }, "node_modules/p-queue": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.2.0.tgz", - "integrity": "sha512-dWgLE8AH0HjQ9fe74pUkKkvzzYT18Inp4zra3lKHnnwqGvcfcUBrvF2EAVX+envufDNBOzpPq/IBUONDbI7+3g==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.0.tgz", + "integrity": "sha512-7NED7xhQ74Ngp4JP/2e0VZHp7vSWfJfqeiR92jPgxsz6m0Se4P03YoTKa9dDXyZ3r6P616gUXttrB6nnHYKang==", "license": "MIT", "dependencies": { "eventemitter3": "^5.0.4", @@ -9027,9 +9028,9 @@ } }, "node_modules/postcss": { - "version": "8.5.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", - "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "funding": [ { @@ -9047,7 +9048,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -9827,9 +9828,9 @@ } }, "node_modules/preact": { - "version": "10.29.1", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.1.tgz", - "integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==", + "version": "10.29.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.2.tgz", + "integrity": "sha512-7tNmwg/7mzzAoB/8kSg6Hl37JraAZw3Z3A0JSY7VXlZwo82Xn0G7wKbNNs2qoF4ZEEsQGTwDAroNdqKs1ofJxQ==", "license": "MIT", "funding": { "type": "opencollective", @@ -10235,13 +10236,13 @@ } }, "node_modules/rolldown": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.1.tgz", - "integrity": "sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.2.tgz", + "integrity": "sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.130.0", + "@oxc-project/types": "=0.132.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -10251,21 +10252,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.1", - "@rolldown/binding-darwin-arm64": "1.0.1", - "@rolldown/binding-darwin-x64": "1.0.1", - "@rolldown/binding-freebsd-x64": "1.0.1", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.1", - "@rolldown/binding-linux-arm64-gnu": "1.0.1", - "@rolldown/binding-linux-arm64-musl": "1.0.1", - "@rolldown/binding-linux-ppc64-gnu": "1.0.1", - "@rolldown/binding-linux-s390x-gnu": "1.0.1", - "@rolldown/binding-linux-x64-gnu": "1.0.1", - "@rolldown/binding-linux-x64-musl": "1.0.1", - "@rolldown/binding-openharmony-arm64": "1.0.1", - "@rolldown/binding-wasm32-wasi": "1.0.1", - "@rolldown/binding-win32-arm64-msvc": "1.0.1", - "@rolldown/binding-win32-x64-msvc": "1.0.1" + "@rolldown/binding-android-arm64": "1.0.2", + "@rolldown/binding-darwin-arm64": "1.0.2", + "@rolldown/binding-darwin-x64": "1.0.2", + "@rolldown/binding-freebsd-x64": "1.0.2", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.2", + "@rolldown/binding-linux-arm64-gnu": "1.0.2", + "@rolldown/binding-linux-arm64-musl": "1.0.2", + "@rolldown/binding-linux-ppc64-gnu": "1.0.2", + "@rolldown/binding-linux-s390x-gnu": "1.0.2", + "@rolldown/binding-linux-x64-gnu": "1.0.2", + "@rolldown/binding-linux-x64-musl": "1.0.2", + "@rolldown/binding-openharmony-arm64": "1.0.2", + "@rolldown/binding-wasm32-wasi": "1.0.2", + "@rolldown/binding-win32-arm64-msvc": "1.0.2", + "@rolldown/binding-win32-x64-msvc": "1.0.2" } }, "node_modules/rollup": { @@ -10865,9 +10866,9 @@ "license": "MIT" }, "node_modules/temml": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/temml/-/temml-0.13.2.tgz", - "integrity": "sha512-n8fDRSsLscq9nh9j6z+FgkCvFMT0IJm6GCgwfzh+7AHT3Sfb4jFTQlsA6hVcF2dYYr3b66oDBVES95RfoukyrA==", + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/temml/-/temml-0.13.3.tgz", + "integrity": "sha512-GLNEdf5qBWux3adbOxFus4jlds8nCdEIkkKq99m/4GGTfqnsjlVlK/i371Ux7yYSg/WNmOyAkNT/GJlZoJ0v+w==", "license": "MIT", "engines": { "node": ">=18.13.0" @@ -11353,16 +11354,16 @@ } }, "node_modules/vite": { - "version": "8.0.13", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.13.tgz", - "integrity": "sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==", + "version": "8.0.14", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.14.tgz", + "integrity": "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", - "postcss": "^8.5.14", - "rolldown": "1.0.1", + "postcss": "^8.5.15", + "rolldown": "1.0.2", "tinyglobby": "^0.2.16" }, "bin": { diff --git a/package.json b/package.json index 090c9b99b3..113fa6b3ea 100644 --- a/package.json +++ b/package.json @@ -30,33 +30,33 @@ }, "dependencies": { "@formatjs/intl-localematcher": "~0.8.8", - "@formatjs/intl-segmenter": "~12.2.7", + "@formatjs/intl-segmenter": "~12.2.8", "@formkit/auto-animate": "~0.9.0", "@github/text-expander-element": "~2.9.4", "@iconify-json/mingcute": "~1.2.7", "@justinribeiro/lite-youtube": "~1.9.0", - "@lingui/detect-locale": "~6.0.1", - "@lingui/react": "~6.0.1", + "@lingui/detect-locale": "~6.1.0", + "@lingui/react": "~6.1.0", "@szhsin/react-menu": "~4.5.1", "chroma-js": "~3.2.0", "compare-versions": "~6.1.1", - "exifreader": "~4.38.1", + "exifreader": "~4.39.1", "fast-blurhash": "~1.1.4", "fast-equals": "~6.0.0", "flexsearch": "~0.8.212", "fuse.js": "~7.3.0", "gifuct-js": "~2.1.2", "html-prettify": "~1.0.7", - "idb-keyval": "~6.2.2", + "idb-keyval": "~6.2.4", "intl-locale-textinfo-polyfill": "~3.0.0", - "js-cookie": "~3.0.5", + "js-cookie": "~3.0.7", "just-debounce-it": "~3.2.0", "lz-string": "~1.5.0", "masto": "~7.11.1", "micro-memoize": "~5.1.1", - "p-queue": "~9.2.0", + "p-queue": "~9.3.0", "p-retry": "~8.0.0", - "preact": "10.29.1", + "preact": "10.29.2", "punycode": "~2.3.1", "qr": "~0.6.0", "react-hotkeys-hook": "~5.2.4", @@ -64,7 +64,7 @@ "react-quick-pinch-zoom": "~5.1.1", "react-router-dom": "6.6.2", "swiped-events": "~1.2.0", - "temml": "~0.13.2", + "temml": "~0.13.3", "tinyld": "~1.3.4", "toastify-js": "~1.12.0", "uid": "~2.0.2", @@ -78,20 +78,20 @@ "@emnapi/core": "~1.10.0", "@emnapi/runtime": "~1.10.0", "@iconify/utils": "~3.1.3", - "@lingui/babel-plugin-lingui-macro": "~6.0.1", - "@lingui/cli": "~6.0.1", - "@lingui/vite-plugin": "~6.0.1", + "@lingui/babel-plugin-lingui-macro": "~6.1.0", + "@lingui/cli": "~6.1.0", + "@lingui/vite-plugin": "~6.1.0", "@playwright/test": "~1.60.0", "@preact/preset-vite": "~2.10.5", - "@types/node": "~25.8.0", - "oxfmt": "~0.49.0", - "postcss": "~8.5.14", + "@types/node": "~25.9.1", + "oxfmt": "~0.51.0", + "postcss": "~8.5.15", "postcss-dark-theme-class": "~2.0.0", "postcss-preset-env": "~11.3.0", "prop-types": "^15.8.1", "sonda": "~0.11.1", "twitter-text": "~3.1.0", - "vite": "~8.0.13", + "vite": "~8.0.14", "vite-plugin-generate-file": "~0.3.1", "vite-plugin-html-config": "~2.0.2", "vite-plugin-pwa": "~1.3.0", From f89687d9ce2b9009d8b2e087eb6120ebc43b318f Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Sat, 23 May 2026 10:42:10 +0800 Subject: [PATCH 03/12] Spec for keyboard shortcuts --- tests/keyboard-shortcuts.spec.js | 597 +++++++++++++++++++++++++++++++ 1 file changed, 597 insertions(+) create mode 100644 tests/keyboard-shortcuts.spec.js diff --git a/tests/keyboard-shortcuts.spec.js b/tests/keyboard-shortcuts.spec.js new file mode 100644 index 0000000000..4a771b8dd1 --- /dev/null +++ b/tests/keyboard-shortcuts.spec.js @@ -0,0 +1,597 @@ +// @ts-check +import { expect, test } from '@playwright/test'; + +const MOCK_INSTANCE_RESPONSE = { + uri: 'test.social', + title: 'Test Social', + domain: 'test.social', + version: '4.0.0', + configuration: { + statuses: { maxCharacters: 500, maxMediaAttachments: 4 }, + polls: { maxOptions: 4, maxCharactersPerOption: 50, minExpiration: 300, maxExpiration: 86400 }, + urls: { streaming: 'wss://test.social' }, + }, +}; + +const MOCK_ACCOUNT_INFO = { + id: '1', + username: 'testuser', + acct: 'testuser', + display_name: 'Test User', + locked: false, + bot: false, + discoverable: true, + created_at: '2024-01-01T00:00:00.000Z', + note: '

Test user

', + url: 'https://test.social/@testuser', + uri: 'https://test.social/users/testuser', + avatar: 'https://test.social/avatars/test.png', + avatar_static: 'https://test.social/avatars/test.png', + header: 'https://test.social/headers/test.png', + header_static: 'https://test.social/headers/test.png', + followers_count: 100, + following_count: 50, + statuses_count: 500, + last_status_at: '2024-06-01', + emojis: [], + roles: [], + fields: [], +}; + +function createMockPost(id, index) { + const i = index ?? 0; + return { + id: String(id), + created_at: new Date(Date.now() - i * 900000).toISOString(), + account: { + id: '1', + username: 'testuser', + acct: 'testuser', + display_name: 'Test User', + url: 'https://test.social/@testuser', + uri: 'https://test.social/users/testuser', + avatar: 'https://test.social/avatar.png', + avatar_static: 'https://test.social/avatar.png', + header: 'https://test.social/header.png', + header_static: 'https://test.social/header.png', + followers_count: 100, + following_count: 50, + statuses_count: 200, + last_status_at: '2024-06-01', + emojis: [], + fields: [], + }, + content: `

Test post ${i}

`, + uri: `https://test.social/users/testuser/statuses/${id}`, + url: `https://test.social/@testuser/${id}`, + media_attachments: [], + mentions: [], + tags: [], + emojis: [], + reblogs_count: 0, + favourites_count: 0, + replies_count: 0, + sensitive: false, + spoiler_text: '', + visibility: 'public', + language: 'en', + favourited: false, + reblogged: false, + bookmarked: false, + muted: false, + pinned: false, + }; +} + +async function setupMockHomeEnv(page) { + await page.route('**/api/v2/instance', async (route) => { + await route.fulfill({ json: MOCK_INSTANCE_RESPONSE }); + }); + await page.route('**/api/v1/instance', async (route) => { + await route.fulfill({ json: MOCK_INSTANCE_RESPONSE }); + }); + await page.goto('/#/_mock/home'); + await page.waitForSelector('.timeline-item', { timeout: 15000 }); +} + +async function setupLoggedInEnv(page) { + await page.addInitScript(() => { + const account = { + info: { + id: '1', + username: 'testuser', + acct: 'testuser', + display_name: 'Test User', + avatar: 'https://test.social/avatar.png', + avatar_static: 'https://test.social/avatar.png', + header: 'https://test.social/header.png', + header_static: 'https://test.social/header.png', + }, + instanceURL: 'test.social', + accessToken: 'mock-access-token', + createdAt: Date.now(), + updatedAt: Date.now(), + lastAccessedAt: Date.now(), + }; + localStorage.setItem('accounts', JSON.stringify([account])); + sessionStorage.setItem('currentAccount', '1'); + localStorage.setItem('preferences', JSON.stringify({ + '1@test.social': { 'posting:default:visibility': 'public' }, + })); + localStorage.setItem('instances', JSON.stringify({ + 'test.social': { + uri: 'test.social', + title: 'Test Social', + version: '4.0.0', + configuration: { + statuses: { maxCharacters: 500, maxMediaAttachments: 4 }, + polls: { maxOptions: 4, maxCharactersPerOption: 50, minExpiration: 300, maxExpiration: 86400 }, + urls: { streaming: 'wss://test.social' }, + }, + }, + })); + localStorage.setItem('credentialApplications', JSON.stringify({ + 'test.social': { + client_id: 'mock-client-id', + client_secret: 'mock-client-secret', + vapid_key: 'mock-vapid-key', + }, + })); + }); + + await page.route('**/api/v2/instance', async (route) => { + await route.fulfill({ json: MOCK_INSTANCE_RESPONSE }); + }); + await page.route('**/api/v1/instance', async (route) => { + await route.fulfill({ json: MOCK_INSTANCE_RESPONSE }); + }); + await page.route('**/api/v1/preferences', async (route) => { + await route.fulfill({ json: {} }); + }); + await page.route('**/api/v1/accounts/verify_credentials', async (route) => { + await route.fulfill({ json: MOCK_ACCOUNT_INFO }); + }); + await page.route('**/api/v1/apps/verify_credentials', async (route) => { + await route.fulfill({ json: { name: 'Test App', website: null } }); + }); +} + +async function focusFirstStatus(page) { + await page.locator('.status').first().focus(); + await page.waitForTimeout(300); +} + +async function focusInput(page) { + await page.evaluate(() => { + const existing = document.getElementById('__test-input__'); + if (existing) existing.remove(); + const input = document.createElement('input'); + input.id = '__test-input__'; + input.style.position = 'fixed'; + input.style.top = '0'; + input.style.left = '0'; + input.style.opacity = '0.01'; + input.style.zIndex = '99999'; + document.body.prepend(input); + input.focus(); + }); + await page.waitForTimeout(100); +} + +async function cleanupInput(page) { + await page.evaluate(() => { + document.getElementById('__test-input__')?.remove(); + }); +} + +function overrideAlert(page) { + return page.evaluate(() => { + window.__alertCalled = false; + window.__alertCount = 0; + window.alert = () => { + window.__alertCalled = true; + window.__alertCount++; + }; + }); +} + +function wasAlertCalled(page) { + return page.evaluate(() => window.__alertCalled); +} + +function getAlertCount(page) { + return page.evaluate(() => window.__alertCount); +} + +function resetAlertCounter(page) { + return page.evaluate(() => { + window.__alertCalled = false; + window.__alertCount = 0; + }); +} + +test.describe('Keyboard Shortcuts', () => { + test.describe('Section 1: Status Interaction Shortcuts (via _mock/home)', () => { + test.beforeEach(async ({ page }) => { + await setupMockHomeEnv(page); + await focusFirstStatus(page); + await overrideAlert(page); + }); + + test('1.1 Reply (r) fires on focused status', async ({ page }) => { + await page.keyboard.press('r'); + await page.waitForTimeout(500); + expect(await wasAlertCalled(page)).toBe(true); + }); + + test('1.2 Favourite (f) fires on focused status', async ({ page }) => { + await page.keyboard.press('f'); + await page.waitForTimeout(500); + expect(await wasAlertCalled(page)).toBe(true); + }); + + test('1.3 Favourite (l) fires on focused status', async ({ page }) => { + await page.keyboard.press('l'); + await page.waitForTimeout(500); + expect(await wasAlertCalled(page)).toBe(true); + }); + + test('1.4 Bookmark (d) fires on focused status', async ({ page }) => { + await page.keyboard.press('d'); + await page.waitForTimeout(500); + expect(await wasAlertCalled(page)).toBe(true); + }); + + test('1.5 Quote (q) fires on focused status', async ({ page }) => { + await page.keyboard.press('q'); + await page.waitForTimeout(500); + expect(await wasAlertCalled(page)).toBe(true); + }); + + test('1.6 Scoping: input focus blocks status shortcuts', async ({ page }) => { + await focusInput(page); + await page.keyboard.press('r'); + await page.waitForTimeout(500); + expect(await wasAlertCalled(page)).toBe(false); + await cleanupInput(page); + }); + + test('1.7 Scoping: modifier key blocks status shortcuts', async ({ page }) => { + await page.keyboard.press('Meta+r'); + await page.waitForTimeout(500); + expect(await wasAlertCalled(page)).toBe(false); + }); + + test('1.8 Focus scoping: reply fires only for focused status, not multiple', async ({ page }) => { + expect(await getAlertCount(page)).toBe(0); + await page.keyboard.press('r'); + await page.waitForTimeout(500); + const count = await getAlertCount(page); + expect(count).toBe(1); + }); + + test('1.9 Focus scoping: favourite fires only for newly focused status', async ({ page }) => { + await page.keyboard.press('f'); + await page.waitForTimeout(500); + expect(await getAlertCount(page)).toBe(1); + await resetAlertCounter(page); + const items = page.locator('.status'); + const count = await items.count(); + if (count < 2) return; + await items.nth(1).focus(); + await page.waitForTimeout(300); + await page.keyboard.press('f'); + await page.waitForTimeout(500); + expect(await getAlertCount(page)).toBe(1); + }); + }); + + test.describe('Section 2: Compose Shortcuts (via _mock/home)', () => { + test.beforeEach(async ({ page }) => { + await setupMockHomeEnv(page); + }); + + test('2.1 Open compose (c) sets showCompose', async ({ page }) => { + await page.keyboard.press('c'); + await page.waitForTimeout(300); + const showCompose = await page.evaluate(() => window.__STATES__?.showCompose); + expect(showCompose).toBeTruthy(); + }); + + test('2.2 Scoping: input focus blocks compose', async ({ page }) => { + await focusInput(page); + await page.keyboard.press('c'); + await page.waitForTimeout(300); + const showCompose = await page.evaluate(() => window.__STATES__?.showCompose); + expect(showCompose).toBeFalsy(); + await cleanupInput(page); + }); + + test('2.3 Scoping: modifier key blocks compose', async ({ page }) => { + await page.keyboard.press('Meta+c'); + await page.waitForTimeout(300); + const showCompose = await page.evaluate(() => window.__STATES__?.showCompose); + expect(showCompose).toBeFalsy(); + }); + }); + + test.describe('Section 3: Number Shortcuts (via _mock/home)', () => { + test.beforeEach(async ({ page }) => { + await setupMockHomeEnv(page); + await page.waitForTimeout(500); + }); + + test('3.1 Number 1 navigates to home', async ({ page }) => { + await page.keyboard.press('1'); + await page.waitForTimeout(500); + const hash = await page.evaluate(() => location.hash); + expect(hash).toBe('#/'); + }); + + test('3.2 Scoping: modifier key blocks number shortcut', async ({ page }) => { + const hashBefore = await page.evaluate(() => location.hash); + await page.keyboard.press('Meta+1'); + await page.waitForTimeout(500); + const hashAfter = await page.evaluate(() => location.hash); + expect(hashAfter).toBe(hashBefore); + }); + }); + + test.describe('Section 4: Help Shortcut (via _mock/home)', () => { + test.beforeEach(async ({ page }) => { + await setupMockHomeEnv(page); + }); + + test('4.1 Open help with ?', async ({ page }) => { + await page.keyboard.press('?'); + await page.waitForTimeout(500); + await expect(page.locator('#keyboard-shortcuts-help-container')).toBeVisible(); + }); + + test('4.2 Close help with Escape', async ({ page }) => { + await page.keyboard.press('?'); + await page.waitForTimeout(500); + await expect(page.locator('#keyboard-shortcuts-help-container')).toBeVisible(); + await page.keyboard.press('Escape'); + await page.waitForTimeout(500); + await expect(page.locator('#keyboard-shortcuts-help-container')).not.toBeVisible(); + }); + + test('4.3 Scoping: modifier key blocks help', async ({ page }) => { + await page.keyboard.press('Meta+?'); + await page.waitForTimeout(500); + await expect(page.locator('#keyboard-shortcuts-help-container')).not.toBeVisible(); + }); + }); + + test.describe('Section 5: Search Overlay (via _mock/home)', () => { + test.beforeEach(async ({ page }) => { + await setupMockHomeEnv(page); + }); + + test('5.1 Open search with / removes hidden attribute', async ({ page }) => { + await page.keyboard.press('/'); + await page.waitForTimeout(500); + await expect(page.locator('#search-command-container')).not.toHaveAttribute('hidden', ''); + }); + + test('5.2 Close search with Escape adds hidden attribute', async ({ page }) => { + await page.keyboard.press('/'); + await page.waitForTimeout(500); + const hiddenBefore = await page.locator('#search-command-container').getAttribute('hidden'); + expect(hiddenBefore).toBeNull(); + await page.keyboard.press('Escape'); + await page.waitForTimeout(500); + await expect(page.locator('#search-command-container')).toHaveAttribute('hidden', ''); + }); + }); + + test.describe('Section 6: Cloak Mode (via _mock/home)', () => { + test.beforeEach(async ({ page }) => { + await setupMockHomeEnv(page); + }); + + test('6.1 Toggle cloak mode on', async ({ page }) => { + await page.keyboard.press('Shift+Alt+k'); + await page.waitForTimeout(300); + const hasCloak = await page.evaluate(() => document.body.classList.contains('cloak')); + expect(hasCloak).toBe(true); + }); + + test('6.2 Toggle cloak mode off', async ({ page }) => { + await page.keyboard.press('Shift+Alt+k'); + await page.waitForTimeout(300); + await page.keyboard.press('Shift+Alt+k'); + await page.waitForTimeout(300); + const hasCloak = await page.evaluate(() => document.body.classList.contains('cloak')); + expect(hasCloak).toBe(false); + }); + + test('6.3 Scoping: modifier key blocks cloak toggle', async ({ page }) => { + await page.keyboard.press('Meta+Shift+Alt+k'); + await page.waitForTimeout(300); + const hasCloak = await page.evaluate(() => document.body.classList.contains('cloak')); + expect(hasCloak).toBe(false); + }); + }); + + test.describe('Section 7: Navigation Commands (g> sequences) — needs auth', () => { + test.beforeEach(async ({ page }) => { + await setupLoggedInEnv(page); + await page.route('**/api/v1/timelines/home**', async (route) => { + await route.fulfill({ json: [] }); + }); + await page.goto('/#/test.social'); + await page.waitForTimeout(3000); + }); + + test('7.1 g then h navigates to home', async ({ page }) => { + await page.keyboard.press('g'); + await page.waitForTimeout(100); + await page.keyboard.press('h'); + await page.waitForTimeout(500); + const hash = await page.evaluate(() => location.hash); + expect(hash).toBe('#/'); + }); + + test('7.2 g then n navigates to notifications', async ({ page }) => { + await page.keyboard.press('g'); + await page.waitForTimeout(100); + await page.keyboard.press('n'); + await page.waitForTimeout(500); + const hash = await page.evaluate(() => location.hash); + expect(hash).toMatch(/notifications/); + }); + + test('7.3 g then s opens settings', async ({ page }) => { + await page.keyboard.press('g'); + await page.waitForTimeout(100); + await page.keyboard.press('s'); + await page.waitForTimeout(500); + const showSettings = await page.evaluate(() => window.__STATES__?.showSettings); + expect(showSettings).toBe(true); + }); + + test('7.4 g then b navigates to bookmarks', async ({ page }) => { + await page.keyboard.press('g'); + await page.waitForTimeout(100); + await page.keyboard.press('b'); + await page.waitForTimeout(500); + const hash = await page.evaluate(() => location.hash); + expect(hash).toMatch(/\/b$/); + }); + }); + + test.describe('Section 8: Timeline Navigation (j/k) — needs auth', () => { + test.beforeEach(async ({ page }) => { + await setupLoggedInEnv(page); + const mockPosts = Array.from({ length: 5 }, (_, i) => createMockPost(100 + i, i)); + await page.route('**/api/v1/timelines/home**', async (route) => { + await route.fulfill({ json: mockPosts }); + }); + await page.goto('/#/test.social'); + await page.waitForSelector('.timeline-item', { timeout: 20000 }); + await page.waitForTimeout(1000); + }); + + test('8.1 j focuses next timeline item', async ({ page }) => { + await focusFirstStatus(page); + await page.keyboard.press('j'); + await page.waitForTimeout(300); + const activeItem = await page.evaluate(() => + document.activeElement?.closest('.timeline-item'), + ); + expect(activeItem).not.toBeNull(); + }); + + test('8.2 j then k navigates back to previous item', async ({ page }) => { + const count = await page.locator('.timeline-item').count(); + expect(count).toBeGreaterThanOrEqual(2); + await focusFirstStatus(page); + await page.keyboard.press('j'); + await page.waitForTimeout(200); + await page.keyboard.press('k'); + await page.waitForTimeout(200); + const activeItem = await page.evaluate(() => + document.activeElement?.closest('.timeline-item'), + ); + expect(activeItem).not.toBeNull(); + }); + + test('8.3 Scoping: input focus blocks j (default library behavior)', async ({ page }) => { + await focusFirstStatus(page); + await focusInput(page); + await page.keyboard.press('j'); + await page.waitForTimeout(300); + const stillInInput = await page.evaluate(() => + document.activeElement?.id === '__test-input__', + ); + await cleanupInput(page); + expect(stillInInput).toBe(true); + }); + + test('8.4 Scoping: modifier key blocks j navigation', async ({ page }) => { + await focusFirstStatus(page); + await page.keyboard.press('Meta+j'); + await page.waitForTimeout(300); + const onFirstItem = await page.evaluate(() => { + const ae = document.activeElement; + return ae?.closest('.timeline-item')?.classList.contains('timeline-item') === true; + }); + expect(onFirstItem).toBe(true); + }); + }); + + test.describe('Section 9: Modal Escape (via _mock/home)', () => { + test.beforeEach(async ({ page }) => { + await setupMockHomeEnv(page); + }); + + test('9.1 Escape closes help modal', async ({ page }) => { + await page.keyboard.press('?'); + await page.waitForTimeout(500); + await expect(page.locator('#keyboard-shortcuts-help-container')).toBeVisible(); + await page.keyboard.press('Escape'); + await page.waitForTimeout(500); + await expect(page.locator('#keyboard-shortcuts-help-container')).not.toBeVisible(); + }); + + test('9.2 Scoping: modifier key does not close modal', async ({ page }) => { + await page.keyboard.press('?'); + await page.waitForTimeout(500); + await expect(page.locator('#keyboard-shortcuts-help-container')).toBeVisible(); + await page.keyboard.press('Meta+Escape'); + await page.waitForTimeout(500); + await expect(page.locator('#keyboard-shortcuts-help-container')).toBeVisible(); + }); + }); + + test.describe('Section 10: Status Detail Page — needs auth', () => { + test.beforeEach(async ({ page }) => { + await setupLoggedInEnv(page); + + const contextDescendants = Array.from({ length: 3 }, (_, i) => ({ + ...createMockPost(124 + i, i + 1), + descendant: true, + in_reply_to_id: '123', + in_reply_to_account_id: '1', + })); + + await page.route('**/api/v1/statuses/123', async (route) => { + await route.fulfill({ + json: { ...createMockPost(123, 0), content: '

Status detail test post

' }, + }); + }); + await page.route('**/api/v1/statuses/123/context', async (route) => { + await route.fulfill({ + json: { ancestors: [], descendants: contextDescendants }, + }); + }); + + await page.route('**/api/v1/timelines/home**', async (route) => { + await route.fulfill({ json: [] }); + }); + + await page.goto('/#/test.social/s/123'); + await page.waitForSelector('article.status', { timeout: 15000 }); + await page.waitForTimeout(500); + }); + + test('10.1 Escape closes status detail', async ({ page }) => { + await page.keyboard.press('Escape'); + await page.waitForTimeout(500); + const hash = await page.evaluate(() => location.hash); + expect(hash).not.toMatch(/\/s\/123/); + }); + + test('10.2 j focuses next context status', async ({ page }) => { + await page.keyboard.press('j'); + await page.waitForTimeout(300); + const activeEl = await page.evaluate(() => { + const el = document.activeElement; + return el?.closest('.status-focus, .status-link'); + }); + expect(activeEl).not.toBeNull(); + }); + }); +}); \ No newline at end of file From c3bc3bf82ddc8ee2be9e19b443fffb9e5eaa6f33 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sat, 23 May 2026 14:29:40 +0000 Subject: [PATCH 04/12] [autofix.ci] apply automated fixes --- tests/keyboard-shortcuts.spec.js | 188 ++++++++++++++++++++++--------- 1 file changed, 134 insertions(+), 54 deletions(-) diff --git a/tests/keyboard-shortcuts.spec.js b/tests/keyboard-shortcuts.spec.js index 4a771b8dd1..f80034d634 100644 --- a/tests/keyboard-shortcuts.spec.js +++ b/tests/keyboard-shortcuts.spec.js @@ -8,7 +8,12 @@ const MOCK_INSTANCE_RESPONSE = { version: '4.0.0', configuration: { statuses: { maxCharacters: 500, maxMediaAttachments: 4 }, - polls: { maxOptions: 4, maxCharactersPerOption: 50, minExpiration: 300, maxExpiration: 86400 }, + polls: { + maxOptions: 4, + maxCharactersPerOption: 50, + minExpiration: 300, + maxExpiration: 86400, + }, urls: { streaming: 'wss://test.social' }, }, }; @@ -115,28 +120,42 @@ async function setupLoggedInEnv(page) { }; localStorage.setItem('accounts', JSON.stringify([account])); sessionStorage.setItem('currentAccount', '1'); - localStorage.setItem('preferences', JSON.stringify({ - '1@test.social': { 'posting:default:visibility': 'public' }, - })); - localStorage.setItem('instances', JSON.stringify({ - 'test.social': { - uri: 'test.social', - title: 'Test Social', - version: '4.0.0', - configuration: { - statuses: { maxCharacters: 500, maxMediaAttachments: 4 }, - polls: { maxOptions: 4, maxCharactersPerOption: 50, minExpiration: 300, maxExpiration: 86400 }, - urls: { streaming: 'wss://test.social' }, + localStorage.setItem( + 'preferences', + JSON.stringify({ + '1@test.social': { 'posting:default:visibility': 'public' }, + }), + ); + localStorage.setItem( + 'instances', + JSON.stringify({ + 'test.social': { + uri: 'test.social', + title: 'Test Social', + version: '4.0.0', + configuration: { + statuses: { maxCharacters: 500, maxMediaAttachments: 4 }, + polls: { + maxOptions: 4, + maxCharactersPerOption: 50, + minExpiration: 300, + maxExpiration: 86400, + }, + urls: { streaming: 'wss://test.social' }, + }, }, - }, - })); - localStorage.setItem('credentialApplications', JSON.stringify({ - 'test.social': { - client_id: 'mock-client-id', - client_secret: 'mock-client-secret', - vapid_key: 'mock-vapid-key', - }, - })); + }), + ); + localStorage.setItem( + 'credentialApplications', + JSON.stringify({ + 'test.social': { + client_id: 'mock-client-id', + client_secret: 'mock-client-secret', + vapid_key: 'mock-vapid-key', + }, + }), + ); }); await page.route('**/api/v2/instance', async (route) => { @@ -248,7 +267,9 @@ test.describe('Keyboard Shortcuts', () => { expect(await wasAlertCalled(page)).toBe(true); }); - test('1.6 Scoping: input focus blocks status shortcuts', async ({ page }) => { + test('1.6 Scoping: input focus blocks status shortcuts', async ({ + page, + }) => { await focusInput(page); await page.keyboard.press('r'); await page.waitForTimeout(500); @@ -256,13 +277,17 @@ test.describe('Keyboard Shortcuts', () => { await cleanupInput(page); }); - test('1.7 Scoping: modifier key blocks status shortcuts', async ({ page }) => { + test('1.7 Scoping: modifier key blocks status shortcuts', async ({ + page, + }) => { await page.keyboard.press('Meta+r'); await page.waitForTimeout(500); expect(await wasAlertCalled(page)).toBe(false); }); - test('1.8 Focus scoping: reply fires only for focused status, not multiple', async ({ page }) => { + test('1.8 Focus scoping: reply fires only for focused status, not multiple', async ({ + page, + }) => { expect(await getAlertCount(page)).toBe(0); await page.keyboard.press('r'); await page.waitForTimeout(500); @@ -270,7 +295,9 @@ test.describe('Keyboard Shortcuts', () => { expect(count).toBe(1); }); - test('1.9 Focus scoping: favourite fires only for newly focused status', async ({ page }) => { + test('1.9 Focus scoping: favourite fires only for newly focused status', async ({ + page, + }) => { await page.keyboard.press('f'); await page.waitForTimeout(500); expect(await getAlertCount(page)).toBe(1); @@ -294,7 +321,9 @@ test.describe('Keyboard Shortcuts', () => { test('2.1 Open compose (c) sets showCompose', async ({ page }) => { await page.keyboard.press('c'); await page.waitForTimeout(300); - const showCompose = await page.evaluate(() => window.__STATES__?.showCompose); + const showCompose = await page.evaluate( + () => window.__STATES__?.showCompose, + ); expect(showCompose).toBeTruthy(); }); @@ -302,7 +331,9 @@ test.describe('Keyboard Shortcuts', () => { await focusInput(page); await page.keyboard.press('c'); await page.waitForTimeout(300); - const showCompose = await page.evaluate(() => window.__STATES__?.showCompose); + const showCompose = await page.evaluate( + () => window.__STATES__?.showCompose, + ); expect(showCompose).toBeFalsy(); await cleanupInput(page); }); @@ -310,7 +341,9 @@ test.describe('Keyboard Shortcuts', () => { test('2.3 Scoping: modifier key blocks compose', async ({ page }) => { await page.keyboard.press('Meta+c'); await page.waitForTimeout(300); - const showCompose = await page.evaluate(() => window.__STATES__?.showCompose); + const showCompose = await page.evaluate( + () => window.__STATES__?.showCompose, + ); expect(showCompose).toBeFalsy(); }); }); @@ -328,7 +361,9 @@ test.describe('Keyboard Shortcuts', () => { expect(hash).toBe('#/'); }); - test('3.2 Scoping: modifier key blocks number shortcut', async ({ page }) => { + test('3.2 Scoping: modifier key blocks number shortcut', async ({ + page, + }) => { const hashBefore = await page.evaluate(() => location.hash); await page.keyboard.press('Meta+1'); await page.waitForTimeout(500); @@ -345,22 +380,30 @@ test.describe('Keyboard Shortcuts', () => { test('4.1 Open help with ?', async ({ page }) => { await page.keyboard.press('?'); await page.waitForTimeout(500); - await expect(page.locator('#keyboard-shortcuts-help-container')).toBeVisible(); + await expect( + page.locator('#keyboard-shortcuts-help-container'), + ).toBeVisible(); }); test('4.2 Close help with Escape', async ({ page }) => { await page.keyboard.press('?'); await page.waitForTimeout(500); - await expect(page.locator('#keyboard-shortcuts-help-container')).toBeVisible(); + await expect( + page.locator('#keyboard-shortcuts-help-container'), + ).toBeVisible(); await page.keyboard.press('Escape'); await page.waitForTimeout(500); - await expect(page.locator('#keyboard-shortcuts-help-container')).not.toBeVisible(); + await expect( + page.locator('#keyboard-shortcuts-help-container'), + ).not.toBeVisible(); }); test('4.3 Scoping: modifier key blocks help', async ({ page }) => { await page.keyboard.press('Meta+?'); await page.waitForTimeout(500); - await expect(page.locator('#keyboard-shortcuts-help-container')).not.toBeVisible(); + await expect( + page.locator('#keyboard-shortcuts-help-container'), + ).not.toBeVisible(); }); }); @@ -369,20 +412,31 @@ test.describe('Keyboard Shortcuts', () => { await setupMockHomeEnv(page); }); - test('5.1 Open search with / removes hidden attribute', async ({ page }) => { + test('5.1 Open search with / removes hidden attribute', async ({ + page, + }) => { await page.keyboard.press('/'); await page.waitForTimeout(500); - await expect(page.locator('#search-command-container')).not.toHaveAttribute('hidden', ''); + await expect( + page.locator('#search-command-container'), + ).not.toHaveAttribute('hidden', ''); }); - test('5.2 Close search with Escape adds hidden attribute', async ({ page }) => { + test('5.2 Close search with Escape adds hidden attribute', async ({ + page, + }) => { await page.keyboard.press('/'); await page.waitForTimeout(500); - const hiddenBefore = await page.locator('#search-command-container').getAttribute('hidden'); + const hiddenBefore = await page + .locator('#search-command-container') + .getAttribute('hidden'); expect(hiddenBefore).toBeNull(); await page.keyboard.press('Escape'); await page.waitForTimeout(500); - await expect(page.locator('#search-command-container')).toHaveAttribute('hidden', ''); + await expect(page.locator('#search-command-container')).toHaveAttribute( + 'hidden', + '', + ); }); }); @@ -394,7 +448,9 @@ test.describe('Keyboard Shortcuts', () => { test('6.1 Toggle cloak mode on', async ({ page }) => { await page.keyboard.press('Shift+Alt+k'); await page.waitForTimeout(300); - const hasCloak = await page.evaluate(() => document.body.classList.contains('cloak')); + const hasCloak = await page.evaluate(() => + document.body.classList.contains('cloak'), + ); expect(hasCloak).toBe(true); }); @@ -403,14 +459,18 @@ test.describe('Keyboard Shortcuts', () => { await page.waitForTimeout(300); await page.keyboard.press('Shift+Alt+k'); await page.waitForTimeout(300); - const hasCloak = await page.evaluate(() => document.body.classList.contains('cloak')); + const hasCloak = await page.evaluate(() => + document.body.classList.contains('cloak'), + ); expect(hasCloak).toBe(false); }); test('6.3 Scoping: modifier key blocks cloak toggle', async ({ page }) => { await page.keyboard.press('Meta+Shift+Alt+k'); await page.waitForTimeout(300); - const hasCloak = await page.evaluate(() => document.body.classList.contains('cloak')); + const hasCloak = await page.evaluate(() => + document.body.classList.contains('cloak'), + ); expect(hasCloak).toBe(false); }); }); @@ -448,7 +508,9 @@ test.describe('Keyboard Shortcuts', () => { await page.waitForTimeout(100); await page.keyboard.press('s'); await page.waitForTimeout(500); - const showSettings = await page.evaluate(() => window.__STATES__?.showSettings); + const showSettings = await page.evaluate( + () => window.__STATES__?.showSettings, + ); expect(showSettings).toBe(true); }); @@ -465,7 +527,9 @@ test.describe('Keyboard Shortcuts', () => { test.describe('Section 8: Timeline Navigation (j/k) — needs auth', () => { test.beforeEach(async ({ page }) => { await setupLoggedInEnv(page); - const mockPosts = Array.from({ length: 5 }, (_, i) => createMockPost(100 + i, i)); + const mockPosts = Array.from({ length: 5 }, (_, i) => + createMockPost(100 + i, i), + ); await page.route('**/api/v1/timelines/home**', async (route) => { await route.fulfill({ json: mockPosts }); }); @@ -498,13 +562,15 @@ test.describe('Keyboard Shortcuts', () => { expect(activeItem).not.toBeNull(); }); - test('8.3 Scoping: input focus blocks j (default library behavior)', async ({ page }) => { + test('8.3 Scoping: input focus blocks j (default library behavior)', async ({ + page, + }) => { await focusFirstStatus(page); await focusInput(page); await page.keyboard.press('j'); await page.waitForTimeout(300); - const stillInInput = await page.evaluate(() => - document.activeElement?.id === '__test-input__', + const stillInInput = await page.evaluate( + () => document.activeElement?.id === '__test-input__', ); await cleanupInput(page); expect(stillInInput).toBe(true); @@ -516,7 +582,10 @@ test.describe('Keyboard Shortcuts', () => { await page.waitForTimeout(300); const onFirstItem = await page.evaluate(() => { const ae = document.activeElement; - return ae?.closest('.timeline-item')?.classList.contains('timeline-item') === true; + return ( + ae?.closest('.timeline-item')?.classList.contains('timeline-item') === + true + ); }); expect(onFirstItem).toBe(true); }); @@ -530,19 +599,27 @@ test.describe('Keyboard Shortcuts', () => { test('9.1 Escape closes help modal', async ({ page }) => { await page.keyboard.press('?'); await page.waitForTimeout(500); - await expect(page.locator('#keyboard-shortcuts-help-container')).toBeVisible(); + await expect( + page.locator('#keyboard-shortcuts-help-container'), + ).toBeVisible(); await page.keyboard.press('Escape'); await page.waitForTimeout(500); - await expect(page.locator('#keyboard-shortcuts-help-container')).not.toBeVisible(); + await expect( + page.locator('#keyboard-shortcuts-help-container'), + ).not.toBeVisible(); }); test('9.2 Scoping: modifier key does not close modal', async ({ page }) => { await page.keyboard.press('?'); await page.waitForTimeout(500); - await expect(page.locator('#keyboard-shortcuts-help-container')).toBeVisible(); + await expect( + page.locator('#keyboard-shortcuts-help-container'), + ).toBeVisible(); await page.keyboard.press('Meta+Escape'); await page.waitForTimeout(500); - await expect(page.locator('#keyboard-shortcuts-help-container')).toBeVisible(); + await expect( + page.locator('#keyboard-shortcuts-help-container'), + ).toBeVisible(); }); }); @@ -559,7 +636,10 @@ test.describe('Keyboard Shortcuts', () => { await page.route('**/api/v1/statuses/123', async (route) => { await route.fulfill({ - json: { ...createMockPost(123, 0), content: '

Status detail test post

' }, + json: { + ...createMockPost(123, 0), + content: '

Status detail test post

', + }, }); }); await page.route('**/api/v1/statuses/123/context', async (route) => { @@ -594,4 +674,4 @@ test.describe('Keyboard Shortcuts', () => { expect(activeEl).not.toBeNull(); }); }); -}); \ No newline at end of file +}); From 3e9e325b715f370d169830d1d90f1caf4ad850af Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Mon, 25 May 2026 11:57:59 +0800 Subject: [PATCH 05/12] Potential fix for notification streaming/polling --- src/components/background-service.jsx | 30 +++++++++++++++------------ src/locales/en.po | 4 ++-- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/components/background-service.jsx b/src/components/background-service.jsx index bbc9273e56..89ad817308 100644 --- a/src/components/background-service.jsx +++ b/src/components/background-service.jsx @@ -66,24 +66,30 @@ export default memo(function BackgroundService() { let sub; let streamTimeout; let pollNotifications; + let cancelled = false; if (isLoggedIn && visible) { const { masto, streaming, instance } = api(); (async () => { // 1. Get the latest notification await checkLatestNotification(masto, instance); - let hasStreaming = false; - // 2. Start streaming + const startPolling = () => { + if (cancelled) return; + console.log('🎏 Fallback to polling'); + pollNotifications = setInterval(() => { + checkLatestNotification(masto, instance, true); + }, POLL_INTERVAL); + }; + + // 2. Start streaming or fall back to polling if (streaming) { streamTimeout = setTimeout(() => { (async () => { try { - hasStreaming = true; sub = streaming.user.notification.subscribe(); console.log('🎏 Streaming notification', sub); for await (const entry of sub) { - if (!sub) break; - if (!visible) break; + if (cancelled || !sub) break; console.log('🔔🔔 Notification entry', entry); if (entry.event === 'notification') { console.log('🔔🔔 Notification', entry); @@ -95,22 +101,20 @@ export default memo(function BackgroundService() { } console.log('💥 Streaming notification loop STOPPED'); } catch (e) { - hasStreaming = false; - console.error(e); + console.error('💥 Streaming error', e); } - if (!hasStreaming) { - console.log('🎏 Streaming failed, fallback to polling'); - pollNotifications = setInterval(() => { - checkLatestNotification(masto, instance, true); - }, POLL_INTERVAL); - } + startPolling(); })(); }, STREAMING_TIMEOUT); + } else { + console.log('🎏 No streaming available, polling directly'); + startPolling(); } })(); } return () => { + cancelled = true; sub?.unsubscribe?.(); sub = null; clearTimeout(streamTimeout); diff --git a/src/locales/en.po b/src/locales/en.po index 9dbd4d6d56..a25a30edf0 100644 --- a/src/locales/en.po +++ b/src/locales/en.po @@ -342,11 +342,11 @@ msgstr "" msgid "New list" msgstr "" -#: src/components/background-service.jsx:160 +#: src/components/background-service.jsx:164 msgid "Cloak mode disabled" msgstr "" -#: src/components/background-service.jsx:160 +#: src/components/background-service.jsx:164 msgid "Cloak mode enabled" msgstr "" From f03d09922411d5c7cf770ef1da80127b29d1abb8 Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Tue, 26 May 2026 16:02:39 +0800 Subject: [PATCH 06/12] Finally fix the weird filtered post sort in boosts carousel well, I hope it's fixed. --- src/components/timeline.jsx | 26 ++++++++------------------ src/locales/en.po | 10 +++++----- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/src/components/timeline.jsx b/src/components/timeline.jsx index 5c7502b248..e2c2a0f33d 100644 --- a/src/components/timeline.jsx +++ b/src/components/timeline.jsx @@ -703,26 +703,16 @@ export const TimelineItem = memo( const filteredItemsIDs = new Set(); // Here, we don't hide filtered posts, but we sort them last fItems.sort((a, b) => { - // if (a._filtered && !b._filtered) { - // return 1; - // } - // if (!a._filtered && b._filtered) { - // return -1; - // } const aFiltered = isFiltered(a.filtered, filterContext); const bFiltered = isFiltered(b.filtered, filterContext); - if (aFiltered && aFiltered?.action !== 'blur') { - filteredItemsIDs.add(a.id); - } - if (bFiltered && bFiltered?.action !== 'blur') { - filteredItemsIDs.add(b.id); - } - if (aFiltered && !bFiltered) { - return 1; - } - if (!aFiltered && bFiltered) { - return -1; - } + const aShouldSort = aFiltered && aFiltered.action !== 'blur'; + const bShouldSort = bFiltered && bFiltered.action !== 'blur'; + + if (aShouldSort) filteredItemsIDs.add(a.id); + if (bShouldSort) filteredItemsIDs.add(b.id); + + if (aShouldSort && !bShouldSort) return 1; + if (!aShouldSort && bShouldSort) return -1; return 0; }); diff --git a/src/locales/en.po b/src/locales/en.po index a25a30edf0..bbecfabf1f 100644 --- a/src/locales/en.po +++ b/src/locales/en.po @@ -525,7 +525,7 @@ msgstr "Attachment #{i} failed" #: src/components/compose.jsx:1514 #: src/components/status.jsx:2555 -#: src/components/timeline.jsx:1068 +#: src/components/timeline.jsx:1058 msgid "Content warning" msgstr "" @@ -756,14 +756,14 @@ msgstr "Edit History Snapshots" #: src/components/edit-history-controls.jsx:35 #: src/components/gif-picker-modal.jsx:208 #: src/components/media-modal.jsx:478 -#: src/components/timeline.jsx:981 +#: src/components/timeline.jsx:971 msgid "Previous" msgstr "" #: src/components/edit-history-controls.jsx:47 #: src/components/gif-picker-modal.jsx:226 #: src/components/media-modal.jsx:497 -#: src/components/timeline.jsx:998 +#: src/components/timeline.jsx:988 msgid "Next" msgstr "" @@ -1406,7 +1406,7 @@ msgstr "" #: src/components/status-compact.jsx:74 #: src/components/status.jsx:3618 #: src/components/status.jsx:3696 -#: src/components/timeline.jsx:1057 +#: src/components/timeline.jsx:1047 #: src/pages/catchup.jsx:79 #: src/pages/catchup.jsx:2052 msgid "Filtered" @@ -3066,7 +3066,7 @@ msgid "Pinned posts" msgstr "Pinned posts" #. placeholder {0}: filterInfo.titlesStr -#: src/components/timeline.jsx:1052 +#: src/components/timeline.jsx:1042 msgid "<0>Filtered: <1>{0}" msgstr "" From dbfad960336c53bd2f3a2c39468d7a8b6d4a9d70 Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Tue, 26 May 2026 20:39:47 +0800 Subject: [PATCH 07/12] Fix cards are not spoiler-proof on Safari --- src/components/status.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/status.css b/src/components/status.css index 3119563258..5d80d17b23 100644 --- a/src/components/status.css +++ b/src/components/status.css @@ -804,6 +804,10 @@ filter: contrast(0); background-color: #000; } + .title, + .meta { + background-color: currentColor; + } * { text-decoration-color: inherit; text-decoration-thickness: 1.5em; From 749fe55fe87bd395454efc2b4ad265b2290b216a Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Tue, 26 May 2026 22:23:42 +0800 Subject: [PATCH 08/12] Upgrade oxfmt --- package-lock.json | 170 ++++++++++++++++++++++++---------------------- package.json | 2 +- 2 files changed, 88 insertions(+), 84 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2df720198e..44b8cfc776 100644 --- a/package-lock.json +++ b/package-lock.json @@ -64,7 +64,7 @@ "@playwright/test": "~1.60.0", "@preact/preset-vite": "~2.10.5", "@types/node": "~25.9.1", - "oxfmt": "~0.51.0", + "oxfmt": "~0.52.0", "postcss": "~8.5.15", "postcss-dark-theme-class": "~2.0.0", "postcss-preset-env": "~11.3.0", @@ -4097,9 +4097,9 @@ } }, "node_modules/@oxfmt/binding-android-arm-eabi": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.51.0.tgz", - "integrity": "sha512-Ni0sCqg5CIHaLIYFGj+ncbcumylvNC6FE4rfD0KfdmnWHbPJ+zev0qZCXKxy2hFVa0fYRK0yPzf5nzPbkZou7g==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.52.0.tgz", + "integrity": "sha512-17EMSJnQ9g+upVHrAUYDMfH5lvRKQ9Nvg8WtEoH72oDr1VpWz+7/o3tD97U1EToen2YAQ/68JmtDYkQUi20dfQ==", "cpu": [ "arm" ], @@ -4114,9 +4114,9 @@ } }, "node_modules/@oxfmt/binding-android-arm64": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.51.0.tgz", - "integrity": "sha512-eu5lAZjuo0KAkp+M24EhDqfOwA8owQ8d7wyBlOUUGRbDLHpU3IRlDHp8Dif+YqGlxs6jra7yS6WQu/NkPhAxeg==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.52.0.tgz", + "integrity": "sha512-A2G1IdwGEW2lLJkIxcvuirRH1CzSl/e0NX11zTlW1gvxJThfwbI/BEoaKrTNpm7M2FchvIf6guvIQU7d5iz+OQ==", "cpu": [ "arm64" ], @@ -4131,9 +4131,9 @@ } }, "node_modules/@oxfmt/binding-darwin-arm64": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.51.0.tgz", - "integrity": "sha512-6LsUNIdURhhcIfIn8+xsOb61mSTa9msAHTeSGx9Jf4rsP/gN8PGCF+SKWPAQZbND2w/WBkqQ6303jqEEIXzMdQ==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.52.0.tgz", + "integrity": "sha512-f9+bLvOYxy7NttCLFTvQ7afmqDOWY4wIP9xdvfj5trQ1qj6f2UFAGwZESlfsMjvJNTyRpXfIlOanCI9FOvoeQA==", "cpu": [ "arm64" ], @@ -4148,9 +4148,9 @@ } }, "node_modules/@oxfmt/binding-darwin-x64": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.51.0.tgz", - "integrity": "sha512-9aUMGmVxdHjYMsEAW1tNRoieTJXlVNDFkRvIR1J7LttJXWjVYCu2ekclLij2KJtxBxSQOYSHd12ME/adVGVbZg==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.52.0.tgz", + "integrity": "sha512-YSTB9sJ5nnQd/Q0ddHkgof0ZCHPAnWZT1IW2SJ8omz7CP7KluJhO1fNHrpqdxCtpztJwSs4hY1uAee35wKxxaw==", "cpu": [ "x64" ], @@ -4165,9 +4165,9 @@ } }, "node_modules/@oxfmt/binding-freebsd-x64": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.51.0.tgz", - "integrity": "sha512-mkY1nhZTqYb+NHaAWxOCKISN6FwdrwMNsu17vTUA3wzUV2VJ+Paq15ZokRcsMU/2PUdHO73prxyeJpjXQ3MPpQ==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.52.0.tgz", + "integrity": "sha512-NIrRNTTPCs4UbmVs0bxLSCDlLCtIRMJIXklNKaXa5Oj2/K1UIMBvgE8+uPVo01Io3N9HF0+GAX+aAHjUgZS7vA==", "cpu": [ "x64" ], @@ -4182,9 +4182,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm-gnueabihf": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.51.0.tgz", - "integrity": "sha512-wtFwNwE4+YCNuPaWoGDZeGsKvD6D1YSUNBJNn/rJBh7CrDBThFE+TBI5kY7vRW9rIOQRsbW2IpyyL3Du4Zqwiw==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.52.0.tgz", + "integrity": "sha512-JXUCde8mn3GpgQouz2PXUokgy/uT1QrRJBL2s983VWcSQp62wTFYiNXgTKdeo1Jgbr0IgUnKKvzIk/YBlj/nVQ==", "cpu": [ "arm" ], @@ -4199,9 +4199,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm-musleabihf": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.51.0.tgz", - "integrity": "sha512-rnOaNx86G7iRKM6lsCIQMux0SMGNC/TEbFR+r7lpruJ12bnrIWgxd5w1PLqOvgR9r8ZJbpK/zfRKctJnh8/Jfg==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.52.0.tgz", + "integrity": "sha512-psbUXaRZ+V8DaXz10Qf7LSHtdtdKAmC8fxXgeU608jjzrmWK4quamZMOpl6sf+dikoFHA85uE93Q0BqxrCdQrQ==", "cpu": [ "arm" ], @@ -4216,9 +4216,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm64-gnu": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.51.0.tgz", - "integrity": "sha512-jOgDzSqWcICGRjsp4mc08FxKMN8vzP2Kgs4E0d2HUP99F+nJDQKklRV4Zuj+0gcBgjrzx2CbpqaIdUVPepCojA==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.52.0.tgz", + "integrity": "sha512-Jw7MgWUU9lcLCcy82updISP3EthTlfvAwR6gWNxPzqly7+fLvOi2gHQE9xXQjpqaVLm/8P+gOzlv9ODuoVlaaw==", "cpu": [ "arm64" ], @@ -4236,9 +4236,9 @@ } }, "node_modules/@oxfmt/binding-linux-arm64-musl": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.51.0.tgz", - "integrity": "sha512-KBUCdrH5bwVrAvI9gU/1S55oH6fzXjr++J/oVocdu7bYTks1l7DNNT+rLd/1TDdAEjObGwmfWamn7LC1m8A0DQ==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.52.0.tgz", + "integrity": "sha512-wZg6bLjDvh2KibyI3QFUYo8GTXneIFsd0JvehtvJiUmQ8WRPERgxd/VM4ctWb86U5FT1FkqgS8/wZKVB+AZScg==", "cpu": [ "arm64" ], @@ -4256,9 +4256,9 @@ } }, "node_modules/@oxfmt/binding-linux-ppc64-gnu": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.51.0.tgz", - "integrity": "sha512-NapfjYsABFqTJ1Dn9Efq6sN5esaHconVKwVLbDGNQLrwpOx/g17mkwErHzU72PutL67nf3wNAkbq122H+zLxag==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.52.0.tgz", + "integrity": "sha512-IngE8uxhNvxcMrLjZNDo9xNLY7rEK33AKnaMd2B46he1e/mz2CfcW6If/U1wUjdRZddm1QzQaciqZkuMkdh1FA==", "cpu": [ "ppc64" ], @@ -4276,9 +4276,9 @@ } }, "node_modules/@oxfmt/binding-linux-riscv64-gnu": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.51.0.tgz", - "integrity": "sha512-5dlDt1dUZCVi6elIhiK1PWg9wpTzTcIuj0IZnSurvIoMrhOWqqTcc1dSTxcSkNaBZhfsNqRZdINI1zAgbKkJNQ==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.52.0.tgz", + "integrity": "sha512-H3+DdFMv/efN3Efmhsv18jDrpiWWqKG7wsfAlQBqAt6z/E2Bx+TwEj2Nowe51CPOWB8/mFBC2dAMSgVFLvvowA==", "cpu": [ "riscv64" ], @@ -4296,9 +4296,9 @@ } }, "node_modules/@oxfmt/binding-linux-riscv64-musl": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.51.0.tgz", - "integrity": "sha512-pgdWUJn0S5nulyiVdlFV8DzCUnGXkU99W5PSkkmbaZW+LrZBPxpezun4G0DDHbQaVYuJeCuKsXsGKGo77CkUTQ==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.52.0.tgz", + "integrity": "sha512-zji+1kb7lJKohSDjzC1IsS+K/cKRs1hdVf0ZH0VbdbiakmtLvN9twBoXo/k8VdjFax7kfo+DyPxS7vv52br1aw==", "cpu": [ "riscv64" ], @@ -4316,9 +4316,9 @@ } }, "node_modules/@oxfmt/binding-linux-s390x-gnu": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.51.0.tgz", - "integrity": "sha512-2XTFUe97CbDGAI8vjwDfZ1HdakO0XIADyJ24idEg64SC4/K4in/OisXVnrW4NMK7I6TgC7EqRhC0Ln/nKhAemA==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.52.0.tgz", + "integrity": "sha512-hcLBYedpCy7ToUvvBidWk7+11Yhg1oAZ4+6hKPic/mQI6NaqXJSXMps5nFlwUuX2ewhtLZZDPg63TI042qGKBg==", "cpu": [ "s390x" ], @@ -4336,9 +4336,9 @@ } }, "node_modules/@oxfmt/binding-linux-x64-gnu": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.51.0.tgz", - "integrity": "sha512-kQ1OuCqqt/yyf0ZN9VFxW1/JnlgJgii3Dr7pWf9vNBvrX1hv6g39/+mc5oGRHRGJFZtl3zsGDWR9c5N2B/gwBw==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.52.0.tgz", + "integrity": "sha512-IDO2loXK2OtTOhSPchU9MW25mWL2QCDGdJbjN8MXKZVS80qXe5gMTwQWu/gMJ3juoBHbkuUZNB2N1LHzNT7DoA==", "cpu": [ "x64" ], @@ -4356,9 +4356,9 @@ } }, "node_modules/@oxfmt/binding-linux-x64-musl": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.51.0.tgz", - "integrity": "sha512-ARTYqxHF475o96Gbn41hvSWSSRygPlRDXZZgZ9I2scU1y0qiWpCQyZCoefaQa0mwv+wwtZ+luS4YOzsRzM/izg==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.52.0.tgz", + "integrity": "sha512-mAV2Hjn0SatJ+KoAzKUC3eJhdJ8wv+3m1KyuS0dTsbF0c5weq+QrCt/DRZZM+uj/XiKzCDEUKYsBF30e2qkcyw==", "cpu": [ "x64" ], @@ -4376,9 +4376,9 @@ } }, "node_modules/@oxfmt/binding-openharmony-arm64": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.51.0.tgz", - "integrity": "sha512-QiC1XrCl6a6BmqMzduO8hdIRMf1m44hCkt2Q68KWkTvUB/E7fd2iomyNh6KnnRca5w6eBrRAAtLFqTh+xjsjJA==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.52.0.tgz", + "integrity": "sha512-vd4npaUIwChxp7XzkqmepBWTT9YMcSe/NBApVGPC30/lLyOVaV3dvma1SKo03t8O73BPRAG7EyJzGlN5cJM5hQ==", "cpu": [ "arm64" ], @@ -4393,9 +4393,9 @@ } }, "node_modules/@oxfmt/binding-win32-arm64-msvc": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.51.0.tgz", - "integrity": "sha512-NC/hJb9dtU23Zf8L7IVK95xnFjiQ7AfcLO2l5pb69TDEr958qxrtnB2CveeeNSCBFNIkgaTCfd/vHNSoG78l9g==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.52.0.tgz", + "integrity": "sha512-k2sz6gWQdMfh5HPpIS+Bw/0UEV/kaK2xuqJRrWL233sEHx9WLlsmvlPFM4HUNThkYbSN0U0vPW7LVKZWDS8hPQ==", "cpu": [ "arm64" ], @@ -4410,9 +4410,9 @@ } }, "node_modules/@oxfmt/binding-win32-ia32-msvc": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.51.0.tgz", - "integrity": "sha512-2C45za4Rj36n8YIbhRL1PQbxmXJYf81WEcAgvj5I4ptRROG+A+81hREEN5bmCHADE1UfYaN312U6tkILoZZy6w==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.52.0.tgz", + "integrity": "sha512-rhke69GTcArodLHpjMTfNnvjTEBryDeZcUCKK/VjXDMtfTULl6QRh0ymX5/hbCUv2WjYm9h/QbW++q2vE15gWQ==", "cpu": [ "ia32" ], @@ -4427,9 +4427,9 @@ } }, "node_modules/@oxfmt/binding-win32-x64-msvc": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.51.0.tgz", - "integrity": "sha512-73RqdAuVKQTkjZIDw08JaDHUM4lav5Qu+CaPwg4QbbA7k8o7LEW0p3UsfZ/F8dsO/pwVYh3RzFcanwLRTTahbQ==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.52.0.tgz", + "integrity": "sha512-q5xL7oeXkZdEtNZWBdvehJcmt+GRu9l2bK40yJs1jJXlqq+r0Hygb1rTjq+FM2o/2xyt4cufH6KRplHp3Jjsvw==", "cpu": [ "x64" ], @@ -8811,9 +8811,9 @@ } }, "node_modules/oxfmt": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.51.0.tgz", - "integrity": "sha512-l/AoAnaEOV7Q5/Z9kHOMDehVJnCgYN7wRoooWCTUMBMi16BJhLZqd9cmCnwcVFfVlzkt53zK2KLPFNp8vSsoDg==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.52.0.tgz", + "integrity": "sha512-nJlYM35F64zTDMecCNhoHNkf+D/eHv7xcjj9XDSj+bFAVtN93m7v8DQMdHd6nDG6Akf/kEYYHmDUBs2Dz27Sug==", "dev": true, "license": "MIT", "dependencies": { @@ -8829,32 +8829,36 @@ "url": "https://github.com/sponsors/Boshen" }, "optionalDependencies": { - "@oxfmt/binding-android-arm-eabi": "0.51.0", - "@oxfmt/binding-android-arm64": "0.51.0", - "@oxfmt/binding-darwin-arm64": "0.51.0", - "@oxfmt/binding-darwin-x64": "0.51.0", - "@oxfmt/binding-freebsd-x64": "0.51.0", - "@oxfmt/binding-linux-arm-gnueabihf": "0.51.0", - "@oxfmt/binding-linux-arm-musleabihf": "0.51.0", - "@oxfmt/binding-linux-arm64-gnu": "0.51.0", - "@oxfmt/binding-linux-arm64-musl": "0.51.0", - "@oxfmt/binding-linux-ppc64-gnu": "0.51.0", - "@oxfmt/binding-linux-riscv64-gnu": "0.51.0", - "@oxfmt/binding-linux-riscv64-musl": "0.51.0", - "@oxfmt/binding-linux-s390x-gnu": "0.51.0", - "@oxfmt/binding-linux-x64-gnu": "0.51.0", - "@oxfmt/binding-linux-x64-musl": "0.51.0", - "@oxfmt/binding-openharmony-arm64": "0.51.0", - "@oxfmt/binding-win32-arm64-msvc": "0.51.0", - "@oxfmt/binding-win32-ia32-msvc": "0.51.0", - "@oxfmt/binding-win32-x64-msvc": "0.51.0" - }, - "peerDependencies": { - "svelte": "^5.0.0" + "@oxfmt/binding-android-arm-eabi": "0.52.0", + "@oxfmt/binding-android-arm64": "0.52.0", + "@oxfmt/binding-darwin-arm64": "0.52.0", + "@oxfmt/binding-darwin-x64": "0.52.0", + "@oxfmt/binding-freebsd-x64": "0.52.0", + "@oxfmt/binding-linux-arm-gnueabihf": "0.52.0", + "@oxfmt/binding-linux-arm-musleabihf": "0.52.0", + "@oxfmt/binding-linux-arm64-gnu": "0.52.0", + "@oxfmt/binding-linux-arm64-musl": "0.52.0", + "@oxfmt/binding-linux-ppc64-gnu": "0.52.0", + "@oxfmt/binding-linux-riscv64-gnu": "0.52.0", + "@oxfmt/binding-linux-riscv64-musl": "0.52.0", + "@oxfmt/binding-linux-s390x-gnu": "0.52.0", + "@oxfmt/binding-linux-x64-gnu": "0.52.0", + "@oxfmt/binding-linux-x64-musl": "0.52.0", + "@oxfmt/binding-openharmony-arm64": "0.52.0", + "@oxfmt/binding-win32-arm64-msvc": "0.52.0", + "@oxfmt/binding-win32-ia32-msvc": "0.52.0", + "@oxfmt/binding-win32-x64-msvc": "0.52.0" + }, + "peerDependencies": { + "svelte": "^5.0.0", + "vite-plus": "*" }, "peerDependenciesMeta": { "svelte": { "optional": true + }, + "vite-plus": { + "optional": true } } }, diff --git a/package.json b/package.json index 113fa6b3ea..7816d38d39 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "@playwright/test": "~1.60.0", "@preact/preset-vite": "~2.10.5", "@types/node": "~25.9.1", - "oxfmt": "~0.51.0", + "oxfmt": "~0.52.0", "postcss": "~8.5.15", "postcss-dark-theme-class": "~2.0.0", "postcss-preset-env": "~11.3.0", From f0a5590f8935766e52b1df615758a1c18ddcfe32 Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Wed, 27 May 2026 19:06:32 +0800 Subject: [PATCH 09/12] Fix multiple videos autoplaying with sound in media carousel modal --- src/components/media-modal.jsx | 28 +++++++++++++++++++++++++++- src/components/media.jsx | 12 +++++++++--- src/locales/en.po | 22 +++++++++++----------- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/src/components/media-modal.jsx b/src/components/media-modal.jsx index 5b5d1097ee..4c9e730d92 100644 --- a/src/components/media-modal.jsx +++ b/src/components/media-modal.jsx @@ -113,6 +113,27 @@ function MediaModal({ }; }, []); + const prevIndexRef = useRef(currentIndex); + useEffect(() => { + const prevIndex = prevIndexRef.current; + prevIndexRef.current = currentIndex; + if (prevIndex === currentIndex) return; + + const carousel = carouselRef.current; + if (!carousel) return; + + carousel.querySelectorAll('video, audio').forEach((el) => { + if (el.muted) return; + const item = el.closest('.carousel-item'); + if (item) { + const idx = Array.from(item.parentNode.children).indexOf(item); + if (idx !== currentIndex) { + el.pause(); + } + } + }); + }, [currentIndex]); + useEffect(() => { let timer = setTimeout(() => { carouselRef.current?.focus?.(); @@ -319,7 +340,12 @@ function MediaModal({ )} - + ); })} diff --git a/src/components/media.jsx b/src/components/media.jsx index f040c43189..95e476a00b 100644 --- a/src/components/media.jsx +++ b/src/components/media.jsx @@ -93,6 +93,7 @@ function Media({ altIndex, checkAspectRatio = true, onClick, + autoplay = false, }) { let { id, @@ -585,7 +586,7 @@ function Media({ data-orientation="${orientation}" style="view-transition-name: ${mediaVTN}" preload="auto" - autoplay + ${autoplay ? 'autoplay' : ''} playsinline ${loopable ? 'loop' : ''} controls @@ -801,11 +802,16 @@ function Media({ preload="metadata" controls controlsList="nofullscreen" - autoPlay + autoPlay={autoplay} playsInline /> ) : ( -