diff --git a/CHANGELOG.md b/CHANGELOG.md
index 249596dc05..bebb2a3b15 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,88 @@
All notable changes to this project will be documented in this file.
+## [4.5.0] - UNRELEASED
+
+### Added
+
+- **Add support for allowing and authoring quotes** (#35355, #35578, #35614, #35618, #35624, #35626, #35652, #35629, #35665, #35653, #35670, #35677, #35690, #35697, #35689, #35699, #35700, #35701, #35709, #35714, #35713, #35715, #35725, #35749, #35769, #35780, #35762, #35804, #35808, #35805, #35819, #35824, #35828, #35822, #35835, #35865, #35860, #35832, #35891, #35894, #35895, #35820, #35917, #35924, #35925, #35914, #35930, #35941, #35939, #35948, #35955, #35967, #35990, #35991, #35975, #35971, #36002, #35986, #36031, #36034, #36038, #36054, #36052, #36055, #36065, #36068, #36083, #36087, #36080, #36091, #36090, #36118, #36119, #36128, #36094, #36129, #36138, #36132, #36151, #36158, #36171, #36194, #36220, #36169, #36130, #36249, #36153, #36299, #36291, #36301, #36315, #36317, #36364, #36383, #36381, #36459, #36464, and #36461 by @ChaosExAnima, @ClearlyClaire, @Lycolia, @diondiondion, and @tribela)\
+ This includes a revamp of the composer interface.\
+ See https://blog.joinmastodon.org/2025/09/introducing-quote-posts/ for a user-centric overview of the feature, and https://docs.joinmastodon.org/client/quotes/ for API documentation.
+- **Add support for fetching and refreshing replies to the web UI** (#35210, #35496, #35575, #35500, #35577, #35602, #35603, #35654, #36141, #36237, #36172, #36256, #36271, #36334, #36382, and #36239 by @ClearlyClaire, @Gargron, and @diondiondion)
+- **Add ability to block words in usernames** (#35407, #35655, and #35806 by @ClearlyClaire and @Gargron)
+- Add support for displaying link previews for Admin UI (#35958 by @ThisIsMissEm)
+- Add support for dynamic viewport height (#36272 by @e1berd)
+- Add support for numeric-based URIs for new local accounts (#32724, #36304, #36316, and #36365 by @ClearlyClaire)
+- Add Traditional Mongolian to posting languages (#36196 by @shimon1024)
+- Add example post with manual quote approval policy to `dev:populate_sample_data` (#36099 by @ClearlyClaire)
+- Add server-side support for handling posts with a quote policy allowing followers to quote (#36093 and #36127 by @ClearlyClaire)
+- Add schema.org markup to SEO-enabled posts (#36075 by @Gargron)
+- Add migration to fill unset default quote policy based on default post privacy (#36041 by @ClearlyClaire)
+- Add support for exposing conversation context for new public conversations according to FEP-7888 (#35959 and #36064 by @ClearlyClaire and @jesseplusplus)
+- Add digest re-check before removing followers in synchronization mechanism (#34273 by @ClearlyClaire)
+- Add “Posting defaults” setting page, moving existing settings from “Other” (#35896, #36033, #35966, #35969, and #36084 by @ClearlyClaire and @diondiondion)
+- Add support for displaying Valkey version on admin dashboard (#35785 by @ykzts)
+- Add delivery failure tracking and handling to FASP jobs (#35625, #35628, and #35723 by @oneiros)
+- Add example of quote post with a preview card to development sample data (#35616 by @ClearlyClaire)
+- Add second set of blocked text that applies to accounts regardless of account age for spam-blocking (#35563 by @ClearlyClaire)
+- Add experimental feature to select custom emoji rendering (#35229, #35282, #35253, #35424, #35473, #35483, #35505, #35568, #35605, #35659, #35664, #35739, #35985, #36051, #36071, #36137, #36165, #36248, #36262, #36275, #36293, #36341, #36342, #36366, #36377, #36378, #36385, #36393, #36397, #36403, #36413, #36410, #36454, and #36402 by @ChaosExAnima and @braddunbar)\
+ This also completely reworks the processing and rendering of emojis and server-rendered HTML in statuses and other places.
+
+### Changed
+
+- Change confirmation dialogs for follow button actions “unfollow”, “unblock”, and “withdraw request” (#36289 by @diondiondion)
+- Change “Follow” button labels (#36264 by @diondiondion)
+- Change display of content warnings in Admin UI (#35935 by @ThisIsMissEm)
+- Change index on `follows` table to improve performance of some queries (#36374 by @ClearlyClaire)
+- Change links to accounts in settings and moderation views to link to local view unless account is suspended (#36340 by @diondiondion)
+- Change redirection for denied registration from web app to sign-in page with error message (#36384 by @ClearlyClaire)
+- Change `timeline_preview` setting into four more granular settings (#36338 and #36467 by @ClearlyClaire)
+- Change wording and design of interaction dialog to simplify it (#36124 by @diondiondion)
+- Change dropdown menus to allow disabled items to be focused (#36078 by @diondiondion)
+- Change modal background colours in light mode (#36069 by @diondiondion)
+- Change “Posting defaults” settings page to enforce `nobody` quote policy for `private` default visibility (#36040 by @ClearlyClaire)
+- Change description of “Quiet public” (#36032 by @ClearlyClaire)
+- Change “Boost with original visibility” to “Share again with your followers” (#36035 by @ClearlyClaire)
+- Change handling of push subscriptions to automatically delete invalid ones on delivery (#35987 by @ThisIsMissEm)
+- Change design of quote posts in web UI (#35584 and #35834 by @ClearlyClaire and @Gargron)
+- Change auditable accounts to be sorted by username in admin action logs interface (#35272 by @breadtk)
+- Change order of translation restoration and service credit on post card (#33619 by @colindean)
+- Change position of ‘add more’ to be inside table toolbar on reports (#35963 by @ThisIsMissEm)
+
+### Fixed
+
+- Fix rendering of poll options in status history modal (#35633 by @ThisIsMissEm)
+- Fix “mute” button being displayed to unauthenticated visitors in hashtag dropdown (#36353 by @mkljczk)
+- Fix overflow handling of `.more-from-author` (#36310 by @edent)
+- Fix unfortunate action button wrapping in admin area (#36247 by @diondiondion)
+- Fix translate button width in Safari (#36164 and #36216 by @diondiondion)
+- Fix login page linking to other pages within OAuth authorization flow (#36115 by @Gargron)
+- Fix stale search results being displayed in Web UI while new query is in progress (#36053 by @ChaosExAnima)
+- Fix YouTube iframe not being able to start at a defined time (#26584 by @BrunoViveiros)
+- Fix banned text being able to be circumvented via unicode (#35978 by @Gargron)
+- Fix batch table toolbar displaying under status media (#35962 by @ThisIsMissEm)
+- Fix incorrect RSS feed MIME type in gzip_types directive (#35562 by @iioflow)
+- Fix 404 error after deleting status from detail view (#35800) (#35881 by @crafkaz)
+- Fix feeds keyboard navigation issues (#35853, #35864, and #36267 by @braddunbar and @diondiondion)
+- Fix layout shift caused by “Who to follow” widget (#35861 by @diondiondion)
+- Fix Vagrantfile (#35765 by @ClearlyClaire)
+- Fix reply indicator displaying wrong avatar in rare cases (#35756 by @ClearlyClaire)
+- Fix `Chewy::UndefinedUpdateStrategy` in `dev:populate_sample_data` task when Elasticsearch is enabled (#35615 by @ClearlyClaire)
+- Fix unnecessary account note addition for already-muted moved-to users (#35566 by @mjankowski)
+- Fix seeded admin user creation failing on specific configurations (#35565 by @oneiros)
+- Fix media modal images in Web UI having redundant `title` attribute (#35468 by @mayank99)
+- Fix inconsistent default privacy post setting when unset in settings (#35422 by @oneiros)
+- Fix glitchy status keyboard navigation (#35455 and #35504 by @diondiondion)
+- Fix post being submitted when pressing “Enter” in the CW field (#35445 by @diondiondion)
+
+## [4.4.7] - 2025-10-15
+
+### Fixed
+
+- Fix forwarder being called with `nil` status when quote post is soft-deleted (#36463 by @ClearlyClaire)
+- Fix moderation warning e-mails that include posts (#36462 by @ClearlyClaire)
+- Fix allow_referrer_origin typo (#36460 by @ShadowJonathan)
+
## [4.4.6] - 2025-10-13
### Security
diff --git a/Gemfile b/Gemfile
index aa201d1e72..a12e716920 100644
--- a/Gemfile
+++ b/Gemfile
@@ -105,7 +105,7 @@ gem 'prometheus_exporter', '~> 2.2', require: false
gem 'opentelemetry-api', '~> 1.7.0'
group :opentelemetry do
- gem 'opentelemetry-exporter-otlp', '~> 0.30.0', require: false
+ gem 'opentelemetry-exporter-otlp', '~> 0.31.0', require: false
gem 'opentelemetry-instrumentation-active_job', '~> 0.9.0', require: false
gem 'opentelemetry-instrumentation-active_model_serializers', '~> 0.23.0', require: false
gem 'opentelemetry-instrumentation-concurrent_ruby', '~> 0.23.0', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 1d63e0d955..991cdf1549 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -121,7 +121,7 @@ GEM
erubi (>= 1.0.0)
rack (>= 0.9.0)
rouge (>= 1.0.0)
- bigdecimal (3.2.3)
+ bigdecimal (3.3.1)
bindata (2.5.1)
binding_of_caller (1.0.1)
debug_inspector (>= 1.2.0)
@@ -277,7 +277,7 @@ GEM
google-protobuf (4.32.1)
bigdecimal
rake (>= 13)
- googleapis-common-protos-types (1.21.0)
+ googleapis-common-protos-types (1.22.0)
google-protobuf (~> 4.26)
haml (6.3.0)
temple (>= 0.8.2)
@@ -502,9 +502,9 @@ GEM
openssl-signature_algorithm (1.3.0)
openssl (> 2.0)
opentelemetry-api (1.7.0)
- opentelemetry-common (0.22.0)
+ opentelemetry-common (0.23.0)
opentelemetry-api (~> 1.0)
- opentelemetry-exporter-otlp (0.30.0)
+ opentelemetry-exporter-otlp (0.31.0)
google-protobuf (>= 3.18)
googleapis-common-protos-types (~> 1.3)
opentelemetry-api (~> 1.1)
@@ -568,7 +568,7 @@ GEM
opentelemetry-instrumentation-base (~> 0.24)
opentelemetry-registry (0.4.0)
opentelemetry-api (~> 1.1)
- opentelemetry-sdk (1.9.0)
+ opentelemetry-sdk (1.10.0)
opentelemetry-api (~> 1.1)
opentelemetry-common (~> 0.20)
opentelemetry-registry (~> 0.2)
@@ -1008,7 +1008,7 @@ DEPENDENCIES
omniauth-saml (~> 2.0)
omniauth_openid_connect (~> 0.8.0)
opentelemetry-api (~> 1.7.0)
- opentelemetry-exporter-otlp (~> 0.30.0)
+ opentelemetry-exporter-otlp (~> 0.31.0)
opentelemetry-instrumentation-active_job (~> 0.9.0)
opentelemetry-instrumentation-active_model_serializers (~> 0.23.0)
opentelemetry-instrumentation-concurrent_ruby (~> 0.23.0)
diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb
index fc430544fb..780c0be319 100644
--- a/app/controllers/auth/registrations_controller.rb
+++ b/app/controllers/auth/registrations_controller.rb
@@ -89,7 +89,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
end
def check_enabled_registrations
- redirect_to root_path unless allowed_registration?(request.remote_ip, @invite)
+ redirect_to new_user_session_path, alert: I18n.t('devise.failure.closed_registrations', email: Setting.site_contact_email) unless allowed_registration?(request.remote_ip, @invite)
end
def invite_code
diff --git a/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx b/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx
index c9a5826566..f260444265 100644
--- a/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx
@@ -93,14 +93,16 @@ class CompareHistoryModal extends PureComponent {
{currentVersion.getIn(['poll', 'options']).map(option => (
-
-
-
+
+ {/* FIXME: does not support multiple choice, #35632 */}
+
+
+
))}
diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json
index dc02cf731a..0a7b3c805e 100644
--- a/app/javascript/mastodon/locales/be.json
+++ b/app/javascript/mastodon/locales/be.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "Ціхі публічны",
"privacy_policy.last_updated": "Адноўлена {date}",
"privacy_policy.title": "Палітыка канфідэнцыйнасці",
+ "quote_error.edit": "Нельга дадаваць цытаты пры рэдагаванні допісаў.",
"quote_error.poll": "Нельга цытаваць з апытаннямі.",
"quote_error.quote": "За раз дазволена рабіць толькі адну цытату.",
"quote_error.unauthorized": "Вы не ўвайшлі, каб цытаваць гэты допіс.",
diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json
index 3ba60cb04c..b9f7d0bdfb 100644
--- a/app/javascript/mastodon/locales/cs.json
+++ b/app/javascript/mastodon/locales/cs.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "Ztišené veřejné",
"privacy_policy.last_updated": "Naposledy aktualizováno {date}",
"privacy_policy.title": "Zásady ochrany osobních údajů",
+ "quote_error.edit": "Citáty nemohou být přidány při úpravě příspěvku.",
"quote_error.poll": "Citování není u dotazníků povoleno.",
"quote_error.quote": "Je povoleno citovat pouze jednou.",
"quote_error.unauthorized": "Nemáte oprávnění citovat tento příspěvek.",
diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json
index 255b41e871..c36da1a614 100644
--- a/app/javascript/mastodon/locales/da.json
+++ b/app/javascript/mastodon/locales/da.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "Offentlig (stille)",
"privacy_policy.last_updated": "Senest opdateret {date}",
"privacy_policy.title": "Privatlivspolitik",
+ "quote_error.edit": "Citater kan ikke tilføjes ved redigering af et indlæg.",
"quote_error.poll": "Citering ikke tilladt i afstemninger.",
"quote_error.quote": "Kun ét citat ad gangen er tilladt.",
"quote_error.unauthorized": "Du har ikke tilladelse til at citere dette indlæg.",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index c1d848ee07..b7d52e4e50 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "Öffentlich (still)",
"privacy_policy.last_updated": "Stand: {date}",
"privacy_policy.title": "Datenschutzerklärung",
+ "quote_error.edit": "Beim Bearbeiten eines Beitrags können keine Zitate hinzugefügt werden.",
"quote_error.poll": "Zitieren ist bei Umfragen nicht gestattet.",
"quote_error.quote": "Es ist jeweils nur ein Zitat zulässig.",
"quote_error.unauthorized": "Du bist nicht berechtigt, diesen Beitrag zu zitieren.",
diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json
index 5c94e6d858..400171aeb0 100644
--- a/app/javascript/mastodon/locales/el.json
+++ b/app/javascript/mastodon/locales/el.json
@@ -739,7 +739,7 @@
"poll_button.add_poll": "Προσθήκη δημοσκόπησης",
"poll_button.remove_poll": "Αφαίρεση δημοσκόπησης",
"privacy.change": "Προσαρμογή ιδιωτικότητας ανάρτησης",
- "privacy.direct.long": "Όλοι όσοι αναφέρθηκαν στην ανάρτηση",
+ "privacy.direct.long": "Όλοι όσοι επισημάνθηκαν στην ανάρτηση",
"privacy.direct.short": "Ιδιωτική επισήμανση",
"privacy.private.long": "Μόνο οι ακόλουθοί σας",
"privacy.private.short": "Ακόλουθοι",
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "Ήσυχα δημόσια",
"privacy_policy.last_updated": "Τελευταία ενημέρωση {date}",
"privacy_policy.title": "Πολιτική Απορρήτου",
+ "quote_error.edit": "Δεν μπορούν να προστεθούν παραθέσεις κατά την επεξεργασία μιας ανάρτησης.",
"quote_error.poll": "Η παράθεση δεν επιτρέπεται με δημοσκοπήσεις.",
"quote_error.quote": "Επιτρέπεται μόνο μία παράθεση τη φορά.",
"quote_error.unauthorized": "Δεν είστε εξουσιοδοτημένοι να παραθέσετε αυτή την ανάρτηση.",
diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json
index cb6ba17612..d9b5bdaec5 100644
--- a/app/javascript/mastodon/locales/es-AR.json
+++ b/app/javascript/mastodon/locales/es-AR.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "Público silencioso",
"privacy_policy.last_updated": "Última actualización: {date}",
"privacy_policy.title": "Política de privacidad",
+ "quote_error.edit": "Las citas no se pueden agregar al editar un mensaje.",
"quote_error.poll": "No se permite citar encuestas.",
"quote_error.quote": "Solo se permite una cita a la vez.",
"quote_error.unauthorized": "No tenés autorización para citar este mensaje.",
diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json
index 59b0b68c88..a523b32867 100644
--- a/app/javascript/mastodon/locales/es-MX.json
+++ b/app/javascript/mastodon/locales/es-MX.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "Pública, pero discreta",
"privacy_policy.last_updated": "Actualizado por última vez {date}",
"privacy_policy.title": "Política de Privacidad",
+ "quote_error.edit": "No se pueden añadir citas mientras se edita una publicación.",
"quote_error.poll": "No se permite citar encuestas.",
"quote_error.quote": "Solo se permite una cita a la vez.",
"quote_error.unauthorized": "No estás autorizado a citar esta publicación.",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index 9985cdea1e..96ae785743 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "Pública silenciosa",
"privacy_policy.last_updated": "Actualizado por última vez {date}",
"privacy_policy.title": "Política de Privacidad",
+ "quote_error.edit": "No se pueden añadir citas mientras se edita una publicación.",
"quote_error.poll": "No es posible citar encuestas.",
"quote_error.quote": "Solo se permite una cita a la vez.",
"quote_error.unauthorized": "No tienes permiso para citar esta publicación.",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index 4cdcece7fe..ca38be9513 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "Vaivihkaa julkinen",
"privacy_policy.last_updated": "Päivitetty viimeksi {date}",
"privacy_policy.title": "Tietosuojakäytäntö",
+ "quote_error.edit": "Lainauksia ei voi lisätä julkaisua muokattaessa.",
"quote_error.poll": "Äänestysten lainaaminen ei ole sallittua.",
"quote_error.quote": "Vain yksi lainaus kerrallaan on sallittu.",
"quote_error.unauthorized": "Sinulla ei ole valtuuksia lainata tätä julkaisua.",
diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json
index a83cd42763..55a3d2455b 100644
--- a/app/javascript/mastodon/locales/fo.json
+++ b/app/javascript/mastodon/locales/fo.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "Stillur almenningur",
"privacy_policy.last_updated": "Seinast dagført {date}",
"privacy_policy.title": "Privatlívspolitikkur",
+ "quote_error.edit": "Sitatir kunnu ikki leggjast afturat tá tú rættar ein post.",
"quote_error.poll": "Tað er ikki loyvt at sitera spurnarkanningar.",
"quote_error.quote": "Bara ein sitering er loyvd í senn.",
"quote_error.unauthorized": "Tú hevur ikki rættindi at sitera hendan postin.",
diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json
index 8ba7a73abe..0cec616ff0 100644
--- a/app/javascript/mastodon/locales/gl.json
+++ b/app/javascript/mastodon/locales/gl.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "Pública limitada",
"privacy_policy.last_updated": "Actualizado por última vez no {date}",
"privacy_policy.title": "Política de Privacidade",
+ "quote_error.edit": "Non se poden engadir citas ao editar unha publicación.",
"quote_error.poll": "Non se permite citar as enquisas.",
"quote_error.quote": "Só se permite citar unha vez.",
"quote_error.unauthorized": "Non tes permiso para citar esta publicación.",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index 61e8cb2e5f..9e7a90cab1 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "ציבורי שקט",
"privacy_policy.last_updated": "עודכן לאחרונה {date}",
"privacy_policy.title": "מדיניות פרטיות",
+ "quote_error.edit": "לא ניתן להוסיף ציטוטים בשלב עריכת ההודעה.",
"quote_error.poll": "לא ניתן לכלול משאל כאשר מחברים הודעת ציטוט.",
"quote_error.quote": "רק ציטוט אחד מותר בכל הודעה.",
"quote_error.unauthorized": "אין לך הרשאה לצטט את ההודעה הזו.",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index 1d1d824a45..5cc41a1340 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "Csendes nyilvános",
"privacy_policy.last_updated": "Utoljára frissítve: {date}",
"privacy_policy.title": "Adatvédelmi szabályzat",
+ "quote_error.edit": "Idézés nem adható hozzá bejegyzés szerkesztésekor.",
"quote_error.poll": "Az idézés szavazások esetén nincs engedélyezve.",
"quote_error.quote": "Egyszerre csak egy idézet van engedélyezve.",
"quote_error.unauthorized": "Nem idézheted ezt a bejegyzést.",
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index ecf8f46f75..12ffbec03d 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "Minder openbaar",
"privacy_policy.last_updated": "Laatst bijgewerkt op {date}",
"privacy_policy.title": "Privacybeleid",
+ "quote_error.edit": "Citaten kunnen niet tijdens het bewerken van een bericht worden toegevoegd.",
"quote_error.poll": "Het is niet mogelijk om polls te citeren.",
"quote_error.quote": "Je kunt maar één bericht per keer citeren.",
"quote_error.unauthorized": "Je bent niet gemachtigd om dit bericht te citeren.",
diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json
index 8e76cd8fe0..6f6d96509d 100644
--- a/app/javascript/mastodon/locales/sq.json
+++ b/app/javascript/mastodon/locales/sq.json
@@ -749,6 +749,7 @@
"privacy.unlisted.short": "Publik i qetë",
"privacy_policy.last_updated": "Përditësuar së fundi më {date}",
"privacy_policy.title": "Rregulla Privatësie",
+ "quote_error.edit": "Kur përpunohet një postim, s’mund të shtohen citime.",
"quote_error.poll": "Me pyetësorët nuk lejohet citim.",
"quote_error.quote": "Lejohet vetëm një citim në herë.",
"quote_error.unauthorized": "S’jen i autorizuar ta citoni këtë postim.",
diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index 6301c8b7da..19b37b569b 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "Sessizce herkese açık",
"privacy_policy.last_updated": "Son güncelleme {date}",
"privacy_policy.title": "Gizlilik Politikası",
+ "quote_error.edit": "Gönderi düzenlenirken alıntılar eklenemez.",
"quote_error.poll": "Anketlerde alıntıya izin verilmez.",
"quote_error.quote": "Bir seferde tek bir alıntıya izin var.",
"quote_error.unauthorized": "Bu gönderiyi alıntılamaya yetkiniz yok.",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index 87fe47d777..052dfdcfd0 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "悄悄公开",
"privacy_policy.last_updated": "最近更新于 {date}",
"privacy_policy.title": "隐私政策",
+ "quote_error.edit": "编辑嘟文时无法添加引用。",
"quote_error.poll": "不允许引用投票嘟文。",
"quote_error.quote": "一次只能引用一条嘟文。",
"quote_error.unauthorized": "你没有权限引用此嘟文。",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index 20f94573d7..81cb45fd3b 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -753,6 +753,7 @@
"privacy.unlisted.short": "不公開",
"privacy_policy.last_updated": "最後更新:{date}",
"privacy_policy.title": "隱私權政策",
+ "quote_error.edit": "編輯嘟文時無法新增引用嘟文。",
"quote_error.poll": "無法引用投票嘟文。",
"quote_error.quote": "一次僅能引用一則嘟文。",
"quote_error.unauthorized": "您不被授權允許引用此嘟文。",
diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss
index 0a8cb5ce0d..08bb98cfa6 100644
--- a/app/javascript/styles/mastodon/admin.scss
+++ b/app/javascript/styles/mastodon/admin.scss
@@ -712,7 +712,7 @@ body,
}
&__title {
- word-wrap: break-word;
+ overflow-wrap: break-word;
}
&__timestamp {
@@ -763,7 +763,7 @@ body,
}
&__title {
- word-wrap: break-word;
+ overflow-wrap: break-word;
}
&__timestamp {
@@ -1413,7 +1413,7 @@ a.sparkline {
.report-header {
display: grid;
- grid-gap: 15px;
+ gap: 15px;
grid-template-columns: minmax(0, 1fr) 300px;
&__details {
@@ -1523,7 +1523,7 @@ a.sparkline {
margin: 8px 0;
overflow: hidden;
text-overflow: ellipsis;
- word-wrap: break-word;
+ overflow-wrap: break-word;
max-height: 21px * 2;
position: relative;
font-size: 15px;
@@ -1680,7 +1680,7 @@ a.sparkline {
&__content {
font-size: 15px;
line-height: 20px;
- word-wrap: break-word;
+ overflow-wrap: break-word;
font-weight: 400;
color: $primary-text-color;
@@ -1782,7 +1782,7 @@ a.sparkline {
padding: 15px;
font-size: 15px;
line-height: 20px;
- word-wrap: break-word;
+ overflow-wrap: break-word;
font-weight: 400;
color: $primary-text-color;
box-sizing: border-box;
@@ -1964,7 +1964,7 @@ a.sparkline {
border-radius: 4px;
font-size: 15px;
line-height: 20px;
- word-wrap: break-word;
+ overflow-wrap: break-word;
font-weight: 400;
border: 1px solid lighten($ui-base-color, 4%);
color: $primary-text-color;
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index ee54cd71ad..65ed88dca9 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -1122,7 +1122,7 @@
.edit-indicator__content,
.reply-indicator__content {
position: relative;
- word-wrap: break-word;
+ overflow-wrap: break-word;
font-weight: 400;
overflow: hidden;
text-overflow: ellipsis;
@@ -1363,7 +1363,7 @@
}
.announcements__item__content {
- word-wrap: break-word;
+ overflow-wrap: break-word;
overflow-y: auto;
.emojione {
@@ -3968,7 +3968,7 @@ a.account__display-name {
.react-toggle-screenreader-only,
.sr-only {
border: 0;
- clip: rect(0 0 0 0);
+ clip-path: inset(50%);
height: 1px;
margin: -1px;
overflow: hidden;
@@ -5177,10 +5177,8 @@ a.status-card {
&__menu {
@include search-popout;
- & {
- padding: 0;
- background: $ui-secondary-color;
- }
+ padding: 0;
+ background: $ui-secondary-color;
}
&__menu-list {
@@ -8322,7 +8320,7 @@ noscript {
font-weight: 400;
overflow: hidden;
word-break: normal;
- word-wrap: break-word;
+ overflow-wrap: break-word;
p {
margin-bottom: 20px;
@@ -8966,7 +8964,7 @@ noscript {
position: relative;
font-size: 15px;
line-height: 20px;
- word-wrap: break-word;
+ overflow-wrap: break-word;
font-weight: 400;
max-height: 50vh;
overflow: hidden;
diff --git a/app/javascript/styles/mastodon/dashboard.scss b/app/javascript/styles/mastodon/dashboard.scss
index c99cdc357a..8326022f71 100644
--- a/app/javascript/styles/mastodon/dashboard.scss
+++ b/app/javascript/styles/mastodon/dashboard.scss
@@ -61,7 +61,7 @@
.dashboard {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr);
- grid-gap: 10px;
+ gap: 10px;
@media screen and (width <= 1350px) {
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
diff --git a/app/javascript/styles/mastodon/emoji_picker.scss b/app/javascript/styles/mastodon/emoji_picker.scss
index 1fde5de1dc..d443b74fe3 100644
--- a/app/javascript/styles/mastodon/emoji_picker.scss
+++ b/app/javascript/styles/mastodon/emoji_picker.scss
@@ -190,7 +190,7 @@
padding: 0;
margin: -1px;
overflow: hidden;
- clip: rect(0, 0, 0, 0);
+ clip-path: inset(50%);
border: 0;
}
diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss
index b3708b722e..650081d1eb 100644
--- a/app/javascript/styles/mastodon/forms.scss
+++ b/app/javascript/styles/mastodon/forms.scss
@@ -299,7 +299,7 @@ code {
color: $primary-text-color;
display: block;
margin-bottom: 8px;
- word-wrap: break-word;
+ overflow-wrap: break-word;
font-weight: 500;
}
diff --git a/app/javascript/styles/mastodon/polls.scss b/app/javascript/styles/mastodon/polls.scss
index b13c9d6132..e8f2f5c394 100644
--- a/app/javascript/styles/mastodon/polls.scss
+++ b/app/javascript/styles/mastodon/polls.scss
@@ -60,7 +60,6 @@
&__text {
display: inline-block;
- word-wrap: break-word;
overflow-wrap: break-word;
max-width: calc(100% - 45px - 25px);
}
diff --git a/app/models/account.rb b/app/models/account.rb
index 76c7c3bd24..eb0faa9e64 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -52,7 +52,7 @@
# requested_review_at :datetime
# indexable :boolean default(FALSE), not null
# attribution_domains :string default([]), is an Array
-# id_scheme :integer default("username_ap_id")
+# id_scheme :integer default("numeric_ap_id")
#
class Account < ApplicationRecord
@@ -442,7 +442,6 @@ class Account < ApplicationRecord
before_validation :prepare_contents, if: :local?
before_create :generate_keys
- before_create :set_id_scheme
before_destroy :clean_feed_manager
def ensure_keys!
@@ -467,12 +466,6 @@ class Account < ApplicationRecord
self.public_key = keypair.public_key.to_pem
end
- def set_id_scheme
- return unless local? && Mastodon::Feature.numeric_ap_ids_enabled?
-
- self.id_scheme = :numeric_ap_id
- end
-
def normalize_domain
return if local?
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index 8b21cfb2eb..926151f095 100644
--- a/config/locales/cs.yml
+++ b/config/locales/cs.yml
@@ -1669,6 +1669,13 @@ cs:
expires_at: Vyprší
uses: Použití
title: Pozvat lidi
+ link_preview:
+ author_html: Podle %{name}
+ potentially_sensitive_content:
+ action: Kliknutím zobrazíte
+ confirm_visit: Opravdu chcete otevřít tento odkaz?
+ hide_button: Skrýt
+ label: Potenciálně citlivý obsah
lists:
errors:
limit: Dosáhl jste maximálního počtu seznamů
@@ -1985,6 +1992,9 @@ cs:
other: "%{count} videí"
boosted_from_html: Boostnuto z %{acct_link}
content_warning: 'Varování o obsahu: %{warning}'
+ content_warnings:
+ hide: Skrýt příspěvek
+ show: Zobrazit více
default_language: Stejný jako jazyk rozhraní
disallowed_hashtags:
few: 'obsahoval zakázané hashtagy: %{tags}'
diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml
index 65095cd788..29cc473e01 100644
--- a/config/locales/devise.en.yml
+++ b/config/locales/devise.en.yml
@@ -7,6 +7,7 @@ en:
send_paranoid_instructions: If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes. Please check your spam folder if you didn't receive this email.
failure:
already_authenticated: You are already signed in.
+ closed_registrations: Your registration attempt has been blocked due to a network policy. If you believe this is an error, contact %{email}.
inactive: Your account is not activated yet.
invalid: Invalid %{authentication_keys} or password.
last_attempt: You have one more attempt before your account is locked.
diff --git a/config/locales/hu.yml b/config/locales/hu.yml
index 2b57ef5516..e85f476e4d 100644
--- a/config/locales/hu.yml
+++ b/config/locales/hu.yml
@@ -1591,6 +1591,13 @@ hu:
expires_at: Lejárat
uses: Használat
title: Meghívások
+ link_preview:
+ author_html: 'Szerző: %{name}'
+ potentially_sensitive_content:
+ action: Kattints a megjelenítéshez
+ confirm_visit: Biztos, hogy megnyitod ezt a hivatkozást?
+ hide_button: Elrejtés
+ label: Lehet, hogy kényes tartalom
lists:
errors:
limit: Elérted a listák maximális számát
@@ -1901,6 +1908,9 @@ hu:
other: "%{count} videó"
boosted_from_html: Megtolva innen %{acct_link}
content_warning: 'Tartalmi figyelmeztetés: %{warning}'
+ content_warnings:
+ hide: Bejegyzés elrejtése
+ show: Több megjelenítése
default_language: Felhasználói felület nyelvével azonos
disallowed_hashtags:
one: 'tiltott hashtaget tartalmaz: %{tags}'
diff --git a/config/locales/tr.yml b/config/locales/tr.yml
index f07a66d327..6b53a1d191 100644
--- a/config/locales/tr.yml
+++ b/config/locales/tr.yml
@@ -1591,6 +1591,13 @@ tr:
expires_at: Bitiş tarihi
uses: Kullanım
title: İnsanları davet et
+ link_preview:
+ author_html: 'Yazan: %{name}'
+ potentially_sensitive_content:
+ action: Göstermek için tıklayın
+ confirm_visit: Bu bağlantıyı açmak istediğinizden emin misiniz?
+ hide_button: Gizle
+ label: Potansiyel olarak hassas içerik
lists:
errors:
limit: Azami liste sayısına ulaştınız
diff --git a/db/migrate/20251007142305_change_defaults_for_account_id_scheme.rb b/db/migrate/20251007142305_change_defaults_for_account_id_scheme.rb
new file mode 100644
index 0000000000..6c07236968
--- /dev/null
+++ b/db/migrate/20251007142305_change_defaults_for_account_id_scheme.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class ChangeDefaultsForAccountIdScheme < ActiveRecord::Migration[8.0]
+ def change
+ change_column_default :accounts, :id_scheme, from: 0, to: 1
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index c642fca11d..73f1607eb2 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[8.0].define(version: 2025_10_07_100813) do
+ActiveRecord::Schema[8.0].define(version: 2025_10_07_142305) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql"
@@ -199,7 +199,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_10_07_100813) do
t.boolean "indexable", default: false, null: false
t.string "attribution_domains", default: [], array: true
t.string "following_url", default: "", null: false
- t.integer "id_scheme", default: 0
+ t.integer "id_scheme", default: 1
t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin
t.index "lower((username)::text), COALESCE(lower((domain)::text), ''::text)", name: "index_accounts_on_username_and_domain_lower", unique: true
t.index ["domain", "id"], name: "index_accounts_on_domain_and_id"
diff --git a/docker-compose.yml b/docker-compose.yml
index 83ff4336d0..7205d5a27e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -59,7 +59,7 @@ services:
web:
# You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes
# build: .
- image: ghcr.io/glitch-soc/mastodon:v4.4.6
+ image: ghcr.io/glitch-soc/mastodon:v4.4.7
restart: always
env_file: .env.production
command: bundle exec puma -C config/puma.rb
@@ -83,7 +83,7 @@ services:
# build:
# dockerfile: ./streaming/Dockerfile
# context: .
- image: ghcr.io/glitch-soc/mastodon-streaming:v4.4.6
+ image: ghcr.io/glitch-soc/mastodon-streaming:v4.4.7
restart: always
env_file: .env.production
command: node ./streaming/index.js
@@ -102,7 +102,7 @@ services:
sidekiq:
# You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes
# build: .
- image: ghcr.io/glitch-soc/mastodon:v4.4.6
+ image: ghcr.io/glitch-soc/mastodon:v4.4.7
restart: always
env_file: .env.production
command: bundle exec sidekiq
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index 7fca8e8c82..b8f6436fde 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -17,7 +17,7 @@ module Mastodon
end
def default_prerelease
- 'alpha.3'
+ 'beta.1'
end
def prerelease
diff --git a/package.json b/package.json
index 2a722de54d..49bfee461b 100644
--- a/package.json
+++ b/package.json
@@ -191,7 +191,7 @@
"storybook": "^9.1.1",
"stylelint": "^16.19.1",
"stylelint-config-prettier-scss": "^1.0.0",
- "stylelint-config-standard-scss": "^15.0.1",
+ "stylelint-config-standard-scss": "^16.0.0",
"typescript": "~5.9.0",
"typescript-eslint": "^8.45.0",
"vitest": "^3.2.4"
diff --git a/spec/controllers/auth/registrations_controller_spec.rb b/spec/controllers/auth/registrations_controller_spec.rb
index 04c2d5dbbb..c7bbe13092 100644
--- a/spec/controllers/auth/registrations_controller_spec.rb
+++ b/spec/controllers/auth/registrations_controller_spec.rb
@@ -12,11 +12,11 @@ RSpec.describe Auth::RegistrationsController do
allow(Rails.configuration.x).to receive(:single_user_mode).and_return(true)
end
- it 'redirects to root' do
+ it 'redirects to sign-in' do
Fabricate(:account)
get path
- expect(response).to redirect_to '/'
+ expect(response).to redirect_to '/auth/sign_in'
expect(Rails.configuration.x).to have_received(:single_user_mode)
end
end
@@ -27,10 +27,10 @@ RSpec.describe Auth::RegistrationsController do
allow(Rails.configuration.x).to receive(:single_user_mode).and_return(false)
end
- it 'redirects to root' do
+ it 'redirects to sign-in' do
get path
- expect(response).to redirect_to '/'
+ expect(response).to redirect_to '/auth/sign_in'
expect(Rails.configuration.x).to have_received(:single_user_mode)
end
end
diff --git a/spec/controllers/concerns/account_controller_concern_spec.rb b/spec/controllers/concerns/account_controller_concern_spec.rb
index df6278a6e9..b5c8c16643 100644
--- a/spec/controllers/concerns/account_controller_concern_spec.rb
+++ b/spec/controllers/concerns/account_controller_concern_spec.rb
@@ -58,7 +58,7 @@ RSpec.describe AccountControllerConcern do
expect(response)
.to have_http_status(200)
.and have_http_link_header(webfinger_url(resource: account.to_webfinger_s)).for(rel: 'lrdd', type: 'application/jrd+json')
- .and have_http_link_header(account_url(account, protocol: :https)).for(rel: 'alternate', type: 'application/activity+json')
+ .and have_http_link_header(ActivityPub::TagManager.instance.uri_for(account)).for(rel: 'alternate', type: 'application/activity+json')
expect(response.body)
.to include(account.username)
end
diff --git a/spec/controllers/follower_accounts_controller_spec.rb b/spec/controllers/follower_accounts_controller_spec.rb
index e14ed00e60..dab6aadbaa 100644
--- a/spec/controllers/follower_accounts_controller_spec.rb
+++ b/spec/controllers/follower_accounts_controller_spec.rb
@@ -49,8 +49,8 @@ RSpec.describe FollowerAccountsController do
expect(response.parsed_body)
.to include(
orderedItems: contain_exactly(
- include(follow_from_bob.account.username),
- include(follow_from_chris.account.username)
+ ActivityPub::TagManager.instance.uri_for(follow_from_bob.account),
+ ActivityPub::TagManager.instance.uri_for(follow_from_chris.account)
),
totalItems: eq(2),
partOf: be_present
diff --git a/spec/controllers/following_accounts_controller_spec.rb b/spec/controllers/following_accounts_controller_spec.rb
index fea4d4845c..666c655d74 100644
--- a/spec/controllers/following_accounts_controller_spec.rb
+++ b/spec/controllers/following_accounts_controller_spec.rb
@@ -49,8 +49,8 @@ RSpec.describe FollowingAccountsController do
expect(response.parsed_body)
.to include(
orderedItems: contain_exactly(
- include(follow_of_bob.target_account.username),
- include(follow_of_chris.target_account.username)
+ ActivityPub::TagManager.instance.uri_for(follow_of_bob.target_account),
+ ActivityPub::TagManager.instance.uri_for(follow_of_chris.target_account)
),
totalItems: eq(2),
partOf: be_present
diff --git a/spec/lib/activitypub/tag_manager_spec.rb b/spec/lib/activitypub/tag_manager_spec.rb
index 70e084a9c9..cad46ad903 100644
--- a/spec/lib/activitypub/tag_manager_spec.rb
+++ b/spec/lib/activitypub/tag_manager_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe ActivityPub::TagManager do
describe '#url_for' do
context 'with a local account' do
- let(:account) { Fabricate(:account) }
+ let(:account) { Fabricate(:account, id_scheme: :username_ap_id) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.url_for(account))
@@ -49,7 +49,8 @@ RSpec.describe ActivityPub::TagManager do
end
context 'with a local status' do
- let(:status) { Fabricate(:status) }
+ let(:account) { Fabricate(:account, id_scheme: :username_ap_id) }
+ let(:status) { Fabricate(:status, account: account) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.url_for(status))
@@ -58,7 +59,6 @@ RSpec.describe ActivityPub::TagManager do
context 'when using a numeric ID based scheme' do
let(:account) { Fabricate(:account, id_scheme: :numeric_ap_id) }
- let(:status) { Fabricate(:status, account: account) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.url_for(status))
@@ -86,7 +86,7 @@ RSpec.describe ActivityPub::TagManager do
end
context 'with a local account' do
- let(:account) { Fabricate(:account) }
+ let(:account) { Fabricate(:account, id_scheme: :username_ap_id) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.uri_for(account))
@@ -112,7 +112,8 @@ RSpec.describe ActivityPub::TagManager do
end
context 'with a local status' do
- let(:status) { Fabricate(:status) }
+ let(:account) { Fabricate(:account, id_scheme: :username_ap_id) }
+ let(:status) { Fabricate(:status, account: account) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.uri_for(status))
@@ -121,7 +122,6 @@ RSpec.describe ActivityPub::TagManager do
context 'when using a numeric ID based scheme' do
let(:account) { Fabricate(:account, id_scheme: :numeric_ap_id) }
- let(:status) { Fabricate(:status, account: account) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.uri_for(status))
@@ -140,7 +140,8 @@ RSpec.describe ActivityPub::TagManager do
end
context 'with a local conversation' do
- let(:status) { Fabricate(:status) }
+ let(:account) { Fabricate(:account, id_scheme: :username_ap_id) }
+ let(:status) { Fabricate(:status, account: account) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.uri_for(status.conversation))
@@ -149,7 +150,6 @@ RSpec.describe ActivityPub::TagManager do
context 'when using a numeric ID based scheme' do
let(:account) { Fabricate(:account, id_scheme: :numeric_ap_id) }
- let(:status) { Fabricate(:status, account: account) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.uri_for(status.conversation))
@@ -181,7 +181,7 @@ RSpec.describe ActivityPub::TagManager do
end
context 'with a local account' do
- let(:account) { Fabricate(:account) }
+ let(:account) { Fabricate(:account, id_scheme: :username_ap_id) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.key_uri_for(account))
@@ -218,7 +218,9 @@ RSpec.describe ActivityPub::TagManager do
describe '#approval_uri_for' do
context 'with a valid local approval' do
- let(:quote) { Fabricate(:quote, state: :accepted) }
+ let(:quoted_account) { Fabricate(:account, id_scheme: :username_ap_id) }
+ let(:quoted_status) { Fabricate(:status, account: quoted_account) }
+ let(:quote) { Fabricate(:quote, state: :accepted, quoted_status: quoted_status) }
it 'returns a string with the web domain and expected path' do
expect(subject.approval_uri_for(quote))
@@ -227,8 +229,6 @@ RSpec.describe ActivityPub::TagManager do
context 'when using a numeric ID based scheme' do
let(:quoted_account) { Fabricate(:account, id_scheme: :numeric_ap_id) }
- let(:quoted_status) { Fabricate(:status, account: quoted_account) }
- let(:quote) { Fabricate(:quote, state: :accepted, quoted_status: quoted_status) }
it 'returns a string with the web domain and expected path' do
expect(subject.approval_uri_for(quote))
@@ -238,7 +238,9 @@ RSpec.describe ActivityPub::TagManager do
end
context 'with an unapproved local quote' do
- let(:quote) { Fabricate(:quote, state: :rejected) }
+ let(:quoted_account) { Fabricate(:account, id_scheme: :username_ap_id) }
+ let(:quoted_status) { Fabricate(:status, account: quoted_account) }
+ let(:quote) { Fabricate(:quote, state: :rejected, quoted_status: quoted_status) }
it 'returns nil' do
expect(subject.approval_uri_for(quote))
@@ -247,8 +249,6 @@ RSpec.describe ActivityPub::TagManager do
context 'when using a numeric ID based scheme' do
let(:quoted_account) { Fabricate(:account, id_scheme: :numeric_ap_id) }
- let(:quoted_status) { Fabricate(:status, account: quoted_account) }
- let(:quote) { Fabricate(:quote, state: :rejected, quoted_status: quoted_status) }
it 'returns nil' do
expect(subject.approval_uri_for(quote))
@@ -260,7 +260,7 @@ RSpec.describe ActivityPub::TagManager do
context 'with a valid remote approval' do
let(:quoted_account) { Fabricate(:account, domain: 'example.com') }
let(:quoted_status) { Fabricate(:status, account: quoted_account) }
- let(:quote) { Fabricate(:quote, state: :accepted, quoted_status: quoted_status, approval_uri: 'https://example.com/approvals/1') }
+ let(:quote) { Fabricate(:quote, status: Fabricate(:status), state: :accepted, quoted_status: quoted_status, approval_uri: 'https://example.com/approvals/1') }
it 'returns the expected URI' do
expect(subject.approval_uri_for(quote)).to eq quote.approval_uri
@@ -268,7 +268,9 @@ RSpec.describe ActivityPub::TagManager do
end
context 'with an unapproved local quote but check_approval override' do
- let(:quote) { Fabricate(:quote, state: :rejected) }
+ let(:quoted_account) { Fabricate(:account, id_scheme: :username_ap_id) }
+ let(:quoted_status) { Fabricate(:status, account: quoted_account) }
+ let(:quote) { Fabricate(:quote, state: :rejected, quoted_status: quoted_status) }
it 'returns a string with the web domain and expected path' do
expect(subject.approval_uri_for(quote, check_approval: false))
@@ -277,8 +279,6 @@ RSpec.describe ActivityPub::TagManager do
context 'when using a numeric ID based scheme' do
let(:quoted_account) { Fabricate(:account, id_scheme: :numeric_ap_id) }
- let(:quoted_status) { Fabricate(:status, account: quoted_account) }
- let(:quote) { Fabricate(:quote, state: :rejected, quoted_status: quoted_status) }
it 'returns a string with the web domain and expected path' do
expect(subject.approval_uri_for(quote, check_approval: false))
@@ -290,7 +290,8 @@ RSpec.describe ActivityPub::TagManager do
describe '#replies_uri_for' do
context 'with a local status' do
- let(:status) { Fabricate(:status) }
+ let(:account) { Fabricate(:account, id_scheme: :username_ap_id) }
+ let(:status) { Fabricate(:status, account: account) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.replies_uri_for(status))
@@ -299,7 +300,6 @@ RSpec.describe ActivityPub::TagManager do
context 'when using a numeric ID based scheme' do
let(:account) { Fabricate(:account, id_scheme: :numeric_ap_id) }
- let(:status) { Fabricate(:status, account: account) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.replies_uri_for(status))
@@ -311,7 +311,8 @@ RSpec.describe ActivityPub::TagManager do
describe '#likes_uri_for' do
context 'with a local status' do
- let(:status) { Fabricate(:status) }
+ let(:account) { Fabricate(:account, id_scheme: :username_ap_id) }
+ let(:status) { Fabricate(:status, account: account) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.likes_uri_for(status))
@@ -320,7 +321,6 @@ RSpec.describe ActivityPub::TagManager do
context 'when using a numeric ID based scheme' do
let(:account) { Fabricate(:account, id_scheme: :numeric_ap_id) }
- let(:status) { Fabricate(:status, account: account) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.likes_uri_for(status))
@@ -332,7 +332,8 @@ RSpec.describe ActivityPub::TagManager do
describe '#shares_uri_for' do
context 'with a local status' do
- let(:status) { Fabricate(:status) }
+ let(:account) { Fabricate(:account, id_scheme: :username_ap_id) }
+ let(:status) { Fabricate(:status, account: account) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.shares_uri_for(status))
@@ -341,7 +342,6 @@ RSpec.describe ActivityPub::TagManager do
context 'when using a numeric ID based scheme' do
let(:account) { Fabricate(:account, id_scheme: :numeric_ap_id) }
- let(:status) { Fabricate(:status, account: account) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.shares_uri_for(status))
@@ -353,7 +353,7 @@ RSpec.describe ActivityPub::TagManager do
describe '#following_uri_for' do
context 'with a local account' do
- let(:account) { Fabricate(:account) }
+ let(:account) { Fabricate(:account, id_scheme: :username_ap_id) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.following_uri_for(account))
@@ -373,7 +373,7 @@ RSpec.describe ActivityPub::TagManager do
describe '#followers_uri_for' do
context 'with a local account' do
- let(:account) { Fabricate(:account) }
+ let(:account) { Fabricate(:account, id_scheme: :username_ap_id) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.followers_uri_for(account))
@@ -400,7 +400,7 @@ RSpec.describe ActivityPub::TagManager do
end
context 'with a local account' do
- let(:account) { Fabricate(:account) }
+ let(:account) { Fabricate(:account, id_scheme: :username_ap_id) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.inbox_uri_for(account))
@@ -427,7 +427,7 @@ RSpec.describe ActivityPub::TagManager do
end
context 'with a local account' do
- let(:account) { Fabricate(:account) }
+ let(:account) { Fabricate(:account, id_scheme: :username_ap_id) }
it 'returns a string starting with web domain and with the expected path' do
expect(subject.outbox_uri_for(account))
@@ -452,7 +452,7 @@ RSpec.describe ActivityPub::TagManager do
end
it 'returns followers collection for unlisted status' do
- status = Fabricate(:status, visibility: :unlisted)
+ status = Fabricate(:status, visibility: :unlisted, account: Fabricate(:account, id_scheme: :username_ap_id))
expect(subject.to(status)).to eq [account_followers_url(status.account)]
end
@@ -462,7 +462,7 @@ RSpec.describe ActivityPub::TagManager do
end
it 'returns followers collection for private status' do
- status = Fabricate(:status, visibility: :private)
+ status = Fabricate(:status, visibility: :private, account: Fabricate(:account, id_scheme: :username_ap_id))
expect(subject.to(status)).to eq [account_followers_url(status.account)]
end
@@ -514,7 +514,7 @@ RSpec.describe ActivityPub::TagManager do
describe '#cc' do
it 'returns followers collection for public status' do
- status = Fabricate(:status, visibility: :public)
+ status = Fabricate(:status, visibility: :public, account: Fabricate(:account, id_scheme: :username_ap_id))
expect(subject.cc(status)).to eq [account_followers_url(status.account)]
end
@@ -591,8 +591,9 @@ RSpec.describe ActivityPub::TagManager do
end
describe '#uri_to_local_id' do
+ let(:account) { Fabricate(:account, id_scheme: :username_ap_id) }
+
it 'returns the local ID' do
- account = Fabricate(:account)
expect(subject.uri_to_local_id(subject.uri_for(account), :username)).to eq account.username
end
end
diff --git a/spec/models/remote_follow_spec.rb b/spec/models/remote_follow_spec.rb
index b3ec7b737e..aad3282562 100644
--- a/spec/models/remote_follow_spec.rb
+++ b/spec/models/remote_follow_spec.rb
@@ -68,7 +68,7 @@ RSpec.describe RemoteFollow do
Addressable::URI.new(
host: 'quitter.no',
path: '/main/ostatussub',
- query_values: { profile: "https://#{Rails.configuration.x.local_domain}/users/alice" },
+ query_values: { profile: ActivityPub::TagManager.instance.uri_for(account) },
scheme: 'https'
).to_s
end
diff --git a/spec/requests/activitypub/outboxes_spec.rb b/spec/requests/activitypub/outboxes_spec.rb
index 22b2f97c07..c109214635 100644
--- a/spec/requests/activitypub/outboxes_spec.rb
+++ b/spec/requests/activitypub/outboxes_spec.rb
@@ -215,7 +215,7 @@ RSpec.describe 'ActivityPub Outboxes' do
def targets_followers_collection?(item, account)
item[:to].include?(
- account_followers_url(account, ActionMailer::Base.default_url_options)
+ ActivityPub::TagManager.instance.followers_uri_for(account)
)
end
end
diff --git a/spec/requests/link_headers_spec.rb b/spec/requests/link_headers_spec.rb
index 5010f7f221..c782744f01 100644
--- a/spec/requests/link_headers_spec.rb
+++ b/spec/requests/link_headers_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'Link headers' do
expect(response)
.to have_http_link_header(webfinger_url(resource: account.to_webfinger_s)).for(rel: 'lrdd', type: 'application/jrd+json')
- .and have_http_link_header(account_url(account)).for(rel: 'alternate', type: 'application/activity+json')
+ .and have_http_link_header(ActivityPub::TagManager.instance.uri_for(account)).for(rel: 'alternate', type: 'application/activity+json')
end
end
end
diff --git a/spec/requests/oauth/userinfo_spec.rb b/spec/requests/oauth/userinfo_spec.rb
index 0aa5a21120..280a3a3541 100644
--- a/spec/requests/oauth/userinfo_spec.rb
+++ b/spec/requests/oauth/userinfo_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe 'OAuth Userinfo Endpoint' do
expect(response.content_type).to start_with('application/json')
expect(response.parsed_body).to include({
iss: root_url,
- sub: account_url(account),
+ sub: ActivityPub::TagManager.instance.uri_for(account),
name: account.display_name,
preferred_username: account.username,
profile: short_account_url(account),
diff --git a/spec/requests/well_known/webfinger_spec.rb b/spec/requests/well_known/webfinger_spec.rb
index 0c4a3c0347..593cecbb89 100644
--- a/spec/requests/well_known/webfinger_spec.rb
+++ b/spec/requests/well_known/webfinger_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe 'The /.well-known/webfinger endpoint' do
expect(response.parsed_body)
.to include(
subject: eq(alice.to_webfinger_s),
- aliases: include("https://#{Rails.configuration.x.local_domain}/@alice", "https://#{Rails.configuration.x.local_domain}/users/alice")
+ aliases: include("https://#{Rails.configuration.x.local_domain}/@alice", ActivityPub::TagManager.instance.uri_for(alice))
)
end
end
diff --git a/yarn.lock b/yarn.lock
index 280631da11..35104f263d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2397,15 +2397,15 @@ __metadata:
languageName: node
linkType: hard
-"@formatjs/ecma402-abstract@npm:2.3.5":
- version: 2.3.5
- resolution: "@formatjs/ecma402-abstract@npm:2.3.5"
+"@formatjs/ecma402-abstract@npm:2.3.6":
+ version: 2.3.6
+ resolution: "@formatjs/ecma402-abstract@npm:2.3.6"
dependencies:
"@formatjs/fast-memoize": "npm:2.2.7"
"@formatjs/intl-localematcher": "npm:0.6.2"
decimal.js: "npm:^10.4.3"
tslib: "npm:^2.8.0"
- checksum: 10c0/c6cac6312a1228347adf3a6a5fd09c0593e7d199e7a56484ece7cb8121c4138ba5c2777b70f82e88d8fbe3199ef5f48b2b1444f0348ee315b930e9db33c67d84
+ checksum: 10c0/63be2a73d3168bf45ab5d50db58376e852db5652d89511ae6e44f1fa03ad96ebbfe9b06a1dfaa743db06e40eb7f33bd77530b9388289855cca79a0e3fc29eacf
languageName: node
linkType: hard
@@ -2429,14 +2429,14 @@ __metadata:
languageName: node
linkType: hard
-"@formatjs/icu-messageformat-parser@npm:2.11.3":
- version: 2.11.3
- resolution: "@formatjs/icu-messageformat-parser@npm:2.11.3"
+"@formatjs/icu-messageformat-parser@npm:2.11.4":
+ version: 2.11.4
+ resolution: "@formatjs/icu-messageformat-parser@npm:2.11.4"
dependencies:
- "@formatjs/ecma402-abstract": "npm:2.3.5"
- "@formatjs/icu-skeleton-parser": "npm:1.8.15"
+ "@formatjs/ecma402-abstract": "npm:2.3.6"
+ "@formatjs/icu-skeleton-parser": "npm:1.8.16"
tslib: "npm:^2.8.0"
- checksum: 10c0/dfa08a671318bc9425f9b8e77ba0fb11856c9e1bb366b2a9c820212711d3483d9337fba50ef0a65c259c5564a6306355b065d739feae56e03b3046edba739460
+ checksum: 10c0/3ea9e9dae18282881d19a5f88107b6013f514ec8675684ed2c04bee2a174032377858937243e3bd9c9263a470988a3773a53bf8d208a34a78e7843ce66f87f3b
languageName: node
linkType: hard
@@ -2450,13 +2450,13 @@ __metadata:
languageName: node
linkType: hard
-"@formatjs/icu-skeleton-parser@npm:1.8.15":
- version: 1.8.15
- resolution: "@formatjs/icu-skeleton-parser@npm:1.8.15"
+"@formatjs/icu-skeleton-parser@npm:1.8.16":
+ version: 1.8.16
+ resolution: "@formatjs/icu-skeleton-parser@npm:1.8.16"
dependencies:
- "@formatjs/ecma402-abstract": "npm:2.3.5"
+ "@formatjs/ecma402-abstract": "npm:2.3.6"
tslib: "npm:^2.8.0"
- checksum: 10c0/e33478f3cdb6d49f8531f35fb80db98d49533add42cd4ab8d3f3cef72c3496ae3042dfe24f252e6afffd3e4f6c9f1dec88367973c14e779dc07947c75641cede
+ checksum: 10c0/6fa1586dc11c925cd8d17e927cc635d238c969a6b7e97282a924376f78622fc25336c407589d19796fb6f8124a0e7765f99ecdb1aac014edcfbe852e7c3d87f3
languageName: node
linkType: hard
@@ -2479,32 +2479,32 @@ __metadata:
linkType: hard
"@formatjs/intl-pluralrules@npm:^5.4.4":
- version: 5.4.5
- resolution: "@formatjs/intl-pluralrules@npm:5.4.5"
+ version: 5.4.6
+ resolution: "@formatjs/intl-pluralrules@npm:5.4.6"
dependencies:
- "@formatjs/ecma402-abstract": "npm:2.3.5"
+ "@formatjs/ecma402-abstract": "npm:2.3.6"
"@formatjs/intl-localematcher": "npm:0.6.2"
decimal.js: "npm:^10.4.3"
tslib: "npm:^2.8.0"
- checksum: 10c0/2405fd2a4c8ce7a5c25ae824daa1408b07664a4f5ca573683fedad78a487a118b50391b0a2234db921c615e1ed4f53e860a55cd9892708ae49f5766980495b6e
+ checksum: 10c0/95dd6fb3e9bd84ce44cc194f6f815d690703bd60b75bf2ae895535d2d9a1a675765879de9b54f854882fc1335cbfac6a535873d5b2d75cc5ca93c6ca172aa272
languageName: node
linkType: hard
-"@formatjs/intl@npm:3.1.7":
- version: 3.1.7
- resolution: "@formatjs/intl@npm:3.1.7"
+"@formatjs/intl@npm:3.1.8":
+ version: 3.1.8
+ resolution: "@formatjs/intl@npm:3.1.8"
dependencies:
- "@formatjs/ecma402-abstract": "npm:2.3.5"
+ "@formatjs/ecma402-abstract": "npm:2.3.6"
"@formatjs/fast-memoize": "npm:2.2.7"
- "@formatjs/icu-messageformat-parser": "npm:2.11.3"
- intl-messageformat: "npm:10.7.17"
+ "@formatjs/icu-messageformat-parser": "npm:2.11.4"
+ intl-messageformat: "npm:10.7.18"
tslib: "npm:^2.8.0"
peerDependencies:
- typescript: 5.8.3
+ typescript: ^5.6.0
peerDependenciesMeta:
typescript:
optional: true
- checksum: 10c0/52d800f587ed11407879f44b971a498844f116d966f9348ef1b597b7a4ee91f8023e0270797961be8126989512859f5944c4115e39675f4959a22b7837b62e77
+ checksum: 10c0/b291e867bcde491737f70254ec30898e120f36784b5ee2911dcc271fbd744e90382f03232ac7f5a55d46071f4ffccfc84b63445734117b75ca1ced659f6b7827
languageName: node
linkType: hard
@@ -2528,22 +2528,22 @@ __metadata:
languageName: node
linkType: hard
-"@formatjs/ts-transformer@npm:3.14.1":
- version: 3.14.1
- resolution: "@formatjs/ts-transformer@npm:3.14.1"
+"@formatjs/ts-transformer@npm:3.14.2":
+ version: 3.14.2
+ resolution: "@formatjs/ts-transformer@npm:3.14.2"
dependencies:
- "@formatjs/icu-messageformat-parser": "npm:2.11.3"
+ "@formatjs/icu-messageformat-parser": "npm:2.11.4"
"@types/node": "npm:^22.0.0"
chalk: "npm:^4.1.2"
json-stable-stringify: "npm:^1.3.0"
tslib: "npm:^2.8.0"
- typescript: "npm:5.8.3"
+ typescript: "npm:^5.6.0"
peerDependencies:
ts-jest: ^29
peerDependenciesMeta:
ts-jest:
optional: true
- checksum: 10c0/ed412d70fb0b8a57b74f1453e2605481295fda71ba462f4c65fab3d1a7f5a0c51c70fa78b9e9e2b291917eb63bbc5cffc7df27f04645832ae64e881e1327a11c
+ checksum: 10c0/990cf49cdc318e37825ec26b1b24d7368e89c5d03184867a4accd8b35d6d6d99a20a8abe6366c9870e56da9e04f4672990ca428686306c9ad8204b401c7d19f8
languageName: node
linkType: hard
@@ -2917,7 +2917,7 @@ __metadata:
stringz: "npm:^2.1.0"
stylelint: "npm:^16.19.1"
stylelint-config-prettier-scss: "npm:^1.0.0"
- stylelint-config-standard-scss: "npm:^15.0.1"
+ stylelint-config-standard-scss: "npm:^16.0.0"
substring-trie: "npm:^1.0.2"
tesseract.js: "npm:^6.0.0"
tiny-queue: "npm:^0.2.1"
@@ -5476,21 +5476,21 @@ __metadata:
linkType: hard
"babel-plugin-formatjs@npm:^10.5.37":
- version: 10.5.40
- resolution: "babel-plugin-formatjs@npm:10.5.40"
+ version: 10.5.41
+ resolution: "babel-plugin-formatjs@npm:10.5.41"
dependencies:
"@babel/core": "npm:^7.26.10"
"@babel/helper-plugin-utils": "npm:^7.26.5"
"@babel/plugin-syntax-jsx": "npm:^7.25.9"
"@babel/traverse": "npm:^7.26.10"
"@babel/types": "npm:^7.26.10"
- "@formatjs/icu-messageformat-parser": "npm:2.11.3"
- "@formatjs/ts-transformer": "npm:3.14.1"
+ "@formatjs/icu-messageformat-parser": "npm:2.11.4"
+ "@formatjs/ts-transformer": "npm:3.14.2"
"@types/babel__core": "npm:^7.20.5"
"@types/babel__helper-plugin-utils": "npm:^7.10.3"
"@types/babel__traverse": "npm:^7.20.6"
tslib: "npm:^2.8.0"
- checksum: 10c0/b065cc92ae70dd237bc2aa151f52f91f06337b2ad268d9332cf257414da528f8376aabe7019f9ff630abf55c1b409ecbac720a6ea163397179133b244982320e
+ checksum: 10c0/bbe0e182185c72e4136a4cf37b2366952ad5b1d090de00a132757d2a65a5a6aef95ada93dffdc4ed0cf4338a0ff29c5a0d025d77e8b774b088c69bd68ac07ca6
languageName: node
linkType: hard
@@ -6118,9 +6118,9 @@ __metadata:
linkType: hard
"core-js@npm:^3.30.2, core-js@npm:^3.45.0":
- version: 3.45.1
- resolution: "core-js@npm:3.45.1"
- checksum: 10c0/c38e5fae5a05ee3a129c45e10056aafe61dbb15fd35d27e0c289f5490387541c89741185e0aeb61acb558559c6697e016c245cca738fa169a73f2b06cd30e6b6
+ version: 3.46.0
+ resolution: "core-js@npm:3.46.0"
+ checksum: 10c0/12d559d39a58227881bc6c86c36d24dcfbe2d56e52dac42e35e8643278172596ab67f57ede98baf40b153ca1b830f37420ea32c3f7417c0c5a1fed46438ae187
languageName: node
linkType: hard
@@ -8395,15 +8395,15 @@ __metadata:
languageName: node
linkType: hard
-"intl-messageformat@npm:10.7.17, intl-messageformat@npm:^10.7.16":
- version: 10.7.17
- resolution: "intl-messageformat@npm:10.7.17"
+"intl-messageformat@npm:10.7.18, intl-messageformat@npm:^10.7.16":
+ version: 10.7.18
+ resolution: "intl-messageformat@npm:10.7.18"
dependencies:
- "@formatjs/ecma402-abstract": "npm:2.3.5"
+ "@formatjs/ecma402-abstract": "npm:2.3.6"
"@formatjs/fast-memoize": "npm:2.2.7"
- "@formatjs/icu-messageformat-parser": "npm:2.11.3"
+ "@formatjs/icu-messageformat-parser": "npm:2.11.4"
tslib: "npm:^2.8.0"
- checksum: 10c0/74445987da233cd5a6df0e4d35813ff11483b0788ff5cbbcf9e2a07c276cdd18001a3ba68583bf8d28920494b68a2be91a9c9f796062973dec3c95a4e88ffa81
+ checksum: 10c0/d54da9987335cb2bca26246304cea2ca6b1cb44ca416d6b28f3aa62b11477c72f7ce0bf3f11f5d236ceb1842bdc3378a926e606496d146fde18783ec92c314e1
languageName: node
linkType: hard
@@ -11219,16 +11219,16 @@ __metadata:
linkType: hard
"react-intl@npm:^7.1.10":
- version: 7.1.13
- resolution: "react-intl@npm:7.1.13"
+ version: 7.1.14
+ resolution: "react-intl@npm:7.1.14"
dependencies:
- "@formatjs/ecma402-abstract": "npm:2.3.5"
- "@formatjs/icu-messageformat-parser": "npm:2.11.3"
- "@formatjs/intl": "npm:3.1.7"
+ "@formatjs/ecma402-abstract": "npm:2.3.6"
+ "@formatjs/icu-messageformat-parser": "npm:2.11.4"
+ "@formatjs/intl": "npm:3.1.8"
"@types/hoist-non-react-statics": "npm:^3.3.1"
"@types/react": "npm:16 || 17 || 18 || 19"
hoist-non-react-statics: "npm:^3.3.2"
- intl-messageformat: "npm:10.7.17"
+ intl-messageformat: "npm:10.7.18"
tslib: "npm:^2.8.0"
peerDependencies:
react: 16 || 17 || 18 || 19
@@ -11236,7 +11236,7 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
- checksum: 10c0/2288c63c3eb2b3fdb79af5fa7b0d297469cc2530143fec798d4603d713c2caf28c9cc1e3a0a53c7b0f90331a3b672ae18e0edefd2fe816de90f90daa7612fb41
+ checksum: 10c0/b4361427ea05b4c9e7d87635a323854ca871710e01cd2a46b5da70b34b78a50661c04b2065258f3f49be134ca414c429c804bc34edc277784a9ffa0c04a30b04
languageName: node
linkType: hard
@@ -12877,62 +12877,62 @@ __metadata:
languageName: node
linkType: hard
-"stylelint-config-recommended-scss@npm:^15.0.1":
- version: 15.0.1
- resolution: "stylelint-config-recommended-scss@npm:15.0.1"
+"stylelint-config-recommended-scss@npm:^16.0.1":
+ version: 16.0.2
+ resolution: "stylelint-config-recommended-scss@npm:16.0.2"
dependencies:
postcss-scss: "npm:^4.0.9"
- stylelint-config-recommended: "npm:^16.0.0"
- stylelint-scss: "npm:^6.12.0"
+ stylelint-config-recommended: "npm:^17.0.0"
+ stylelint-scss: "npm:^6.12.1"
peerDependencies:
postcss: ^8.3.3
- stylelint: ^16.16.0
+ stylelint: ^16.24.0
peerDependenciesMeta:
postcss:
optional: true
- checksum: 10c0/8c5854e143145241dbff3d921298eb59e837aa695c0e6d7f08acf75de81f3f8307d39a931781bf8ac7cbe6bf9079a402fee89566206e9cfb1d728ef6b6486890
+ checksum: 10c0/d4e30a881e248d8b039347bf967526f6afe6d6a07f18e2747e14568de32273e819ba478be7a61a0dd63178931b4e891050a34e73d296ab533aa434209a7f3146
languageName: node
linkType: hard
-"stylelint-config-recommended@npm:^16.0.0":
+"stylelint-config-recommended@npm:^17.0.0":
+ version: 17.0.0
+ resolution: "stylelint-config-recommended@npm:17.0.0"
+ peerDependencies:
+ stylelint: ^16.23.0
+ checksum: 10c0/49e5d1c0f58197b2c5585b85fad814fed9bdec44c9870368c46a762664c5ff158c1145b6337456ae194409d692992b5b87421d62880422f71d8a3360417f5ad1
+ languageName: node
+ linkType: hard
+
+"stylelint-config-standard-scss@npm:^16.0.0":
version: 16.0.0
- resolution: "stylelint-config-recommended@npm:16.0.0"
- peerDependencies:
- stylelint: ^16.16.0
- checksum: 10c0/b2b4ea2633a606a0f686521aa5e8908810c9dd21fd4525c86b34213de1e362b445fd5472b6e5ff251d46f999e2ca2c6c704f2efc1c08d5a532084427f4e1c9d8
- languageName: node
- linkType: hard
-
-"stylelint-config-standard-scss@npm:^15.0.1":
- version: 15.0.1
- resolution: "stylelint-config-standard-scss@npm:15.0.1"
+ resolution: "stylelint-config-standard-scss@npm:16.0.0"
dependencies:
- stylelint-config-recommended-scss: "npm:^15.0.1"
- stylelint-config-standard: "npm:^38.0.0"
+ stylelint-config-recommended-scss: "npm:^16.0.1"
+ stylelint-config-standard: "npm:^39.0.0"
peerDependencies:
postcss: ^8.3.3
- stylelint: ^16.18.0
+ stylelint: ^16.23.1
peerDependenciesMeta:
postcss:
optional: true
- checksum: 10c0/85b4c85a9ecd97176ac104fb4590cd48047b6253b830d08749c024752b9bc8871bbf69eca592769d69cd4c6e3f90005960630f1c2cdaf85dbfabdb5621ecc55f
+ checksum: 10c0/eb77f23824c5d649b193cb71d7f9b538b32b8cc1769451b2993270361127243d4011baf891ec265711b8e34e69ce28acb57ab6c3947b51fa3713ac26f4276439
languageName: node
linkType: hard
-"stylelint-config-standard@npm:^38.0.0":
- version: 38.0.0
- resolution: "stylelint-config-standard@npm:38.0.0"
+"stylelint-config-standard@npm:^39.0.0":
+ version: 39.0.1
+ resolution: "stylelint-config-standard@npm:39.0.1"
dependencies:
- stylelint-config-recommended: "npm:^16.0.0"
+ stylelint-config-recommended: "npm:^17.0.0"
peerDependencies:
- stylelint: ^16.18.0
- checksum: 10c0/8b52c7b7d6287c7495a8fe3a681e07ea9478374e7e66b28d61779072d46cd5b845530b2410df7496a008a8efafe834fb46cf07792f4cf57f996e39f24a801b90
+ stylelint: ^16.23.0
+ checksum: 10c0/70a9862a2cedcc2a1807bd92fc91c40877270cf8a39576b91ae056d6de51d3b68104b26f71056ff22461b4319e9ec988d009abf10ead513b2ec15569d82e865a
languageName: node
linkType: hard
-"stylelint-scss@npm:^6.12.0":
- version: 6.12.0
- resolution: "stylelint-scss@npm:6.12.0"
+"stylelint-scss@npm:^6.12.1":
+ version: 6.12.1
+ resolution: "stylelint-scss@npm:6.12.1"
dependencies:
css-tree: "npm:^3.0.1"
is-plain-object: "npm:^5.0.0"
@@ -12944,7 +12944,7 @@ __metadata:
postcss-value-parser: "npm:^4.2.0"
peerDependencies:
stylelint: ^16.0.2
- checksum: 10c0/c0ba314badd22118047e374febf8dabac56bd351d612ed9c9fc2da5dc760996c2768605aa8d4e483cf0b0fe649c35ae5a003c8a872ee5bec1bbc2d8d45673ff5
+ checksum: 10c0/9a0903d34be3c75a72bef32402899db5f6b94c0823c5944fdf1acb2c3dc61c1f70fbb322558f8cb7e42dd01ed5e0dec22ed298f03b7bacc9f467c28330acae71
languageName: node
linkType: hard
@@ -13512,16 +13512,6 @@ __metadata:
languageName: node
linkType: hard
-"typescript@npm:5.8.3":
- version: 5.8.3
- resolution: "typescript@npm:5.8.3"
- bin:
- tsc: bin/tsc
- tsserver: bin/tsserver
- checksum: 10c0/5f8bb01196e542e64d44db3d16ee0e4063ce4f3e3966df6005f2588e86d91c03e1fb131c2581baf0fb65ee79669eea6e161cd448178986587e9f6844446dbb48
- languageName: node
- linkType: hard
-
"typescript@npm:^5.6.0, typescript@npm:~5.9.0":
version: 5.9.2
resolution: "typescript@npm:5.9.2"
@@ -13532,16 +13522,6 @@ __metadata:
languageName: node
linkType: hard
-"typescript@patch:typescript@npm%3A5.8.3#optional!builtin":
- version: 5.8.3
- resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5"
- bin:
- tsc: bin/tsc
- tsserver: bin/tsserver
- checksum: 10c0/39117e346ff8ebd87ae1510b3a77d5d92dae5a89bde588c747d25da5c146603a99c8ee588c7ef80faaf123d89ed46f6dbd918d534d641083177d5fac38b8a1cb
- languageName: node
- linkType: hard
-
"typescript@patch:typescript@npm%3A^5.6.0#optional!builtin, typescript@patch:typescript@npm%3A~5.9.0#optional!builtin":
version: 5.9.2
resolution: "typescript@patch:typescript@npm%3A5.9.2#optional!builtin::version=5.9.2&hash=5786d5"
@@ -13910,8 +13890,8 @@ __metadata:
linkType: hard
"vite-plugin-pwa@npm:^1.0.2":
- version: 1.0.3
- resolution: "vite-plugin-pwa@npm:1.0.3"
+ version: 1.1.0
+ resolution: "vite-plugin-pwa@npm:1.1.0"
dependencies:
debug: "npm:^4.3.6"
pretty-bytes: "npm:^6.1.1"
@@ -13926,7 +13906,7 @@ __metadata:
peerDependenciesMeta:
"@vite-pwa/assets-generator":
optional: true
- checksum: 10c0/03fc24bd12ae4a4130979da4877e3dabddf13d7d6ff2bd68e5e8497a2643b8874a78e6c2502874277ddf2f28593d0a3b025d78af2335bdcc5d2966295784fd46
+ checksum: 10c0/dc199ccbb3cd0a9f740edcbbc8efa7820f67481ae80a15340ca769c21d4f7452d9a9c1d184eac4f6e3fd1ecd9f7fdfd31cc8f9520e43e6795860fe187c77103a
languageName: node
linkType: hard
@@ -13975,8 +13955,8 @@ __metadata:
linkType: hard
"vite@npm:^5.0.0 || ^6.0.0 || ^7.0.0-0, vite@npm:^7.1.1":
- version: 7.1.9
- resolution: "vite@npm:7.1.9"
+ version: 7.1.10
+ resolution: "vite@npm:7.1.10"
dependencies:
esbuild: "npm:^0.25.0"
fdir: "npm:^6.5.0"
@@ -14025,7 +14005,7 @@ __metadata:
optional: true
bin:
vite: bin/vite.js
- checksum: 10c0/f628f903a137c1410232558bde99c223ea00a090bda6af77752c61f912955f0050aac12d3cfe024d08a0f150ff6fab61b3d0be75d634a59b94d49f525392e1f7
+ checksum: 10c0/ea296971a3094b0e463a91af58de64dca56c8c5c563237e59d158641f8ad7f600f624c4f7c05c18fad68f414e23d50d7145118169b8dcd4bc85283c63c7185bb
languageName: node
linkType: hard