From fad9343bab37cd6de340b4cdd7c427730741e214 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:06:35 +0100 Subject: [PATCH 01/40] New Crowdin Translations (automated) (#28069) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/af.json | 3 + app/javascript/mastodon/locales/be.json | 1 + app/javascript/mastodon/locales/bg.json | 1 + app/javascript/mastodon/locales/ca.json | 1 + app/javascript/mastodon/locales/da.json | 1 + app/javascript/mastodon/locales/de.json | 1 + app/javascript/mastodon/locales/es-AR.json | 1 + app/javascript/mastodon/locales/es-MX.json | 1 + app/javascript/mastodon/locales/es.json | 1 + app/javascript/mastodon/locales/et.json | 15 +++ app/javascript/mastodon/locales/eu.json | 13 +-- app/javascript/mastodon/locales/fi.json | 3 +- app/javascript/mastodon/locales/fo.json | 1 + app/javascript/mastodon/locales/fr-QC.json | 11 ++- app/javascript/mastodon/locales/fr.json | 11 ++- app/javascript/mastodon/locales/fy.json | 16 ++++ app/javascript/mastodon/locales/gl.json | 1 + app/javascript/mastodon/locales/he.json | 1 + app/javascript/mastodon/locales/hu.json | 1 + app/javascript/mastodon/locales/is.json | 1 + app/javascript/mastodon/locales/it.json | 1 + app/javascript/mastodon/locales/ko.json | 1 + app/javascript/mastodon/locales/lt.json | 1 + app/javascript/mastodon/locales/nl.json | 15 +-- app/javascript/mastodon/locales/pl.json | 1 + app/javascript/mastodon/locales/pt-BR.json | 1 + app/javascript/mastodon/locales/pt-PT.json | 1 + app/javascript/mastodon/locales/sl.json | 1 + app/javascript/mastodon/locales/sr-Latn.json | 1 + app/javascript/mastodon/locales/sr.json | 1 + app/javascript/mastodon/locales/sv.json | 1 + app/javascript/mastodon/locales/tr.json | 1 + app/javascript/mastodon/locales/uk.json | 1 + app/javascript/mastodon/locales/vi.json | 1 + app/javascript/mastodon/locales/zh-CN.json | 1 + app/javascript/mastodon/locales/zh-HK.json | 1 + app/javascript/mastodon/locales/zh-TW.json | 3 +- config/locales/ca.yml | 5 + config/locales/et.yml | 2 +- config/locales/fy.yml | 1 + config/locales/lt.yml | 98 ++++++++++++++------ config/locales/nl.yml | 2 +- config/locales/simple_form.et.yml | 4 +- config/locales/zh-TW.yml | 2 +- 44 files changed, 180 insertions(+), 52 deletions(-) diff --git a/app/javascript/mastodon/locales/af.json b/app/javascript/mastodon/locales/af.json index 6f7f355fc..d3cc40c60 100644 --- a/app/javascript/mastodon/locales/af.json +++ b/app/javascript/mastodon/locales/af.json @@ -250,6 +250,9 @@ "notifications.column_settings.unread_notifications.highlight": "Lig ongelese kennisgewings uit", "notifications.filter.boosts": "Aangestuurde plasings", "notifications.group": "{count} kennisgewings", + "notifications.permission_denied_alert": "Lessenaarkennisgewings kan nie geaktiveer word nie omdat 'n webblaaier toegewing voorheen geweier was", + "notifications_permission_banner.enable": "Aktiveer lessenaarkennissgewings", + "notifications_permission_banner.how_to_control": "Om kennisgewings te ontvang wanner Mastodon nie oop is nie, aktiveer lessenaarkennisgewings. Jy kan beheer watter spesifieke tipe interaksies lessenaarkennisgewings genereer deur die {icon} knoppie hier bo sodra hulle geaktiveer is.", "onboarding.actions.go_to_explore": "See what's trending", "onboarding.actions.go_to_home": "Go to your home feed", "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json index 06a329a8b..f94a8b79f 100644 --- a/app/javascript/mastodon/locales/be.json +++ b/app/javascript/mastodon/locales/be.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Супадзенне паведамленняў {x}", "search.search_or_paste": "Пошук", "search_popout.full_text_search_disabled_message": "Недаступна на {domain}.", + "search_popout.full_text_search_logged_out_message": "Даступна толькі пры ўваходзе ў сістэму.", "search_popout.language_code": "ISO код мовы", "search_popout.options": "Параметры пошуку", "search_popout.quick_actions": "Хуткія дзеянні", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index ccbd1042d..f57d868c7 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Съвпадение на публикации {x}", "search.search_or_paste": "Търсене или поставяне на URL адрес", "search_popout.full_text_search_disabled_message": "Не е достъпно на {domain}.", + "search_popout.full_text_search_logged_out_message": "Достъпно само при влизане в системата.", "search_popout.language_code": "Код на езика по ISO", "search_popout.options": "Възможности при търсене", "search_popout.quick_actions": "Бързи действия", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index 9ea2ab33c..87121b7c5 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -605,6 +605,7 @@ "search.quick_action.status_search": "Tuts coincidint amb {x}", "search.search_or_paste": "Cerca o escriu l'URL", "search_popout.full_text_search_disabled_message": "No disponible a {domain}.", + "search_popout.full_text_search_logged_out_message": "Només disponible en iniciar la sessió.", "search_popout.language_code": "Codi de llengua ISO", "search_popout.options": "Opcions de cerca", "search_popout.quick_actions": "Accions ràpides", diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index 577d77782..04fc43734 100644 --- a/app/javascript/mastodon/locales/da.json +++ b/app/javascript/mastodon/locales/da.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Indlæg matchende {x}", "search.search_or_paste": "Søg efter eller angiv URL", "search_popout.full_text_search_disabled_message": "Utilgængelig på {domain}.", + "search_popout.full_text_search_logged_out_message": "Kun tilgængelig, når logget ind.", "search_popout.language_code": "ISO-sprogkode", "search_popout.options": "Søgevalg", "search_popout.quick_actions": "Hurtige handlinger", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index 7c0710efc..cf545e48c 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Beiträge passend zu {x}", "search.search_or_paste": "Suchen oder URL einfügen", "search_popout.full_text_search_disabled_message": "Auf {domain} nicht verfügbar.", + "search_popout.full_text_search_logged_out_message": "Nur verfügbar, wenn angemeldet.", "search_popout.language_code": "ISO-Sprachcode", "search_popout.options": "Suchoptionen", "search_popout.quick_actions": "Schnellaktionen", diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json index dfc00f1d8..4573f4ab9 100644 --- a/app/javascript/mastodon/locales/es-AR.json +++ b/app/javascript/mastodon/locales/es-AR.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Mensajes que coinciden con {x}", "search.search_or_paste": "Buscar o pegar dirección web", "search_popout.full_text_search_disabled_message": "No disponible en {domain}.", + "search_popout.full_text_search_logged_out_message": "Solo disponible al iniciar sesión.", "search_popout.language_code": "Código ISO de idioma", "search_popout.options": "Opciones de búsqueda", "search_popout.quick_actions": "Acciones rápidas", diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json index 83ff3debb..f7cd1b330 100644 --- a/app/javascript/mastodon/locales/es-MX.json +++ b/app/javascript/mastodon/locales/es-MX.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Publicaciones que coinciden con {x}", "search.search_or_paste": "Buscar o pegar URL", "search_popout.full_text_search_disabled_message": "No disponible en {domain}.", + "search_popout.full_text_search_logged_out_message": "Solo disponible si inicias sesión.", "search_popout.language_code": "Código de idioma ISO", "search_popout.options": "Opciones de búsqueda", "search_popout.quick_actions": "Acciones rápidas", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index 9850bf039..bbc8bcc75 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Publicaciones que coinciden con {x}", "search.search_or_paste": "Buscar o pegar URL", "search_popout.full_text_search_disabled_message": "No disponible en {domain}.", + "search_popout.full_text_search_logged_out_message": "Solo disponible si inicias sesión.", "search_popout.language_code": "Código de idioma ISO", "search_popout.options": "Opciones de búsqueda", "search_popout.quick_actions": "Acciones rápidas", diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json index 3b6d86a9d..a67aa6fee 100644 --- a/app/javascript/mastodon/locales/et.json +++ b/app/javascript/mastodon/locales/et.json @@ -21,6 +21,7 @@ "account.blocked": "Blokeeritud", "account.browse_more_on_origin_server": "Vaata rohkem algsel profiilil", "account.cancel_follow_request": "Võta jälgimistaotlus tagasi", + "account.copy": "Kopeeri link profiili", "account.direct": "Maini privaatselt @{name}", "account.disable_notifications": "Peata teavitused @{name} postitustest", "account.domain_blocked": "Domeen peidetud", @@ -191,6 +192,7 @@ "conversation.mark_as_read": "Märgi loetuks", "conversation.open": "Vaata vestlust", "conversation.with": "Koos {names}", + "copy_icon_button.copied": "Kopeeritud vahemällu", "copypaste.copied": "Kopeeritud", "copypaste.copy_to_clipboard": "Kopeeri vahemällu", "directory.federated": "Tuntud födiversumist", @@ -390,6 +392,7 @@ "lists.search": "Otsi enda jälgitavate inimeste hulgast", "lists.subheading": "Sinu nimekirjad", "load_pending": "{count, plural, one {# uus kirje} other {# uut kirjet}}", + "loading_indicator.label": "Laadimine…", "media_gallery.toggle_visible": "{number, plural, one {Varja pilt} other {Varja pildid}}", "moved_to_account_banner.text": "Kontot {disabledAccount} ei ole praegu võimalik kasutada, sest kolisid kontole {movedToAccount}.", "mute_modal.duration": "Kestus", @@ -478,6 +481,17 @@ "onboarding.follows.empty": "Kahjuks ei saa hetkel tulemusi näidata. Proovi kasutada otsingut või lehitse uurimise lehte, et leida inimesi, keda jälgida, või proovi hiljem uuesti.", "onboarding.follows.lead": "Haldad ise oma koduvoogu. Mida rohkemaid inimesi jälgid, seda aktiivsem ja huvitavam see on. Need profiilid võiksid olla head alustamiskohad — saad nende jälgimise alati lõpetada!", "onboarding.follows.title": "Populaarne Mastodonis", + "onboarding.profile.discoverable": "Muuda mu profiil avastatavaks", + "onboarding.profile.discoverable_hint": "Kui nõustud enda avastamisega Mastodonis, võivad sinu postitused ilmuda otsingutulemustes ja trendides ning sinu profiili võidakse soovitada sinuga sarnaste huvidega inimestele.", + "onboarding.profile.display_name": "Näidatav nimi", + "onboarding.profile.display_name_hint": "Su täisnimi või naljanimi…", + "onboarding.profile.lead": "Saad selle alati hiljem seadetes lõpuni viia, kus on saadaval veel rohkem kohandamisvalikuid.", + "onboarding.profile.note": "Elulugu", + "onboarding.profile.note_hint": "Saad @mainida teisi kasutajaid või #sildistada…", + "onboarding.profile.save_and_continue": "Salvesta ja jätka", + "onboarding.profile.title": "Profiili seadistamine", + "onboarding.profile.upload_avatar": "Laadi üles profiilipilt", + "onboarding.profile.upload_header": "Laadi üles profiili päis", "onboarding.share.lead": "Anna inimestele teada, kuidas sind Mastodonist üles leida!", "onboarding.share.message": "Ma olen #Mastodon võrgustikus {username}! tule ja jälgi mind aadressil {url}", "onboarding.share.next_steps": "Võimalikud järgmised sammud:", @@ -521,6 +535,7 @@ "privacy.unlisted.short": "Määramata", "privacy_policy.last_updated": "Viimati uuendatud {date}", "privacy_policy.title": "Isikuandmete kaitse", + "recommended": "Soovitatud", "refresh": "Värskenda", "regeneration_indicator.label": "Laeb…", "regeneration_indicator.sublabel": "Su koduvoog on ettevalmistamisel!", diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json index eb666a0ee..26ed7add1 100644 --- a/app/javascript/mastodon/locales/eu.json +++ b/app/javascript/mastodon/locales/eu.json @@ -16,17 +16,17 @@ "account.badges.bot": "Bot-a", "account.badges.group": "Taldea", "account.block": "Blokeatu @{name}", - "account.block_domain": "Ezkutatu {domain} domeinuko guztia", + "account.block_domain": "Blokeatu {domain} domeinua", "account.block_short": "Blokeatu", "account.blocked": "Blokeatuta", "account.browse_more_on_origin_server": "Arakatu gehiago jatorrizko profilean", "account.cancel_follow_request": "Baztertu jarraitzeko eskaera", "account.copy": "Kopiatu profilerako esteka", "account.direct": "Aipatu pribatuki @{name}", - "account.disable_notifications": "Utzi jakinarazteari @{name} erabiltzailearen bidalketetan", + "account.disable_notifications": "Utzi jakinarazteari @{name} erabiltzaileak argitaratzean", "account.domain_blocked": "Ezkutatutako domeinua", "account.edit_profile": "Aldatu profila", - "account.enable_notifications": "Jakinarazi @{name} erabiltzaileak bidalketak egitean", + "account.enable_notifications": "Jakinarazi @{name} erabiltzaileak argitaratzean", "account.endorse": "Nabarmendu profilean", "account.featured_tags.last_status_at": "Azken bidalketa {date} datan", "account.featured_tags.last_status_never": "Bidalketarik ez", @@ -40,7 +40,7 @@ "account.follows.empty": "Erabiltzaile honek ez du inor jarraitzen oraindik.", "account.follows_you": "Jarraitzen dizu", "account.go_to_profile": "Joan profilera", - "account.hide_reblogs": "Ezkutatu @{name}(r)en bultzadak", + "account.hide_reblogs": "Ezkutatu @{name} erabiltzailearen bultzadak", "account.in_memoriam": "Oroimenezkoa.", "account.joined_short": "Elkartuta", "account.languages": "Aldatu harpidetutako hizkuntzak", @@ -60,8 +60,8 @@ "account.report": "Salatu @{name}", "account.requested": "Onarpenaren zain. Egin klik jarraipen-eskaera ezeztatzeko", "account.requested_follow": "{name}-(e)k zu jarraitzeko eskaera egin du", - "account.share": "@{name}(e)ren profila elkarbanatu", - "account.show_reblogs": "Erakutsi @{name}(r)en bultzadak", + "account.share": "Partekatu @{name} erabiltzailearen profila", + "account.show_reblogs": "Erakutsi @{name} erabiltzailearen bultzadak", "account.statuses_counter": "{count, plural, one {Bidalketa {counter}} other {{counter} bidalketa}}", "account.unblock": "Desblokeatu @{name}", "account.unblock_domain": "Berriz erakutsi {domain}", @@ -606,6 +606,7 @@ "search.quick_action.status_search": "{x}-(r)ekin bat datozen argitalpenak", "search.search_or_paste": "Bilatu edo itsatsi URLa", "search_popout.full_text_search_disabled_message": "{domain}-en ez dago eskuragarri.", + "search_popout.full_text_search_logged_out_message": "Soilik erabilgarri saioa hastean.", "search_popout.language_code": "ISO hizkuntza-kodea", "search_popout.options": "Bilaketaren aukerak", "search_popout.quick_actions": "Ekintza azkarrak", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 7a07913f8..e99de4d03 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -482,7 +482,7 @@ "onboarding.follows.lead": "Kokoat oman kotisyötteesi itse. Mitä enemmän ihmisiä seuraat, sitä aktiivisempi ja kiinnostavampi syöte on. Nämä profiilit voivat olla alkuun hyvä lähtökohta — voit aina lopettaa niiden seuraamisen myöhemmin!", "onboarding.follows.title": "Mukauta kotisyötettäsi", "onboarding.profile.discoverable": "Aseta profiilini löydettäväksi", - "onboarding.profile.discoverable_hint": "Kun olet määrittänyt itsesi löydettäväksi Mastodonista, voivat julkaisusi näkyä hakutuloksissa ja suosituissa kohteissa, ja profiiliasi voidaan ehdottaa käyttäjille, jotka ovat kiinnostuneet samoista aiheista kuin sinä.", + "onboarding.profile.discoverable_hint": "Kun olet määrittänyt itsesi löydettäväksi Mastodonista, julkaisusi voivat näkyä hakutuloksissa ja suosituissa kohteissa ja profiiliasi voidaan ehdottaa käyttäjille, jotka ovat kiinnostuneet samoista aiheista kuin sinä.", "onboarding.profile.display_name": "Näyttönimi", "onboarding.profile.display_name_hint": "Koko nimesi tai lempinimesi…", "onboarding.profile.lead": "Voit viimeistellä tämän milloin tahansa asetuksista, jotka tarjoavat vielä enemmän mukautusvalintoja.", @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Julkaisut haulla {x}", "search.search_or_paste": "Hae tai liitä URL-osoite", "search_popout.full_text_search_disabled_message": "Ei saatavilla palvelimella {domain}.", + "search_popout.full_text_search_logged_out_message": "Saatavilla vain sisäänkirjautuneena.", "search_popout.language_code": "ISO-kielikoodi", "search_popout.options": "Hakuvalinnat", "search_popout.quick_actions": "Pikatoiminnot", diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json index aa99a0c30..45fafd15d 100644 --- a/app/javascript/mastodon/locales/fo.json +++ b/app/javascript/mastodon/locales/fo.json @@ -596,6 +596,7 @@ "search.quick_action.status_search": "Postar, ið samsvara {x}", "search.search_or_paste": "Leita ella set URL inn", "search_popout.full_text_search_disabled_message": "Ikki tøkt á {domain}.", + "search_popout.full_text_search_logged_out_message": "Einans tøkt um innritað er.", "search_popout.language_code": "ISO málkoda", "search_popout.options": "Leitimøguleikar", "search_popout.quick_actions": "Skjótar atgerðir", diff --git a/app/javascript/mastodon/locales/fr-QC.json b/app/javascript/mastodon/locales/fr-QC.json index 94ab5333c..e2067cc46 100644 --- a/app/javascript/mastodon/locales/fr-QC.json +++ b/app/javascript/mastodon/locales/fr-QC.json @@ -21,6 +21,7 @@ "account.blocked": "Bloqué·e", "account.browse_more_on_origin_server": "Parcourir davantage sur le profil original", "account.cancel_follow_request": "Retirer cette demande d'abonnement", + "account.copy": "Copier le lien vers le profil", "account.direct": "Mention privée @{name}", "account.disable_notifications": "Ne plus me notifier quand @{name} publie", "account.domain_blocked": "Domaine bloqué", @@ -191,6 +192,7 @@ "conversation.mark_as_read": "Marquer comme lu", "conversation.open": "Afficher cette conversation", "conversation.with": "Avec {names}", + "copy_icon_button.copied": "Copié dans le presse-papier", "copypaste.copied": "Copié", "copypaste.copy_to_clipboard": "Copier dans le presse-papiers", "directory.federated": "D'un fediverse connu", @@ -479,12 +481,17 @@ "onboarding.follows.empty": "Malheureusement, aucun résultat ne peut être affiché pour le moment. Vous pouvez essayer de rechercher ou de parcourir la page \"Explorer\" pour trouver des personnes à suivre, ou réessayer plus tard.", "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", "onboarding.follows.title": "Popular on Mastodon", + "onboarding.profile.discoverable": "Rendre mon profil découvrable", + "onboarding.profile.discoverable_hint": "Lorsque vous acceptez d'être découvert sur Mastodon, vos messages peuvent apparaître dans les résultats de recherche et les tendances, et votre profil peut être suggéré à des personnes ayant des intérêts similaires aux vôtres.", "onboarding.profile.display_name": "Nom affiché", + "onboarding.profile.display_name_hint": "Votre nom complet ou votre nom rigolo…", + "onboarding.profile.lead": "Vous pouvez toujours compléter cela plus tard dans les paramètres. Vous y trouverez encore plus d'options de personnalisation.", "onboarding.profile.note": "Biographie", + "onboarding.profile.note_hint": "Vous pouvez @mentionner d'autres personnes ou #hashtags…", "onboarding.profile.save_and_continue": "Enregistrer et continuer", "onboarding.profile.title": "Configuration du profil", "onboarding.profile.upload_avatar": "Importer une photo de profil", - "onboarding.profile.upload_header": "Envoyer une image de profil", + "onboarding.profile.upload_header": "Importer un entête de profil", "onboarding.share.lead": "Faites savoir aux gens comment vous trouver sur Mastodon!", "onboarding.share.message": "Je suis {username} sur #Mastodon! Suivez-moi sur {url}", "onboarding.share.next_steps": "Étapes suivantes possibles:", @@ -528,6 +535,7 @@ "privacy.unlisted.short": "Non listé", "privacy_policy.last_updated": "Dernière mise à jour {date}", "privacy_policy.title": "Politique de confidentialité", + "recommended": "Recommandé", "refresh": "Actualiser", "regeneration_indicator.label": "Chargement…", "regeneration_indicator.sublabel": "Votre fil d'accueil est en cours de préparation!", @@ -598,6 +606,7 @@ "search.quick_action.status_search": "Publications correspondant à {x}", "search.search_or_paste": "Rechercher ou saisir un URL", "search_popout.full_text_search_disabled_message": "Non disponible sur {domain}.", + "search_popout.full_text_search_logged_out_message": "Disponible uniquement lorsque vous êtes connecté.", "search_popout.language_code": "code de langue ISO", "search_popout.options": "Options de recherche", "search_popout.quick_actions": "Actions rapides", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index f7b3fc1f0..03b656cc4 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -21,6 +21,7 @@ "account.blocked": "Bloqué·e", "account.browse_more_on_origin_server": "Parcourir davantage sur le profil original", "account.cancel_follow_request": "Annuler le suivi", + "account.copy": "Copier le lien vers le profil", "account.direct": "Mention privée @{name}", "account.disable_notifications": "Ne plus me notifier quand @{name} publie quelque chose", "account.domain_blocked": "Domaine bloqué", @@ -191,6 +192,7 @@ "conversation.mark_as_read": "Marquer comme lu", "conversation.open": "Afficher la conversation", "conversation.with": "Avec {names}", + "copy_icon_button.copied": "Copié dans le presse-papier", "copypaste.copied": "Copié", "copypaste.copy_to_clipboard": "Copier dans le presse-papiers", "directory.federated": "Du fédiverse connu", @@ -479,12 +481,17 @@ "onboarding.follows.empty": "Malheureusement, aucun résultat ne peut être affiché pour le moment. Vous pouvez essayer d'utiliser la recherche ou parcourir la page de découverte pour trouver des personnes à suivre, ou réessayez plus tard.", "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", "onboarding.follows.title": "Personnaliser votre flux principal", + "onboarding.profile.discoverable": "Rendre mon profil découvrable", + "onboarding.profile.discoverable_hint": "Lorsque vous acceptez d'être découvert sur Mastodon, vos messages peuvent apparaître dans les résultats de recherche et les tendances, et votre profil peut être suggéré à des personnes ayant des intérêts similaires aux vôtres.", "onboarding.profile.display_name": "Nom affiché", + "onboarding.profile.display_name_hint": "Votre nom complet ou votre nom rigolo…", + "onboarding.profile.lead": "Vous pouvez toujours compléter cela plus tard dans les paramètres. Vous y trouverez encore plus d'options de personnalisation.", "onboarding.profile.note": "Biographie", + "onboarding.profile.note_hint": "Vous pouvez @mentionner d'autres personnes ou #hashtags…", "onboarding.profile.save_and_continue": "Enregistrer et continuer", "onboarding.profile.title": "Configuration du profil", "onboarding.profile.upload_avatar": "Importer une photo de profil", - "onboarding.profile.upload_header": "Envoyer une image de profil", + "onboarding.profile.upload_header": "Importer un entête de profil", "onboarding.share.lead": "Faites savoir aux gens comment ils peuvent vous trouver sur Mastodon!", "onboarding.share.message": "Je suis {username} sur #Mastodon ! Suivez-moi sur {url}", "onboarding.share.next_steps": "Étapes suivantes possibles :", @@ -528,6 +535,7 @@ "privacy.unlisted.short": "Non listé", "privacy_policy.last_updated": "Dernière mise à jour {date}", "privacy_policy.title": "Politique de confidentialité", + "recommended": "Recommandé", "refresh": "Actualiser", "regeneration_indicator.label": "Chargement…", "regeneration_indicator.sublabel": "Votre fil principal est en cours de préparation !", @@ -598,6 +606,7 @@ "search.quick_action.status_search": "Publications correspondant à {x}", "search.search_or_paste": "Rechercher ou saisir une URL", "search_popout.full_text_search_disabled_message": "Non disponible sur {domain}.", + "search_popout.full_text_search_logged_out_message": "Disponible uniquement lorsque vous êtes connecté.", "search_popout.language_code": "code de langue ISO", "search_popout.options": "Options de recherche", "search_popout.quick_actions": "Actions rapides", diff --git a/app/javascript/mastodon/locales/fy.json b/app/javascript/mastodon/locales/fy.json index 2128a045b..2ec4a53bf 100644 --- a/app/javascript/mastodon/locales/fy.json +++ b/app/javascript/mastodon/locales/fy.json @@ -21,6 +21,7 @@ "account.blocked": "Blokkearre", "account.browse_more_on_origin_server": "Mear op it orizjinele profyl besjen", "account.cancel_follow_request": "Folchfersyk annulearje", + "account.copy": "Keppeling nei profyl kopiearje", "account.direct": "Privee fermelde @{name}", "account.disable_notifications": "Jou gjin melding mear wannear @{name} in berjocht pleatst", "account.domain_blocked": "Domein blokkearre", @@ -191,6 +192,7 @@ "conversation.mark_as_read": "As lêzen markearje", "conversation.open": "Petear toane", "conversation.with": "Mei {names}", + "copy_icon_button.copied": "Nei klamboerd kopiearre", "copypaste.copied": "Kopiearre", "copypaste.copy_to_clipboard": "Nei klamboerd kopiearje", "directory.federated": "Fediverse (wat bekend is)", @@ -390,6 +392,7 @@ "lists.search": "Sykje nei minsken dy’t jo folgje", "lists.subheading": "Jo listen", "load_pending": "{count, plural, one {# nij item} other {# nije items}}", + "loading_indicator.label": "Lade…", "media_gallery.toggle_visible": "{number, plural, one {ôfbylding ferstopje} other {ôfbyldingen ferstopje}}", "moved_to_account_banner.text": "Omdat jo nei {movedToAccount} ferhuze binne is jo account {disabledAccount} op dit stuit útskeakele.", "mute_modal.duration": "Doer", @@ -478,6 +481,17 @@ "onboarding.follows.empty": "Spitigernôch kinne op dit stuit gjin resultaten toand wurde. Jo kinne probearje te sykjen of te blêdzjen troch de ferkenningsside om minsken te finen dy’t jo folgje kinne, of probearje it letter opnij.", "onboarding.follows.lead": "Jo beheare jo eigen startside. Hoe mear minsken jo folgje, hoe aktiver en ynteressanter it wêze sil. Dizze profilen kinne in goed startpunt wêze, jo kinne se letter altyd ûntfolgje!", "onboarding.follows.title": "Populêr op Mastodon", + "onboarding.profile.discoverable": "Meitsje myn profyl te finen", + "onboarding.profile.discoverable_hint": "Wannear’t jo akkoard gean mei it te finen wêzen op Mastodon, ferskine jo berjochten yn sykresultaten en kinne se trending wurde, en jo profyl kin oan oare minsken oanrekommandearre wurde wannear’t se fergelykbere ynteressen hawwe.", + "onboarding.profile.display_name": "Werjeftenamme", + "onboarding.profile.display_name_hint": "Jo folsleine namme of in aardige bynamme…", + "onboarding.profile.lead": "Jo kinne dit letter altyd oanfolje yn de ynstellingen, wêr’t noch mear oanpassingsopsjes beskikber binne.", + "onboarding.profile.note": "Biografy", + "onboarding.profile.note_hint": "Jo kinne oare minsken @fermelde of #hashtags brûke…", + "onboarding.profile.save_and_continue": "Bewarje en trochgean", + "onboarding.profile.title": "Profyl ynstelle", + "onboarding.profile.upload_avatar": "Profylfoto oplade", + "onboarding.profile.upload_header": "Omslachfoto foar profyl oplade", "onboarding.share.lead": "Lit minsken witte hoe’t se jo fine kinne op Mastodon!", "onboarding.share.message": "Ik bin {username} op #Mastodon! Folgje my op {url}", "onboarding.share.next_steps": "Mooglike folgjende stappen:", @@ -521,6 +535,7 @@ "privacy.unlisted.short": "Minder iepenbier", "privacy_policy.last_updated": "Lêst bywurke op {date}", "privacy_policy.title": "Privacybelied", + "recommended": "Oanrekommandearre", "refresh": "Ferfarskje", "regeneration_indicator.label": "Lade…", "regeneration_indicator.sublabel": "Jo starttiidline wurdt oanmakke!", @@ -591,6 +606,7 @@ "search.quick_action.status_search": "Berjochten dy’t oerienkomme mei {x}", "search.search_or_paste": "Sykje of fier URL yn", "search_popout.full_text_search_disabled_message": "Net beskikber op {domain}.", + "search_popout.full_text_search_logged_out_message": "Allinnich beskikber as jo oanmeld binne.", "search_popout.language_code": "ISO-taalkoade", "search_popout.options": "Sykopsjes", "search_popout.quick_actions": "Flugge aksjes", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index 83bc826a7..ea6bc05bc 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Publicacións coincidentes {x}", "search.search_or_paste": "Busca ou insire URL", "search_popout.full_text_search_disabled_message": "Non está dispoñible en {domain}.", + "search_popout.full_text_search_logged_out_message": "Só dispoñible ao iniciar sesión.", "search_popout.language_code": "Código ISO do idioma", "search_popout.options": "Opcións de busca", "search_popout.quick_actions": "Accións rápidas", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index 4ab516fae..dda92c5c9 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "הודעות המכילות {x}", "search.search_or_paste": "חפש או הזן קישור", "search_popout.full_text_search_disabled_message": "בלתי זמין על {domain}.", + "search_popout.full_text_search_logged_out_message": "זמין רק לאחר כניסה לאתר.", "search_popout.language_code": "קוד ISO לשפה", "search_popout.options": "אפשרויות חיפוש", "search_popout.quick_actions": "פעולות זריזות", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index 9be5b57e4..9bef81417 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Bejegyzések a következő keresésre: {x}", "search.search_or_paste": "Keresés vagy URL beillesztése", "search_popout.full_text_search_disabled_message": "Nem érhető el ezen: {domain}.", + "search_popout.full_text_search_logged_out_message": "Csak bejelentkezve érhető el.", "search_popout.language_code": "ISO nyelvkód", "search_popout.options": "Keresési beállítások", "search_popout.quick_actions": "Gyors műveletek", diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json index 42d2c9811..0df1a5e75 100644 --- a/app/javascript/mastodon/locales/is.json +++ b/app/javascript/mastodon/locales/is.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Færslur sem samsvara {x}", "search.search_or_paste": "Leita eða líma slóð", "search_popout.full_text_search_disabled_message": "Ekki tiltækt á {domain}.", + "search_popout.full_text_search_logged_out_message": "Aðeins tiltækt eftir innskráningu.", "search_popout.language_code": "ISO-kóði tungumáls", "search_popout.options": "Leitarvalkostir", "search_popout.quick_actions": "Flýtiaðgerðir", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index 2ecf1d8c1..fa659506a 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Post corrispondenti a {x}", "search.search_or_paste": "Cerca o incolla URL", "search_popout.full_text_search_disabled_message": "Non disponibile in {domain}.", + "search_popout.full_text_search_logged_out_message": "Disponibile solo dopo aver effettuato l'accesso.", "search_popout.language_code": "Codice ISO lingua", "search_popout.options": "Opzioni di ricerca", "search_popout.quick_actions": "Azioni rapide", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index 9947d1d8c..46caf32b0 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "{x}에 맞는 게시물", "search.search_or_paste": "검색하거나 URL 붙여넣기", "search_popout.full_text_search_disabled_message": "{domain}에서는 이용할 수 없습니다.", + "search_popout.full_text_search_logged_out_message": "로그인되어 있을 때만 할 수 있습니다.", "search_popout.language_code": "ISO 언어코드", "search_popout.options": "검색 옵션", "search_popout.quick_actions": "빠른 작업", diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json index 4cb95426a..a976d5907 100644 --- a/app/javascript/mastodon/locales/lt.json +++ b/app/javascript/mastodon/locales/lt.json @@ -445,6 +445,7 @@ "search.placeholder": "Paieška", "search.search_or_paste": "Ieškok arba įklijuok URL", "search_popout.full_text_search_disabled_message": "Nepasiekima {domain}.", + "search_popout.full_text_search_logged_out_message": "Pasiekiama tik prisijungus.", "search_popout.language_code": "ISO kalbos kodas", "search_popout.specific_date": "konkreti data", "search_popout.user": "naudotojas", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index b39f1a5c8..295b420fd 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -143,7 +143,7 @@ "compose_form.encryption_warning": "Berichten op Mastodon worden, net zoals op andere social media, niet end-to-end versleuteld. Deel daarom geen gevoelige informatie via Mastodon.", "compose_form.hashtag_warning": "Dit bericht valt niet onder een hashtag te bekijken, omdat deze niet openbaar is. Alleen openbare berichten kunnen via hashtags gevonden worden.", "compose_form.lock_disclaimer": "Jouw account is niet {locked}. Iedereen kan jou volgen en kan de berichten zien die je alleen aan jouw volgers hebt gericht.", - "compose_form.lock_disclaimer.lock": "besloten", + "compose_form.lock_disclaimer.lock": "vergrendeld", "compose_form.placeholder": "Wat wil je kwijt?", "compose_form.poll.add_option": "Keuze toevoegen", "compose_form.poll.duration": "Duur van de peiling", @@ -382,7 +382,7 @@ "lists.delete": "Lijst verwijderen", "lists.edit": "Lijst bewerken", "lists.edit.submit": "Titel veranderen", - "lists.exclusive": "Verberg deze berichten op je starttijdlijn", + "lists.exclusive": "Verberg lijstleden op je starttijdlijn", "lists.new.create": "Lijst toevoegen", "lists.new.title_placeholder": "Naam nieuwe lijst", "lists.replies_policy.followed": "Elke gevolgde gebruiker", @@ -395,7 +395,7 @@ "loading_indicator.label": "Laden…", "media_gallery.toggle_visible": "{number, plural, one {afbeelding verbergen} other {afbeeldingen verbergen}}", "moved_to_account_banner.text": "Omdat je naar {movedToAccount} bent verhuisd is jouw account {disabledAccount} momenteel uitgeschakeld.", - "mute_modal.duration": "Duur", + "mute_modal.duration": "Tijdsduur", "mute_modal.hide_notifications": "Verberg meldingen van deze persoon?", "mute_modal.indefinite": "Voor onbepaalde tijd", "navigation_bar.about": "Over", @@ -481,8 +481,8 @@ "onboarding.follows.empty": "Helaas kunnen op dit moment geen resultaten worden getoond. Je kunt proberen te zoeken of op de verkenningspagina te bladeren om mensen te vinden die je kunt volgen, of probeer het later opnieuw.", "onboarding.follows.lead": "Jouw starttijdlijn is de belangrijkste manier om Mastodon te ervaren. Hoe meer mensen je volgt, hoe actiever en interessanter het zal zijn. Om te beginnen, zijn hier enkele suggesties:", "onboarding.follows.title": "Je starttijdlijn aan jouw wensen aanpassen", - "onboarding.profile.discoverable": "Maak mij profiel ontdekbaar", - "onboarding.profile.discoverable_hint": "Wanneer je kiest voor Mastodon kun je berichten weergeven in zoekresultaten en trending, en je profiel kan worden voorgesteld aan mensen met vergelijkbare interesses.", + "onboarding.profile.discoverable": "Maak mijn profiel vindbaar", + "onboarding.profile.discoverable_hint": "Wanneer je akkoord gaat met het vindbaar zijn op Mastodon, verschijnen je berichten in zoekresultaten en kunnen ze trending worden, en je profiel kan aan andere mensen worden aanbevolen wanneer ze vergelijkbare interesses hebben.", "onboarding.profile.display_name": "Weergavenaam", "onboarding.profile.display_name_hint": "Jouw volledige naam of een leuke bijnaam…", "onboarding.profile.lead": "Je kunt dit later altijd aanvullen in de instellingen, waar nog meer aanpassingsopties beschikbaar zijn.", @@ -491,7 +491,7 @@ "onboarding.profile.save_and_continue": "Opslaan en doorgaan", "onboarding.profile.title": "Profiel instellen", "onboarding.profile.upload_avatar": "Profielfoto uploaden", - "onboarding.profile.upload_header": "Kop voor het profiel uploaden", + "onboarding.profile.upload_header": "Omslagfoto voor het profiel uploaden", "onboarding.share.lead": "Laat mensen weten hoe ze je kunnen vinden op Mastodon!", "onboarding.share.message": "Ik ben {username} op #Mastodon! Volg mij op {url}", "onboarding.share.next_steps": "Mogelijke volgende stappen:", @@ -504,7 +504,7 @@ "onboarding.steps.publish_status.body": "Zeg hallo tegen de wereld met tekst, foto's, video's of peilingen {emoji}", "onboarding.steps.publish_status.title": "Maak je eerste bericht", "onboarding.steps.setup_profile.body": "Anderen zullen eerder met je in contact treden als je wat over jezelf vertelt.", - "onboarding.steps.setup_profile.title": "Pas je profiel aan", + "onboarding.steps.setup_profile.title": "Je profiel aanpassen", "onboarding.steps.share_profile.body": "Laat je vrienden weten waar je te vinden bent op Mastodon", "onboarding.steps.share_profile.title": "Deel je Mastodonprofiel", "onboarding.tips.2fa": "Wist je dat? Je kunt je account beveiligen door tweestapsverificatie in te stellen in je accountinstellingen. Het werkt met elke TOTP-app naar keuze, geen telefoonnummer nodig!", @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Berichten die overeenkomen met {x}", "search.search_or_paste": "Zoek of voer een URL in", "search_popout.full_text_search_disabled_message": "Niet beschikbaar op {domain}.", + "search_popout.full_text_search_logged_out_message": "Alleen beschikbaar als je bent ingelogd.", "search_popout.language_code": "ISO-taalcode", "search_popout.options": "Zoekopties", "search_popout.quick_actions": "Snelle acties", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index 1e6985df2..dc77f8f4e 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Wpisy pasujące do {x}", "search.search_or_paste": "Wyszukaj lub wklej adres", "search_popout.full_text_search_disabled_message": "Niedostępne na {domain}.", + "search_popout.full_text_search_logged_out_message": "Dostępne tylko po zalogowaniu.", "search_popout.language_code": "Kod języka wg ISO", "search_popout.options": "Opcje wyszukiwania", "search_popout.quick_actions": "Szybkie akcje", diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json index 68f367abc..e7975dd76 100644 --- a/app/javascript/mastodon/locales/pt-BR.json +++ b/app/javascript/mastodon/locales/pt-BR.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Publicações correspondentes a {x}", "search.search_or_paste": "Buscar ou colar URL", "search_popout.full_text_search_disabled_message": "Não disponível em {domain}.", + "search_popout.full_text_search_logged_out_message": "Disponível apenas quando conectado.", "search_popout.language_code": "Código ISO do idioma", "search_popout.options": "Opções de pesquisa", "search_popout.quick_actions": "Ações rápidas", diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json index 36e09ac96..2d1616960 100644 --- a/app/javascript/mastodon/locales/pt-PT.json +++ b/app/javascript/mastodon/locales/pt-PT.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Publicações com correspondência a {x}", "search.search_or_paste": "Pesquisar ou introduzir URL", "search_popout.full_text_search_disabled_message": "Não disponível em {domain}.", + "search_popout.full_text_search_logged_out_message": "Apenas disponível quando tem sessão iniciada.", "search_popout.language_code": "Código ISO do idioma", "search_popout.options": "Opções de pesquisa", "search_popout.quick_actions": "Ações rápidas", diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json index 21d198284..4ef2681f9 100644 --- a/app/javascript/mastodon/locales/sl.json +++ b/app/javascript/mastodon/locales/sl.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Objave, ki se ujemajo z {x}", "search.search_or_paste": "Iščite ali prilepite URL", "search_popout.full_text_search_disabled_message": "Ni dostopno na {domain}.", + "search_popout.full_text_search_logged_out_message": "Na voljo le, če ste prijavljeni.", "search_popout.language_code": "Koda ISO jezika", "search_popout.options": "Možnosti iskanja", "search_popout.quick_actions": "Hitra dejanja", diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index 762ac68d9..35bb8f992 100644 --- a/app/javascript/mastodon/locales/sr-Latn.json +++ b/app/javascript/mastodon/locales/sr-Latn.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Podudaranje objava {x}", "search.search_or_paste": "Pretražite ili unesite adresu", "search_popout.full_text_search_disabled_message": "Nije dostupno na {domain}.", + "search_popout.full_text_search_logged_out_message": "Dostupno samo kada ste prijavljeni.", "search_popout.language_code": "ISO kod jezika", "search_popout.options": "Opcije pretrage", "search_popout.quick_actions": "Brze radnje", diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json index 898f0c124..552c04d13 100644 --- a/app/javascript/mastodon/locales/sr.json +++ b/app/javascript/mastodon/locales/sr.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Подударање објава {x}", "search.search_or_paste": "Претражите или унесите адресу", "search_popout.full_text_search_disabled_message": "Није доступно на {domain}.", + "search_popout.full_text_search_logged_out_message": "Доступно само када сте пријављени.", "search_popout.language_code": "ISO код језика", "search_popout.options": "Опције претраге", "search_popout.quick_actions": "Брзе радње", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index 6473a41d6..8a07da72d 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -604,6 +604,7 @@ "search.quick_action.status_search": "Inlägg som matchar {x}", "search.search_or_paste": "Sök eller klistra in URL", "search_popout.full_text_search_disabled_message": "Inte tillgänglig på {domain}.", + "search_popout.full_text_search_logged_out_message": "Endast tillgängligt när du är inloggad.", "search_popout.language_code": "ISO språkkod", "search_popout.options": "Sökalternativ", "search_popout.quick_actions": "Snabbåtgärder", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index 25b61f40e..8eb09bb7c 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Eşleşen gönderiler {x}", "search.search_or_paste": "Ara veya bağlantıyı yapıştır", "search_popout.full_text_search_disabled_message": "{domain} sunucusunda mevcut değil.", + "search_popout.full_text_search_logged_out_message": "Sadece oturum açıldığında mevcuttur.", "search_popout.language_code": "ISO dil kodu", "search_popout.options": "Arama seçenekleri", "search_popout.quick_actions": "Hızlı eylemler", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index 585a4b385..58a14c0ed 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Збіг дописів {x}", "search.search_or_paste": "Введіть адресу або пошуковий запит", "search_popout.full_text_search_disabled_message": "Недоступно на {domain}.", + "search_popout.full_text_search_logged_out_message": "Доступно лише після входу.", "search_popout.language_code": "Код мови ISO", "search_popout.options": "Опції пошуку", "search_popout.quick_actions": "Швидкі дії", diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json index 8fc670557..9ac90b407 100644 --- a/app/javascript/mastodon/locales/vi.json +++ b/app/javascript/mastodon/locales/vi.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Tút nhắc đến {x}", "search.search_or_paste": "Tìm kiếm hoặc nhập URL", "search_popout.full_text_search_disabled_message": "Không khả dụng trên {domain}.", + "search_popout.full_text_search_logged_out_message": "Cần đăng nhập trước.", "search_popout.language_code": "Mã ngôn ngữ ISO", "search_popout.options": "Tùy chọn tìm kiếm", "search_popout.quick_actions": "Thao tác nhanh", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index e58b50476..1678fd729 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "匹配 {x} 的嘟文", "search.search_or_paste": "搜索或输入网址", "search_popout.full_text_search_disabled_message": "在 {domain} 不可用", + "search_popout.full_text_search_logged_out_message": "只有登录后才可用。", "search_popout.language_code": "ISO语言代码", "search_popout.options": "搜索选项", "search_popout.quick_actions": "快捷操作", diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json index af4dad7f7..263c70799 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "符合的帖文 {x}", "search.search_or_paste": "搜尋或貼上網址", "search_popout.full_text_search_disabled_message": "在 {domain} 上無法使用。", + "search_popout.full_text_search_logged_out_message": "登入後才可使用。", "search_popout.language_code": "ISO 語言代碼", "search_popout.options": "搜尋選項", "search_popout.quick_actions": "快速動作", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index 783f95b30..7ba66ae8c 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -176,7 +176,7 @@ "confirmations.domain_block.confirm": "封鎖整個網域", "confirmations.domain_block.message": "您真的非常確定要封鎖整個 {domain} 網域嗎?大部分情況下,封鎖或靜音少數特定的帳號就能滿足需求了。您將不能在任何公開的時間軸及通知中看到來自此網域的內容。您來自該網域的跟隨者也將被移除。", "confirmations.edit.confirm": "編輯", - "confirmations.edit.message": "編輯嘟文將覆蓋掉您目前正在撰寫的訊息。是否仍要繼續?", + "confirmations.edit.message": "編輯嘟文將覆蓋掉您目前正在撰寫之嘟文內容。您是否仍要繼續?", "confirmations.logout.confirm": "登出", "confirmations.logout.message": "您確定要登出嗎?", "confirmations.mute.confirm": "靜音", @@ -606,6 +606,7 @@ "search.quick_action.status_search": "符合的嘟文 {x}", "search.search_or_paste": "搜尋或輸入網址", "search_popout.full_text_search_disabled_message": "{domain} 上無法使用。", + "search_popout.full_text_search_logged_out_message": "僅於登入時能使用。", "search_popout.language_code": "ISO 語言代碼 (ISO language code)", "search_popout.options": "搜尋選項", "search_popout.quick_actions": "快捷操作", diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 85b444c28..0d7605f02 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -534,6 +534,7 @@ ca: total_reported: Informes sobre ells total_storage: Adjunts multimèdia totals_time_period_hint_html: Els totals mostrats a sota incloeixen dades de tots els temps. + unknown_instance: A hores d'ara no hi ha cap registre d'aquest domini al servidor. invites: deactivate_all: Desactiva-ho tot filter: @@ -610,6 +611,7 @@ ca: created_at: Denunciat delete_and_resolve: Elimina les publicacions forwarded: Reenviat + forwarded_replies_explanation: Aquesta denúncia és d'un usuari extern i sobre contingut extern. Se t'han reenviat perquè el contingut denunciat és en resposta a un dels teus usuaris. forwarded_to: Reenviat a %{domain} mark_as_resolved: Marca com a resolt mark_as_sensitive: Marca com a sensible @@ -1038,9 +1040,12 @@ ca: hint_html: Una cosa més! Necessitem confirmar que ets una persona humana (és així com mantenim a ratlla l'spam). Resolt el CAPTCHA inferior i clica a "Segueix". title: Revisió de seguretat confirmations: + awaiting_review: S'ha confirmat la teva adreça-e. El personal de %{domain} revisa ara el registre. Rebràs un correu si t'aproven el compte. + awaiting_review_title: S'està revisant la teva inscripció clicking_this_link: en clicar aquest enllaç login_link: inici de sessió proceed_to_login_html: Ara pots passar a %{login_link}. + registration_complete: La teva inscripció a %{domain} ja és completa. welcome_title: Hola, %{name}! wrong_email_hint: Si aquesta adreça de correu electrònic no és correcte, pots canviar-la en els ajustos del compte. delete_account: Elimina el compte diff --git a/config/locales/et.yml b/config/locales/et.yml index 20f79bdd3..fb0fdc3a3 100644 --- a/config/locales/et.yml +++ b/config/locales/et.yml @@ -1804,7 +1804,7 @@ et: Kui mõni asi arusaamatuks jääb, siis võib vaadata juhendvideot: https://youtu.be/J4ItbTOAw7Q explanation: Siin on mõned nõuanded, mis aitavad alustada final_action: Alusta postitamist - final_step: 'Nüüd tee oma esimene postitus. Hea tava on uues kohas ennast tutvustada ning kindlasti kasuta selles postituses ka teemaviidet #tutvustus. Isegi kui sul ei ole veel jälgijaid, siis su postitusi näevad kohalikul ajajoonel ka kõik teised serveri kasutajad.' + final_step: 'Nüüd tee oma esimene postitus. Hea tava on uues kohas ennast tutvustada ning kindlasti kasuta selles postituses ka silti #tutvustus. Isegi kui sul ei ole veel jälgijaid, siis su postitusi näevad kohalikul ajajoonel ka kõik teised serveri kasutajad.' full_handle: Kasutajanimi Mastodon võrgustikus full_handle_hint: Kui jagad kasutajanime väljaspool serverit, siis kasuta kindlasti pikka nime. Erinevates serverites võib olla sama kasutajanimega liikmeid. subject: Tere tulemast Mastodoni diff --git a/config/locales/fy.yml b/config/locales/fy.yml index 6a7cb3551..a08b3a401 100644 --- a/config/locales/fy.yml +++ b/config/locales/fy.yml @@ -611,6 +611,7 @@ fy: created_at: Rapportearre op delete_and_resolve: Berjocht fuortsmite forwarded: Trochstjoerd + forwarded_replies_explanation: Dit rapport komt fan in eksterne brûker en giet oer eksterne ynhâld. It is nei jo trochstjoerd, omdat de rapportearre ynhâld in reaksje is op ien fan jo brûkers. forwarded_to: Trochstjoerd nei %{domain} mark_as_resolved: As oplost markearje mark_as_sensitive: As gefoelich markearje diff --git a/config/locales/lt.yml b/config/locales/lt.yml index 035b04462..111127749 100644 --- a/config/locales/lt.yml +++ b/config/locales/lt.yml @@ -1,37 +1,44 @@ --- lt: about: - about_mastodon_html: Mastodon, tai socialinis tinklas pagrįstas atviro kodo programavimu, ir atvirais web protokolais. Visiškai nemokamas. Ši sistema decantrilizuota kaip jūsų elektroninis paštas. + about_mastodon_html: 'Ateities socialinis tinklas: jokių reklamų, jokių įmonių sekimo, etiškas dizainas ir decentralizacija. Turėk savo duomenis su Mastodon!' contact_missing: Nenustatyta - contact_unavailable: Nėra duomenų - hosted_on: Mastodon palaikomas naudojantis %{domain} talpinimu + contact_unavailable: Nėra + hosted_on: Mastodon talpinamas %{domain} title: Apie accounts: follow: Sekti followers: few: Sekėjai - many: Sekėjai + many: Sekėjo one: Sekėjas - other: Sekėjai - following: Sekami - last_active: paskutinį kartą aktyvus - link_verified_on: Nuorodos nuosavybė paskutinį kartą tikrinta %{date} - nothing_here: Čia nieko nėra! + other: Sekėjų + following: Seka + instance_actor_flash: Ši paskyra yra virtualus veikėjas (-a), naudojamas atstovauti pačiam serveriui, o ne atskiram naudotojui. Tai naudojama federacijos tikslais ir neturėtų būti pristabdyta. + last_active: paskutinis aktyumas + link_verified_on: Šios nuorodos nuosavybė buvo patikrinta %{date} + nothing_here: Nieko čia nėra! pin_errors: - following: Privalai sekti žmogų kurį nori pagerbti - posts_tab_heading: Tootai + following: Privalai sekti asmenį, kurį nori patvirtinti. + posts: + few: Įrašai + many: Įrašo + one: Įrašas + other: Įrašų + posts_tab_heading: Įrašai admin: account_actions: - action: Veiksmas - title: Moderuoti %{acct} + action: Atlikti veiksmą + title: Atlikti prižiūrėjimo veiksmą %{acct} account_moderation_notes: - create: Palikti žinutę - created_msg: Moderavimo žinutė sėkimngai sukurta! - destroyed_msg: Moderacijos žinutė sėkmingai ištrinta! + create: Palikti pastabą + created_msg: Prižiūrėjimo pastaba sėkmingai sukurta! + destroyed_msg: Prižiūrėjimo pastaba sėkmingai sunaikinta! accounts: + add_email_domain_block: Blokuoti el. pašto domeną approve: Patvirtinti - are_you_sure: Ar esate įsitikinęs? - avatar: Profilio nuotrauka + are_you_sure: Ar esi įsitikinęs (-usi)? + avatar: Avataras by_domain: Domenas change_email: current_email: Dabartinis el paštas @@ -208,7 +215,7 @@ lt: destroyed_msg: Skundo žinutė sekmingai ištrinta! reports: action_taken_by: Veiksmo ėmėsi - are_you_sure: Ar tu įsitikinęs? + are_you_sure: Ar esi įsitikinęs (-usi)? assign_to_self: Paskirti man assigned: Paskirtas moderatorius comment: @@ -223,6 +230,7 @@ lt: create_and_unresolve: Atidaryti su rašteliu delete: Ištrinti placeholder: Apibūdink, kokių veiksmų imtasi arba kitokie atnaujinimai.. + notes_description_html: Peržiūrėk ir palik pastabas kitiems prižiūrėtojams ir savo būsimam aš reopen: Atidaryti skundą report: 'Skundas #%{id}' reported_account: Reportuota paskyra @@ -242,6 +250,8 @@ lt: desc_html: Tai priklauso nuo hCaptcha išorinių skriptų, kurie gali kelti susirūpinimą dėl saugumo ir privatumo. Be to, dėl to registracijos procesas kai kuriems žmonėms (ypač neįgaliesiems) gali būti gerokai sunkiau prieinami. Dėl šių priežasčių apsvarstyk alternatyvias priemones, pavyzdžiui, patvirtinimu arba kvietimu grindžiamą registraciją. domain_blocks: all: Visiems + software_updates: + description: Rekomenduojama nuolat atnaujinti Mastodon diegyklę, kad galėtum naudotis naujausiais pataisymais ir funkcijomis. Be to, kartais labai svarbu laiku naujinti Mastodon, kad būtų išvengta saugumo problemų. Dėl šių priežasčių Mastodon kas 30 minučių tikrina, ar yra atnaujinimų, ir praneša tau apie tai pagal tavo el. pašto pranešimų parinktis. statuses: back_to_account: Atgal į paskyros puslapį media: @@ -249,6 +259,13 @@ lt: no_status_selected: Jokie statusai nebuvo pakeisti, nes niekas nepasirinkta title: Paskyros statusai with_media: Su medija + system_checks: + elasticsearch_health_yellow: + message_html: Elasticsearch klasteris yra nesveikas (geltona būsena), galbūt norėsi išsiaiškinti priežastį + elasticsearch_preset: + message_html: Tavo Elasticsearch klasteris turi daugiau nei vieną mazgą, bet Mastodon nėra sukonfigūruotas juos naudoti. + elasticsearch_preset_single_node: + message_html: Tavo Elasticsearch klasteris turi tik vieną mazgą, ES_PRESET turėtų būti nustatyta į single_node_cluster. title: Administracija warning_presets: add_new: Pridėti naują @@ -276,10 +293,11 @@ lt: regenerate_token: Regeneruoti prieigos žetoną token_regenerated: Prieigos žetonas sėkmingai sugeneruotas warning: Būkite atsargūs su šia informacija. Niekada jos nesidalinkite! - your_token: Jūsų prieigos žetonas + your_token: Tavo prieigos raktas auth: delete_account: Ištrinti paskyrą delete_account_html: Jeigu norite ištrinti savo paskyrą, galite eiti čia. Jūsų prašys patvirtinti pasirinkimą. + dont_have_your_security_key: Neturi saugumo rakto? forgot_password: Pamiršote slaptažodį? invalid_reset_password_token: Slaptažodžio atkūrimo žetonas netinkamas arba jo galiojimo laikas pasibaigęs. Prašykite naujo žetono. login: Prisijungti @@ -294,6 +312,12 @@ lt: preamble_invited: Prieš tęsiant, atsižvelk į pagrindines taisykles, kurias nustatė %{domain} prižiūrėtojai. security: Apsauga set_new_password: Nustatyti naują slaptažodį + status: + redirecting_to: Tavo paskyra yra neaktyvi, nes šiuo metu ji nukreipiama į %{acct}. + self_destruct: Kadangi %{domain} uždaromas, turėsi tik ribotą prieigą prie savo paskyros. + view_strikes: Peržiūrėti ankstesnius savo paskyros pažeidimus + challenge: + hint_html: "Patarimas: artimiausią valandą daugiau neprašysime tavo slaptažodžio." datetime: distance_in_words: about_x_hours: "%{count} val" @@ -309,9 +333,16 @@ lt: x_months: "%{count}mėn" x_seconds: "%{count}sek" deletes: - confirm_password: Kad patvirtintumėte savo tapatybę, įveskite dabartini slaptažodį + challenge_not_passed: Įvesta informacija buvo neteisinga + confirm_password: Įvesk dabartinį slaptažodį, kad patvirtintum savo tapatybę + confirm_username: Procedūros patvirtinimui įvesk savo naudotojo vardą proceed: Ištrinti paskyrą - success_msg: Jūsų paskyra sėkmingai ištrinta + success_msg: Tavo paskyra buvo sėkmingai ištrinta + disputes: + strikes: + your_appeal_approved: Tavo apeliacija buvo patvirtinta + your_appeal_pending: Pateikei apeliaciją + your_appeal_rejected: Tavo apeliacija buvo atmesta errors: '403': Jūs neturie prieigos matyti šiam puslapiui. '404': Puslapis nerastas. @@ -412,21 +443,21 @@ lt: title: Naujas mėgstamas follow: body: "%{name} pradėjo jus sekti!" - subject: "%{name} pradėjo jus sekti" + subject: "%{name} dabar seka tave" title: Naujas sekėjas follow_request: action: Tvarkyti prašymus sekti - body: "%{name} nori tapti Jūsų sekėju" + body: "%{name} paprašė tave sekti" subject: 'Laukiantis sprendimo sekėjas: %{name}' title: Naujas prašymas sekti mention: action: Atsakyti - body: 'Jus paminėjo %{name} pranešime:' - subject: Jus paminėjo %{name} + body: 'Tave %{name} paminėjo:' + subject: Tave paminėjo %{name} title: Naujas paminėjimas reblog: - body: 'Jūsų statusą pakėlė %{name}:' - subject: "%{name} pakėlė Jūsų statusą" + body: 'Tavo įrašą pakėlė %{name}:' + subject: "%{name} pakėlė tavo įrašą" title: Naujas pakėlimas pagination: newer: Naujesnis @@ -517,8 +548,9 @@ lt: suspend: Paskyra užrakinta welcome: edit_profile_action: Nustatyti profilį - explanation: Štai keletas patarimų Jums + explanation: Štai keletas patarimų, kaip pradėti final_action: Pradėti kelti įrašus + final_step: 'Pradėk skelbti! Net jei ir neturi sekėjų, tavo viešus įrašus gali matyti kiti, pavyzdžiui, vietinėje laiko skalėje arba saitažodžiuose. Galbūt norėsi prisistatyti saitažodyje #introductions.' full_handle: Jūsų pilnas slapyvardis full_handle_hint: Štai ką jūs sakytumėte savo draugams, kad jie galėtų jums siųsti žinutes arba just sekti iš kitų serverių. subject: Sveiki atvykę į Mastodon @@ -526,9 +558,15 @@ lt: users: follow_limit_reached: Negalite sekti daugiau nei %{limit} žmonių invalid_otp_token: Netinkamas dviejų veiksnių kodas - otp_lost_help_html: Jeigu praradote prieiga prie abiejų, susisiekite su mumis per %{email} + otp_lost_help_html: Jei praradai prieigą prie abiejų, gali susisiek su %{email} seamless_external_login: Jūs esate prisijungę per išorini įrenginį, todėl slaptąžodis ir el pašto nustatymai neprieinami. signed_in_as: 'Prisijungta kaip:' verification: hint_html: "Savo tapatybės patvirtinimas Mastodon skirtas visiems. Remiantis atviraisiais žiniatinklio standartais, dabar ir visam laikui nemokamas. Viskas, ko tau reikia, yra asmeninė svetainė, pagal kurią žmonės tave atpažįsta. Kai iš savo profilio pateiksi nuorodą į šią svetainę, patikrinsime, ar svetainėje yra nuoroda į tavo profilį, ir parodysime vizualinį indikatorių." verification: Patvirtinimas + verified_links: Tavo patikrintos nuorodos + webauthn_credentials: + create: + error: Kilo problema pridedant saugumo raktą. Bandyk dar kartą. + nickname_hint: Įvesk naujojo saugumo rakto slapyvardį + not_enabled: Dar neįjungei WebAuthn diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 6ad414b3e..870da2a9a 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -611,7 +611,7 @@ nl: created_at: Gerapporteerd op delete_and_resolve: Bericht verwijderen forwarded: Doorgestuurd - forwarded_replies_explanation: Dit rapport komt van een externe gebruiker en gaat over externe inhoud. Het is naar u doorgestuurd omdat de gerapporteerde inhoud een reactie is op een van uw gebruikers. + forwarded_replies_explanation: Dit rapport komt van een externe gebruiker en gaat over externe inhoud. Het is naar je doorgestuurd omdat de gerapporteerde inhoud een reactie is op een van uw gebruikers. forwarded_to: Doorgestuurd naar %{domain} mark_as_resolved: Markeer als opgelost mark_as_sensitive: Als gevoelig markeren diff --git a/config/locales/simple_form.et.yml b/config/locales/simple_form.et.yml index b5a80da98..501e1f333 100644 --- a/config/locales/simple_form.et.yml +++ b/config/locales/simple_form.et.yml @@ -69,7 +69,7 @@ et: domain: See võib olla e-postiaadressis näha olev domeen või MX-kirje, mida aadress kasutab. Kontroll toimub liitumise käigus. with_dns_records: Püütakse lahendada selle domeeni DNS-kirjed ja ühtlasi blokeerida ka selle tulemused featured_tag: - name: 'Siin on mõned nendest siltidest mida sa oled kõige hiljutisemalt kasutanud:' + name: 'Siin on mõned nendest siltidest, mida oled viimati kasutanud:' filters: action: Tegevuse valik, kui postitus vastab filtrile actions: @@ -98,7 +98,7 @@ et: thumbnail: Umbes 2:1 mõõdus pilt serveri informatsiooni kõrval. timeline_preview: Sisenemata külastajatel on võimalik sirvida viimaseid avalikke postitusi serveril. trendable_by_default: Populaarse sisu ülevaatuse vahele jätmine. Pärast seda on siiski võimalik üksikuid üksusi trendidest eemaldada. - trends: Populaarsuse suunad näitavad millised postitused, sildid ja uudislood koguvad sinu serveris tähelepanu. + trends: Trendid näitavad, millised postitused, sildid ja uudislood koguvad sinu serveris tähelepanu. trends_as_landing_page: Näitab välja logitud kasutajatele ja külalistele serveri kirjelduse asemel populaarset sisu. Populaarne sisu (trendid) peab selleks olema sisse lülitatud. form_challenge: current_password: Turvalisse alasse sisenemine diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index b8cbf6e80..755ac3403 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -785,7 +785,7 @@ zh-TW: statuses: account: 作者 application: 應用程式 - back_to_account: 返回帳號訊息頁 + back_to_account: 返回帳號資訊頁面 back_to_report: 回到檢舉報告頁面 batch: remove_from_report: 從檢舉報告中移除 From 73ab080608b5d2378bcc2f10c63377af988f71fc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:06:40 +0100 Subject: [PATCH 02/40] Update dependency jsdom to v23 (#28075) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- streaming/package.json | 2 +- yarn.lock | 122 +++++++++++++++++++++++++++-------------- 2 files changed, 81 insertions(+), 43 deletions(-) diff --git a/streaming/package.json b/streaming/package.json index aecc5752e..52245aeeb 100644 --- a/streaming/package.json +++ b/streaming/package.json @@ -18,7 +18,7 @@ "dotenv": "^16.0.3", "express": "^4.18.2", "ioredis": "^5.3.2", - "jsdom": "^22.1.0", + "jsdom": "^23.0.0", "npmlog": "^7.0.1", "pg": "^8.5.0", "pg-connection-string": "^2.6.0", diff --git a/yarn.lock b/yarn.lock index 3275d1235..c7511a151 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2473,7 +2473,7 @@ __metadata: dotenv: "npm:^16.0.3" express: "npm:^4.18.2" ioredis: "npm:^5.3.2" - jsdom: "npm:^22.1.0" + jsdom: "npm:^23.0.0" npmlog: "npm:^7.0.1" pg: "npm:^8.5.0" pg-connection-string: "npm:^2.6.0" @@ -6366,14 +6366,13 @@ __metadata: languageName: node linkType: hard -"data-urls@npm:^4.0.0": - version: 4.0.0 - resolution: "data-urls@npm:4.0.0" +"data-urls@npm:^5.0.0": + version: 5.0.0 + resolution: "data-urls@npm:5.0.0" dependencies: - abab: "npm:^2.0.6" - whatwg-mimetype: "npm:^3.0.0" - whatwg-url: "npm:^12.0.0" - checksum: 928d9a21db31d3dcee125d514fddfeb88067c348b1225e9d2c6ca55db16e1cbe49bf58c092cae7163de958f415fd5c612c2aef2eef87896e097656fce205d766 + whatwg-mimetype: "npm:^4.0.0" + whatwg-url: "npm:^14.0.0" + checksum: 1b894d7d41c861f3a4ed2ae9b1c3f0909d4575ada02e36d3d3bc584bdd84278e20709070c79c3b3bff7ac98598cb191eb3e86a89a79ea4ee1ef360e1694f92ad languageName: node linkType: hard @@ -8850,6 +8849,15 @@ __metadata: languageName: node linkType: hard +"html-encoding-sniffer@npm:^4.0.0": + version: 4.0.0 + resolution: "html-encoding-sniffer@npm:4.0.0" + dependencies: + whatwg-encoding: "npm:^3.1.1" + checksum: 523398055dc61ac9b34718a719cb4aa691e4166f29187e211e1607de63dc25ac7af52ca7c9aead0c4b3c0415ffecb17326396e1202e2e86ff4bca4c0ee4c6140 + languageName: node + linkType: hard + "html-entities@npm:^1.3.1": version: 1.4.0 resolution: "html-entities@npm:1.4.0" @@ -8985,7 +8993,7 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:^7.0.1": +"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.2": version: 7.0.2 resolution: "https-proxy-agent@npm:7.0.2" dependencies: @@ -10603,39 +10611,37 @@ __metadata: languageName: node linkType: hard -"jsdom@npm:^22.1.0": - version: 22.1.0 - resolution: "jsdom@npm:22.1.0" +"jsdom@npm:^23.0.0": + version: 23.0.0 + resolution: "jsdom@npm:23.0.0" dependencies: - abab: "npm:^2.0.6" cssstyle: "npm:^3.0.0" - data-urls: "npm:^4.0.0" + data-urls: "npm:^5.0.0" decimal.js: "npm:^10.4.3" - domexception: "npm:^4.0.0" form-data: "npm:^4.0.0" - html-encoding-sniffer: "npm:^3.0.0" - http-proxy-agent: "npm:^5.0.0" - https-proxy-agent: "npm:^5.0.1" + html-encoding-sniffer: "npm:^4.0.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.2" is-potential-custom-element-name: "npm:^1.0.1" - nwsapi: "npm:^2.2.4" + nwsapi: "npm:^2.2.7" parse5: "npm:^7.1.2" rrweb-cssom: "npm:^0.6.0" saxes: "npm:^6.0.0" symbol-tree: "npm:^3.2.4" - tough-cookie: "npm:^4.1.2" - w3c-xmlserializer: "npm:^4.0.0" + tough-cookie: "npm:^4.1.3" + w3c-xmlserializer: "npm:^5.0.0" webidl-conversions: "npm:^7.0.0" - whatwg-encoding: "npm:^2.0.0" - whatwg-mimetype: "npm:^3.0.0" - whatwg-url: "npm:^12.0.1" - ws: "npm:^8.13.0" - xml-name-validator: "npm:^4.0.0" + whatwg-encoding: "npm:^3.1.1" + whatwg-mimetype: "npm:^4.0.0" + whatwg-url: "npm:^14.0.0" + ws: "npm:^8.14.2" + xml-name-validator: "npm:^5.0.0" peerDependencies: - canvas: ^2.5.0 + canvas: ^3.0.0 peerDependenciesMeta: canvas: optional: true - checksum: a1c1501c611d1fe833e0a28796a234325aa09d4c597a9d8ccf6970004a9d946d261469502eadb555bdd7a55f5a2fbf3ce60c727cd99acb0d63f257fb9afcd33d + checksum: 2c876a02de49e0ed6b667a4eb9b08b8e76ac189a5571ff97791cc9564e713259314deea6d657cc7f59fc30af41b900e7d833c95017e576dfcaf25f32565722af languageName: node linkType: hard @@ -11983,7 +11989,7 @@ __metadata: languageName: node linkType: hard -"nwsapi@npm:^2.2.2, nwsapi@npm:^2.2.4": +"nwsapi@npm:^2.2.2, nwsapi@npm:^2.2.7": version: 2.2.7 resolution: "nwsapi@npm:2.2.7" checksum: 44be198adae99208487a1c886c0a3712264f7bbafa44368ad96c003512fed2753d4e22890ca1e6edb2690c3456a169f2a3c33bfacde1905cf3bf01c7722464db @@ -13423,7 +13429,7 @@ __metadata: languageName: node linkType: hard -"punycode@npm:^2.1.0, punycode@npm:^2.1.1, punycode@npm:^2.3.0": +"punycode@npm:^2.1.0, punycode@npm:^2.1.1, punycode@npm:^2.3.0, punycode@npm:^2.3.1": version: 2.3.1 resolution: "punycode@npm:2.3.1" checksum: 14f76a8206bc3464f794fb2e3d3cc665ae416c01893ad7a02b23766eb07159144ee612ad67af5e84fa4479ccfe67678c4feb126b0485651b302babf66f04f9e9 @@ -16201,7 +16207,7 @@ __metadata: languageName: node linkType: hard -"tough-cookie@npm:^4.1.2": +"tough-cookie@npm:^4.1.2, tough-cookie@npm:^4.1.3": version: 4.1.3 resolution: "tough-cookie@npm:4.1.3" dependencies: @@ -16231,12 +16237,12 @@ __metadata: languageName: node linkType: hard -"tr46@npm:^4.1.1": - version: 4.1.1 - resolution: "tr46@npm:4.1.1" +"tr46@npm:^5.0.0": + version: 5.0.0 + resolution: "tr46@npm:5.0.0" dependencies: - punycode: "npm:^2.3.0" - checksum: 92085dcf186f56a49ba4124a581d9ae6a5d0cd4878107c34e2e670b9ddc49da85e4950084bb3e75015195cc23f37ae1c02d45064e94dd6018f5e789aa51d93a8 + punycode: "npm:^2.3.1" + checksum: 1521b6e7bbc8adc825c4561480f9fe48eb2276c81335eed9fa610aa4c44a48a3221f78b10e5f18b875769eb3413e30efbf209ed556a17a42aa8d690df44b7bee languageName: node linkType: hard @@ -16851,6 +16857,15 @@ __metadata: languageName: node linkType: hard +"w3c-xmlserializer@npm:^5.0.0": + version: 5.0.0 + resolution: "w3c-xmlserializer@npm:5.0.0" + dependencies: + xml-name-validator: "npm:^5.0.0" + checksum: 8712774c1aeb62dec22928bf1cdfd11426c2c9383a1a63f2bcae18db87ca574165a0fbe96b312b73652149167ac6c7f4cf5409f2eb101d9c805efe0e4bae798b + languageName: node + linkType: hard + "walker@npm:^1.0.8": version: 1.0.8 resolution: "walker@npm:1.0.8" @@ -17158,6 +17173,15 @@ __metadata: languageName: node linkType: hard +"whatwg-encoding@npm:^3.1.1": + version: 3.1.1 + resolution: "whatwg-encoding@npm:3.1.1" + dependencies: + iconv-lite: "npm:0.6.3" + checksum: 273b5f441c2f7fda3368a496c3009edbaa5e43b71b09728f90425e7f487e5cef9eb2b846a31bd760dd8077739c26faf6b5ca43a5f24033172b003b72cf61a93e + languageName: node + linkType: hard + "whatwg-mimetype@npm:^3.0.0": version: 3.0.0 resolution: "whatwg-mimetype@npm:3.0.0" @@ -17165,6 +17189,13 @@ __metadata: languageName: node linkType: hard +"whatwg-mimetype@npm:^4.0.0": + version: 4.0.0 + resolution: "whatwg-mimetype@npm:4.0.0" + checksum: a773cdc8126b514d790bdae7052e8bf242970cebd84af62fb2f35a33411e78e981f6c0ab9ed1fe6ec5071b09d5340ac9178e05b52d35a9c4bcf558ba1b1551df + languageName: node + linkType: hard + "whatwg-url@npm:^11.0.0": version: 11.0.0 resolution: "whatwg-url@npm:11.0.0" @@ -17175,13 +17206,13 @@ __metadata: languageName: node linkType: hard -"whatwg-url@npm:^12.0.0, whatwg-url@npm:^12.0.1": - version: 12.0.1 - resolution: "whatwg-url@npm:12.0.1" +"whatwg-url@npm:^14.0.0": + version: 14.0.0 + resolution: "whatwg-url@npm:14.0.0" dependencies: - tr46: "npm:^4.1.1" + tr46: "npm:^5.0.0" webidl-conversions: "npm:^7.0.0" - checksum: 99f506b2c996704fa0fc5c70d8e5e27dce15492db2921c99cf319a8d56cb61641f5c06089f63e1ab1983de9fd6a63c3c112a90cdb5fe352d7a846979b10df566 + checksum: ac32e9ba9d08744605519bbe9e1371174d36229689ecc099157b6ba102d4251a95e81d81f3d80271eb8da182eccfa65653f07f0ab43ea66a6934e643fd091ba9 languageName: node linkType: hard @@ -17616,7 +17647,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.13.0": +"ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.14.2": version: 8.14.2 resolution: "ws@npm:8.14.2" peerDependencies: @@ -17638,6 +17669,13 @@ __metadata: languageName: node linkType: hard +"xml-name-validator@npm:^5.0.0": + version: 5.0.0 + resolution: "xml-name-validator@npm:5.0.0" + checksum: 3fcf44e7b73fb18be917fdd4ccffff3639373c7cb83f8fc35df6001fecba7942f1dbead29d91ebb8315e2f2ff786b508f0c9dc0215b6353f9983c6b7d62cb1f5 + languageName: node + linkType: hard + "xmlchars@npm:^2.2.0": version: 2.2.0 resolution: "xmlchars@npm:2.2.0" From 97e677f9931db77ab329fc24e1c3b238fd3e055c Mon Sep 17 00:00:00 2001 From: June Date: Mon, 27 Nov 2023 11:06:48 +0100 Subject: [PATCH 03/40] Fix not all legal images showing in file picker when uploading custom emoji (#28076) --- app/views/admin/custom_emojis/new.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/custom_emojis/new.html.haml b/app/views/admin/custom_emojis/new.html.haml index 95996dec8..a03676b00 100644 --- a/app/views/admin/custom_emojis/new.html.haml +++ b/app/views/admin/custom_emojis/new.html.haml @@ -7,7 +7,7 @@ .fields-group = f.input :shortcode, wrapper: :with_label, label: t('admin.custom_emojis.shortcode'), hint: t('admin.custom_emojis.shortcode_hint') .fields-group - = f.input :image, wrapper: :with_label, input_html: { accept: CustomEmoji::IMAGE_MIME_TYPES.join(' ') }, hint: t('admin.custom_emojis.image_hint', size: number_to_human_size(CustomEmoji::LIMIT)) + = f.input :image, wrapper: :with_label, input_html: { accept: CustomEmoji::IMAGE_MIME_TYPES.join(',') }, hint: t('admin.custom_emojis.image_hint', size: number_to_human_size(CustomEmoji::LIMIT)) .actions = f.button :button, t('admin.custom_emojis.upload'), type: :submit From 228b6684464c8a4427ff2712a732e343c26a0c1f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 10:07:01 +0000 Subject: [PATCH 04/40] Update DefinitelyTyped types (non-major) (#28077) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 76 ++++++++++++++++++++++++++-------------------------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/package.json b/package.json index bcd91e3fc..5fe190c69 100644 --- a/package.json +++ b/package.json @@ -165,7 +165,7 @@ "@types/react-dom": "^18.2.4", "@types/react-helmet": "^6.1.6", "@types/react-immutable-proptypes": "^2.1.0", - "@types/react-motion": "^0.0.37", + "@types/react-motion": "^0.0.39", "@types/react-overlays": "^3.1.0", "@types/react-router": "^5.1.20", "@types/react-router-dom": "^5.3.3", diff --git a/yarn.lock b/yarn.lock index c7511a151..77045f04f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2321,7 +2321,7 @@ __metadata: "@types/react-dom": "npm:^18.2.4" "@types/react-helmet": "npm:^6.1.6" "@types/react-immutable-proptypes": "npm:^2.1.0" - "@types/react-motion": "npm:^0.0.37" + "@types/react-motion": "npm:^0.0.39" "@types/react-overlays": "npm:^3.1.0" "@types/react-router": "npm:^5.1.20" "@types/react-router-dom": "npm:^5.3.3" @@ -2953,15 +2953,15 @@ __metadata: linkType: hard "@types/babel__core@npm:*, @types/babel__core@npm:^7.1.12, @types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.1.7, @types/babel__core@npm:^7.20.1": - version: 7.20.4 - resolution: "@types/babel__core@npm:7.20.4" + version: 7.20.5 + resolution: "@types/babel__core@npm:7.20.5" dependencies: "@babel/parser": "npm:^7.20.7" "@babel/types": "npm:^7.20.7" "@types/babel__generator": "npm:*" "@types/babel__template": "npm:*" "@types/babel__traverse": "npm:*" - checksum: 2adc7ec49de5f922271ce087cedee000de468a3e13f92b7b6254016bd8357298cb98e6d2b3c9defc69bb6e38e0c134ffe80776a8ce4e9fb167bbffcb4d7613b7 + checksum: bdee3bb69951e833a4b811b8ee9356b69a61ed5b7a23e1a081ec9249769117fa83aaaf023bb06562a038eb5845155ff663e2d5c75dd95c1d5ccc91db012868ff languageName: node linkType: hard @@ -3022,11 +3022,11 @@ __metadata: linkType: hard "@types/emoji-mart@npm:^3.0.9": - version: 3.0.12 - resolution: "@types/emoji-mart@npm:3.0.12" + version: 3.0.13 + resolution: "@types/emoji-mart@npm:3.0.13" dependencies: "@types/react": "npm:*" - checksum: 146abafe3ce9f4954c7f6ed3603bdc5a897b2d6b99dd9da6065ef597a9a6a59fb914e907decbda29b661216ddf3da8bb34a28d50f3d6929efce2b3c42e73b085 + checksum: 840f920c3242e1d274f0102e67cb2d00434e1fd370e0bcc8983b43b6b62322b01e3ddcd5fb078c60883e613530a7c70b8c40060624897543cd4da9441ca81486 languageName: node linkType: hard @@ -3170,12 +3170,12 @@ __metadata: linkType: hard "@types/jest@npm:^29.5.2": - version: 29.5.8 - resolution: "@types/jest@npm:29.5.8" + version: 29.5.10 + resolution: "@types/jest@npm:29.5.10" dependencies: expect: "npm:^29.0.0" pretty-format: "npm:^29.0.0" - checksum: a28e7827ea7e1a2aace6a386868fa6b8402c162d6c71570aed2c29d3745ddc22ceef6899a20643071817905d3c57b670a7992fc8760bff65939351fd4dc481cf + checksum: b46171d59d12a5f69bbe710f65eaf59a8073337c6b4a67dff8158575caec53f1c61f8a7d645b34d6ac3c4ea398acd30f0c5d1c4a131c0c918798019264a3397d languageName: node linkType: hard @@ -3219,9 +3219,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.195": - version: 4.14.201 - resolution: "@types/lodash@npm:4.14.201" - checksum: 14dc43787296c429433d7d034ed47c5ac24b92217056f80a0e6c990449120b9c9c1058918188945fb88353c0c8333c5c36dccc40c51edbd39b05d2169ab2e0ad + version: 4.14.202 + resolution: "@types/lodash@npm:4.14.202" + checksum: 6064d43c8f454170841bd67c8266cc9069d9e570a72ca63f06bceb484cb4a3ee60c9c1f305c1b9e3a87826049fd41124b8ef265c4dd08b00f6766609c7fe9973 languageName: node linkType: hard @@ -3318,16 +3318,16 @@ __metadata: linkType: hard "@types/prop-types@npm:*, @types/prop-types@npm:^15.7.5": - version: 15.7.10 - resolution: "@types/prop-types@npm:15.7.10" - checksum: 964348d05cdf7399260b3179fbd1462b23d7452dc39fbccb319e54ed6ffafb0a01c0a62c3e6f7c944a635c7a4ad5c99d62c4787c9c4b74e2ec07aebaf6cfedc1 + version: 15.7.11 + resolution: "@types/prop-types@npm:15.7.11" + checksum: e53423cf9d510515ef8b47ff42f4f1b65a7b7b37c8704e2dbfcb9a60defe0c0e1f3cb1acfdeb466bad44ca938d7c79bffdd51b48ffb659df2432169d0b27a132 languageName: node linkType: hard "@types/punycode@npm:^2.1.0": - version: 2.1.2 - resolution: "@types/punycode@npm:2.1.2" - checksum: 4a748533bde61097f205638b3acc2c3b0e25382d2c35a2e3b60c33c904afbad158ef778ae3e1b3f3c84edd7b04b6d9fa049f2832210c308d3fee77ba7b637cb9 + version: 2.1.3 + resolution: "@types/punycode@npm:2.1.3" + checksum: c4babd33d0ed010017bc2d44a15b322b1e2997b9bb335020c26a58ac855e176d337536fa0ca84aa1b0c6d7008799566d4d5430a083d123ac6bbcc59c451b9cfc languageName: node linkType: hard @@ -3353,11 +3353,11 @@ __metadata: linkType: hard "@types/react-dom@npm:^18.0.0, @types/react-dom@npm:^18.2.4": - version: 18.2.15 - resolution: "@types/react-dom@npm:18.2.15" + version: 18.2.17 + resolution: "@types/react-dom@npm:18.2.17" dependencies: "@types/react": "npm:*" - checksum: 70e86f15f69f89b8f179139ab2e8a8aa9765e742789f5dd5a46fec40d4300ada8fe3349cceda42b9964a018982d7ccb7d791b47f781966c992bfd37da909fbd3 + checksum: 33b53078ed7e9e0cfc4dc691e938f7db1cc06353bc345947b41b581c3efe2b980c9e4eb6460dbf5ddc521dd91959194c970221a2bd4bfad9d23ebce338e12938 languageName: node linkType: hard @@ -3380,12 +3380,12 @@ __metadata: languageName: node linkType: hard -"@types/react-motion@npm:^0.0.37": - version: 0.0.37 - resolution: "@types/react-motion@npm:0.0.37" +"@types/react-motion@npm:^0.0.39": + version: 0.0.39 + resolution: "@types/react-motion@npm:0.0.39" dependencies: "@types/react": "npm:*" - checksum: 387f60636d9bdd2e765ce94db969cf762a62495e32807f88380748a74e9beeb3d8e17c3ec334dab8040244ea62e7954d5f4d4bdbdd0ecc8985eb4a6ce465b61c + checksum: 0dfcde777576b3c3289b4dbf2a5085decf71aba6d543697f4c1069d02ed3b543792a253692bd98870af04112c92469328a4fdb93988f93af2e099de8f2c9bc2e languageName: node linkType: hard @@ -3447,11 +3447,11 @@ __metadata: linkType: hard "@types/react-test-renderer@npm:^18.0.0": - version: 18.0.6 - resolution: "@types/react-test-renderer@npm:18.0.6" + version: 18.0.7 + resolution: "@types/react-test-renderer@npm:18.0.7" dependencies: "@types/react": "npm:*" - checksum: f490d4379e8d095f8fa91700ceb37d0fe5a96d7cc0c51e9d7127fc3d2dc4e37a382dd6215b295b300037985cb8938cb5088130102ad14b79e4622e7e520c5a3b + checksum: 45cbe963354acee2ab090979d856763c84f59ef7b63477d1fef5d0fd52760b69aa67bbd205fbd3bd36264620fce72c8e407735a9f2009c40ca50da59b0058c34 languageName: node linkType: hard @@ -3483,13 +3483,13 @@ __metadata: linkType: hard "@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7": - version: 18.2.37 - resolution: "@types/react@npm:18.2.37" + version: 18.2.38 + resolution: "@types/react@npm:18.2.38" dependencies: "@types/prop-types": "npm:*" "@types/scheduler": "npm:*" csstype: "npm:^3.0.2" - checksum: 79dd5d23da05bec54e7423ca17096e345eb8fd80a3bf8dd916bb5cdd60677d27c298523aa5b245d090fcc4ec100cfd58c1af4631fbac709d0a9d8be75f9d78a9 + checksum: 56edd4756081b677e38ee23ad6d340658c5e2468785cb20968318cec357e1ea7ccf3ecd9534981741192dd1b894200acfaf0f1551b4795c6077668f6afc19345 languageName: node linkType: hard @@ -3631,8 +3631,8 @@ __metadata: linkType: hard "@types/webpack@npm:^4.41.33": - version: 4.41.36 - resolution: "@types/webpack@npm:4.41.36" + version: 4.41.38 + resolution: "@types/webpack@npm:4.41.38" dependencies: "@types/node": "npm:*" "@types/tapable": "npm:^1" @@ -3640,7 +3640,7 @@ __metadata: "@types/webpack-sources": "npm:*" anymatch: "npm:^3.0.0" source-map: "npm:^0.6.0" - checksum: 9e9021049b8f7482ec7c45e95d7c1da3604ee04481d7550421ed58f201f66edb8eb6c26b85be94ce3f761874cdbb8b570827becdaf5acdb1897aba9b7f226252 + checksum: 5a0a7465d45a0e7701a8c863e88c6cba7660b37e4aeab851c71baf505dbab2e178be1cac82488c2e7d0ea11fb703ceddb53476daec3ec9a004e2fc1554233483 languageName: node linkType: hard @@ -3652,11 +3652,11 @@ __metadata: linkType: hard "@types/yargs@npm:^17.0.24, @types/yargs@npm:^17.0.8": - version: 17.0.31 - resolution: "@types/yargs@npm:17.0.31" + version: 17.0.32 + resolution: "@types/yargs@npm:17.0.32" dependencies: "@types/yargs-parser": "npm:*" - checksum: 1e04df99bd0ad8ac8b3748b6ac0e99a9a4efe20b9cd8eab69ac9503fe87ab9bec312ad56982e969cdb0e2c0679431434ad571f6934049adb15fa35b22810c867 + checksum: 2095e8aad8a4e66b86147415364266b8d607a3b95b4239623423efd7e29df93ba81bb862784a6e08664f645cc1981b25fd598f532019174cd3e5e1e689e1cccf languageName: node linkType: hard From b8fe77353eb41a5c1ad993a83c1d3715ae2b439e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:07:14 +0100 Subject: [PATCH 05/40] Update dependency aws-sdk-s3 to v1.140.0 (#28080) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1c4f628f1..8c571e6ce 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -131,7 +131,7 @@ GEM attr_required (1.0.1) awrence (1.2.1) aws-eventstream (1.3.0) - aws-partitions (1.855.0) + aws-partitions (1.857.0) aws-sdk-core (3.188.0) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.651.0) @@ -140,7 +140,7 @@ GEM aws-sdk-kms (1.73.0) aws-sdk-core (~> 3, >= 3.188.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.139.0) + aws-sdk-s3 (1.140.0) aws-sdk-core (~> 3, >= 3.188.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.6) From 9b8ba9b3506e9899bbaa6a2e8ae430a3f769b892 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 27 Nov 2023 05:40:03 -0500 Subject: [PATCH 06/40] Remove unused `plain_mailer` layout (#28065) --- app/mailers/admin_mailer.rb | 2 -- app/views/layouts/plain_mailer.html.haml | 1 - 2 files changed, 3 deletions(-) delete mode 100644 app/views/layouts/plain_mailer.html.haml diff --git a/app/mailers/admin_mailer.rb b/app/mailers/admin_mailer.rb index 990b92c33..385e53c65 100644 --- a/app/mailers/admin_mailer.rb +++ b/app/mailers/admin_mailer.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class AdminMailer < ApplicationMailer - layout 'plain_mailer' - helper :accounts helper :languages diff --git a/app/views/layouts/plain_mailer.html.haml b/app/views/layouts/plain_mailer.html.haml deleted file mode 100644 index 0a90f092c..000000000 --- a/app/views/layouts/plain_mailer.html.haml +++ /dev/null @@ -1 +0,0 @@ -= yield From 7b56085f11d06371c4c0cd8bfbbaa268bd0b0be9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 13:55:29 +0100 Subject: [PATCH 07/40] Update dependency typescript to v5.3.2 (#28078) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 77045f04f..98dbfbb68 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16416,22 +16416,22 @@ __metadata: linkType: hard "typescript@npm:5, typescript@npm:^5.0.4": - version: 5.2.2 - resolution: "typescript@npm:5.2.2" + version: 5.3.2 + resolution: "typescript@npm:5.3.2" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 91ae3e6193d0ddb8656d4c418a033f0f75dec5e077ebbc2bd6d76439b93f35683936ee1bdc0e9cf94ec76863aa49f27159b5788219b50e1cd0cd6d110aa34b07 + checksum: d7dbe1fbe19039e36a65468ea64b5d338c976550394ba576b7af9c68ed40c0bc5d12ecce390e4b94b287a09a71bd3229f19c2d5680611f35b7c53a3898791159 languageName: node linkType: hard "typescript@patch:typescript@npm%3A5#optional!builtin, typescript@patch:typescript@npm%3A^5.0.4#optional!builtin": - version: 5.2.2 - resolution: "typescript@patch:typescript@npm%3A5.2.2#optional!builtin::version=5.2.2&hash=f3b441" + version: 5.3.2 + resolution: "typescript@patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 062c1cee1990e6b9419ce8a55162b8dc917eb87f807e4de0327dbc1c2fa4e5f61bc0dd4e034d38ff541d1ed0479b53bcee8e4de3a4075c51a1724eb6216cb6f5 + checksum: 73c8bad74e732d93211c9d77f28b03307e2f5fc6a0afc73f4b783261ab567686a16d6ae958bdaef383a00be1b0b8c8b6741dd6ca3d13af4963fa7e47456d49c7 languageName: node linkType: hard From f1657e6d6275384c199956e8872115fdcec600b0 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 27 Nov 2023 14:25:54 +0100 Subject: [PATCH 08/40] Clamp dates when serializing to Elasticsearch API (#28081) --- app/chewy/accounts_index.rb | 4 +++- app/chewy/concerns/datetime_clamping_concern.rb | 14 ++++++++++++++ app/chewy/public_statuses_index.rb | 4 +++- app/chewy/statuses_index.rb | 4 +++- app/chewy/tags_index.rb | 4 +++- 5 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 app/chewy/concerns/datetime_clamping_concern.rb diff --git a/app/chewy/accounts_index.rb b/app/chewy/accounts_index.rb index 00db257ac..59f2f991f 100644 --- a/app/chewy/accounts_index.rb +++ b/app/chewy/accounts_index.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class AccountsIndex < Chewy::Index + include DatetimeClampingConcern + settings index: index_preset(refresh_interval: '30s'), analysis: { filter: { english_stop: { @@ -60,7 +62,7 @@ class AccountsIndex < Chewy::Index field(:following_count, type: 'long') field(:followers_count, type: 'long') field(:properties, type: 'keyword', value: ->(account) { account.searchable_properties }) - field(:last_status_at, type: 'date', value: ->(account) { account.last_status_at || account.created_at }) + field(:last_status_at, type: 'date', value: ->(account) { clamp_date(account.last_status_at || account.created_at) }) field(:display_name, type: 'text', analyzer: 'verbatim') { field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'verbatim' } field(:username, type: 'text', analyzer: 'verbatim', value: ->(account) { [account.username, account.domain].compact.join('@') }) { field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'verbatim' } field(:text, type: 'text', analyzer: 'verbatim', value: ->(account) { account.searchable_text }) { field :stemmed, type: 'text', analyzer: 'natural' } diff --git a/app/chewy/concerns/datetime_clamping_concern.rb b/app/chewy/concerns/datetime_clamping_concern.rb new file mode 100644 index 000000000..7f176b6e5 --- /dev/null +++ b/app/chewy/concerns/datetime_clamping_concern.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module DatetimeClampingConcern + extend ActiveSupport::Concern + + MIN_ISO8601_DATETIME = '0000-01-01T00:00:00Z'.to_datetime.freeze + MAX_ISO8601_DATETIME = '9999-12-31T23:59:59Z'.to_datetime.freeze + + class_methods do + def clamp_date(datetime) + datetime.clamp(MIN_ISO8601_DATETIME, MAX_ISO8601_DATETIME) + end + end +end diff --git a/app/chewy/public_statuses_index.rb b/app/chewy/public_statuses_index.rb index b5f0be5e5..09a4dfc09 100644 --- a/app/chewy/public_statuses_index.rb +++ b/app/chewy/public_statuses_index.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class PublicStatusesIndex < Chewy::Index + include DatetimeClampingConcern + settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: { filter: { english_stop: { @@ -62,6 +64,6 @@ class PublicStatusesIndex < Chewy::Index field(:tags, type: 'text', analyzer: 'hashtag', value: ->(status) { status.tags.map(&:display_name) }) field(:language, type: 'keyword') field(:properties, type: 'keyword', value: ->(status) { status.searchable_properties }) - field(:created_at, type: 'date') + field(:created_at, type: 'date', value: ->(status) { clamp_date(status.created_at) }) end end diff --git a/app/chewy/statuses_index.rb b/app/chewy/statuses_index.rb index e315a2030..e739ccecb 100644 --- a/app/chewy/statuses_index.rb +++ b/app/chewy/statuses_index.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class StatusesIndex < Chewy::Index + include DatetimeClampingConcern + settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: { filter: { english_stop: { @@ -60,6 +62,6 @@ class StatusesIndex < Chewy::Index field(:searchable_by, type: 'long', value: ->(status) { status.searchable_by }) field(:language, type: 'keyword') field(:properties, type: 'keyword', value: ->(status) { status.searchable_properties }) - field(:created_at, type: 'date') + field(:created_at, type: 'date', value: ->(status) { clamp_date(status.created_at) }) end end diff --git a/app/chewy/tags_index.rb b/app/chewy/tags_index.rb index 5b6349a96..c99218a47 100644 --- a/app/chewy/tags_index.rb +++ b/app/chewy/tags_index.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class TagsIndex < Chewy::Index + include DatetimeClampingConcern + settings index: index_preset(refresh_interval: '30s'), analysis: { analyzer: { content: { @@ -42,6 +44,6 @@ class TagsIndex < Chewy::Index field(:name, type: 'text', analyzer: 'content', value: :display_name) { field(:edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content') } field(:reviewed, type: 'boolean', value: ->(tag) { tag.reviewed? }) field(:usage, type: 'long', value: ->(tag, crutches) { tag.history.aggregate(crutches.time_period).accounts }) - field(:last_status_at, type: 'date', value: ->(tag) { tag.last_status_at || tag.created_at }) + field(:last_status_at, type: 'date', value: ->(tag) { clamp_date(tag.last_status_at || tag.created_at) }) end end From 10b879bd5e87b88b09a4316686be939509ede79a Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Tue, 28 Nov 2023 01:51:22 +0100 Subject: [PATCH 09/40] nodeinfo: add instance name and description (#28079) --- app/serializers/node_info/serializer.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/serializers/node_info/serializer.rb b/app/serializers/node_info/serializer.rb index f70cc38f0..3920b3ee4 100644 --- a/app/serializers/node_info/serializer.rb +++ b/app/serializers/node_info/serializer.rb @@ -38,7 +38,10 @@ class NodeInfo::Serializer < ActiveModel::Serializer end def metadata - {} + { + nodeName: Setting.site_title, + nodeDescription: Setting.site_short_description, + } end private From 2d536bb05f26febeedbb652e342aac630665897b Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 28 Nov 2023 02:41:26 -0500 Subject: [PATCH 10/40] Use `admin_mailer` layout with initial salutation (#28085) --- app/mailers/admin_mailer.rb | 2 ++ app/views/admin_mailer/new_appeal.text.erb | 2 -- app/views/admin_mailer/new_critical_software_updates.text.erb | 2 -- app/views/admin_mailer/new_pending_account.text.erb | 2 -- app/views/admin_mailer/new_report.text.erb | 2 -- app/views/admin_mailer/new_software_updates.text.erb | 2 -- app/views/admin_mailer/new_trends.text.erb | 2 -- app/views/layouts/admin_mailer.text.erb | 3 +++ 8 files changed, 5 insertions(+), 12 deletions(-) create mode 100644 app/views/layouts/admin_mailer.text.erb diff --git a/app/mailers/admin_mailer.rb b/app/mailers/admin_mailer.rb index 385e53c65..2a6fbb0ab 100644 --- a/app/mailers/admin_mailer.rb +++ b/app/mailers/admin_mailer.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class AdminMailer < ApplicationMailer + layout 'admin_mailer' + helper :accounts helper :languages diff --git a/app/views/admin_mailer/new_appeal.text.erb b/app/views/admin_mailer/new_appeal.text.erb index 8b8582360..0494f8898 100644 --- a/app/views/admin_mailer/new_appeal.text.erb +++ b/app/views/admin_mailer/new_appeal.text.erb @@ -1,5 +1,3 @@ -<%= raw t('application_mailer.salutation', name: display_name(@me)) %> - <%= raw t('admin_mailer.new_appeal.body', target: @appeal.account.username, action_taken_by: @appeal.strike.account.username, date: l(@appeal.strike.created_at, format: :with_time_zone), type: t(@appeal.strike.action, scope: 'admin_mailer.new_appeal.actions')) %> > <%= raw word_wrap(@appeal.text, break_sequence: "\n> ") %> diff --git a/app/views/admin_mailer/new_critical_software_updates.text.erb b/app/views/admin_mailer/new_critical_software_updates.text.erb index c901bc50f..63c170dc0 100644 --- a/app/views/admin_mailer/new_critical_software_updates.text.erb +++ b/app/views/admin_mailer/new_critical_software_updates.text.erb @@ -1,5 +1,3 @@ -<%= raw t('application_mailer.salutation', name: display_name(@me)) %> - <%= raw t('admin_mailer.new_critical_software_updates.body') %> <%= raw t('application_mailer.view')%> <%= admin_software_updates_url %> diff --git a/app/views/admin_mailer/new_pending_account.text.erb b/app/views/admin_mailer/new_pending_account.text.erb index a8a2a35fa..9eabb8f15 100644 --- a/app/views/admin_mailer/new_pending_account.text.erb +++ b/app/views/admin_mailer/new_pending_account.text.erb @@ -1,5 +1,3 @@ -<%= raw t('application_mailer.salutation', name: display_name(@me)) %> - <%= raw t('admin_mailer.new_pending_account.body') %> <%= @account.user_email %> (@<%= @account.username %>) diff --git a/app/views/admin_mailer/new_report.text.erb b/app/views/admin_mailer/new_report.text.erb index f8a5224a1..8482225ab 100644 --- a/app/views/admin_mailer/new_report.text.erb +++ b/app/views/admin_mailer/new_report.text.erb @@ -1,5 +1,3 @@ -<%= raw t('application_mailer.salutation', name: display_name(@me)) %> - <%= raw(@report.account.local? ? t('admin_mailer.new_report.body', target: @report.target_account.pretty_acct, reporter: @report.account.pretty_acct) : t('admin_mailer.new_report.body_remote', target: @report.target_account.acct, domain: @report.account.domain)) %> <%= raw t('application_mailer.view')%> <%= admin_report_url(@report) %> diff --git a/app/views/admin_mailer/new_software_updates.text.erb b/app/views/admin_mailer/new_software_updates.text.erb index 2fc4d1a5f..96808f3cb 100644 --- a/app/views/admin_mailer/new_software_updates.text.erb +++ b/app/views/admin_mailer/new_software_updates.text.erb @@ -1,5 +1,3 @@ -<%= raw t('application_mailer.salutation', name: display_name(@me)) %> - <%= raw t('admin_mailer.new_software_updates.body') %> <%= raw t('application_mailer.view')%> <%= admin_software_updates_url %> diff --git a/app/views/admin_mailer/new_trends.text.erb b/app/views/admin_mailer/new_trends.text.erb index 10b10e604..4bcfa1401 100644 --- a/app/views/admin_mailer/new_trends.text.erb +++ b/app/views/admin_mailer/new_trends.text.erb @@ -1,5 +1,3 @@ -<%= raw t('application_mailer.salutation', name: display_name(@me)) %> - <%= raw t('admin_mailer.new_trends.body') %> <%= render partial: 'new_trending_links', object: @links unless @links.empty? %> diff --git a/app/views/layouts/admin_mailer.text.erb b/app/views/layouts/admin_mailer.text.erb new file mode 100644 index 000000000..298007ac8 --- /dev/null +++ b/app/views/layouts/admin_mailer.text.erb @@ -0,0 +1,3 @@ +<%= raw t('application_mailer.salutation', name: display_name(@me)) %> + +<%= yield %> From dfc7154767443a21e82531ddfb56c2fc8fb95dda Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 28 Nov 2023 02:43:16 -0500 Subject: [PATCH 11/40] Remove unused `cached_filtered_status_page` method from accounts controller (#28090) --- app/controllers/accounts_controller.rb | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 936973fb2..a34c116a0 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -96,17 +96,4 @@ class AccountsController < ApplicationController def tag_requested? request.path.split('.').first.end_with?(Addressable::URI.parse("/tagged/#{params[:tag]}").normalize) end - - def cached_filtered_status_page - cache_collection_paginated_by_id( - filtered_statuses, - Status, - PAGE_SIZE, - params_slice(:max_id, :min_id, :since_id) - ) - end - - def params_slice(*keys) - params.slice(*keys).permit(*keys) - end end From 9072896ae57c75550c83ad1ec4df7970d9b59045 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 28 Nov 2023 03:19:08 -0500 Subject: [PATCH 12/40] Avoid unnecessary i-var for account rss page url generation (#28092) --- app/controllers/accounts_controller.rb | 3 +-- app/views/accounts/show.html.haml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index a34c116a0..b0f973172 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -18,8 +18,6 @@ class AccountsController < ApplicationController respond_to do |format| format.html do expires_in(15.seconds, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.hour) unless user_signed_in? - - @rss_url = rss_url end format.rss do @@ -84,6 +82,7 @@ class AccountsController < ApplicationController short_account_url(@account, format: 'rss') end end + helper_method :rss_url def media_requested? request.path.split('.').first.end_with?('/media') && !tag_requested? diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml index d56f10a7f..dde9c5084 100644 --- a/app/views/accounts/show.html.haml +++ b/app/views/accounts/show.html.haml @@ -5,7 +5,7 @@ - if @account.user_prefers_noindex? %meta{ name: 'robots', content: 'noindex, noarchive' }/ - %link{ rel: 'alternate', type: 'application/rss+xml', href: @rss_url }/ + %link{ rel: 'alternate', type: 'application/rss+xml', href: rss_url }/ %link{ rel: 'alternate', type: 'application/activity+json', href: ActivityPub::TagManager.instance.uri_for(@account) }/ - @account.fields.select(&:verifiable?).each do |field| From af02484714162d2a17c23c3beb4a534017945be5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Nov 2023 09:59:48 +0100 Subject: [PATCH 13/40] New Crowdin Translations (automated) (#28096) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/gl.json | 2 +- app/javascript/mastodon/locales/ru.json | 17 +++++++++++++++++ app/javascript/mastodon/locales/th.json | 1 + config/locales/nl.yml | 2 +- config/locales/ru.yml | 3 +++ 5 files changed, 23 insertions(+), 2 deletions(-) diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index ea6bc05bc..08d7d4977 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -687,7 +687,7 @@ "status.translated_from_with": "Traducido do {lang} usando {provider}", "status.uncached_media_warning": "A vista previa non está dispoñíble", "status.unmute_conversation": "Deixar de silenciar conversa", - "status.unpin": "Desafixar do perfil", + "status.unpin": "Non fixar no perfil", "subscribed_languages.lead": "Ao facer cambios só as publicacións nos idiomas seleccionados aparecerán nas túas cronoloxías. Non elixas ningún para poder ver publicacións en tódolos idiomas.", "subscribed_languages.save": "Gardar cambios", "subscribed_languages.target": "Cambiar a subscrición a idiomas para {target}", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index 5c98d906b..f0c48236b 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -21,6 +21,7 @@ "account.blocked": "Заблокировано", "account.browse_more_on_origin_server": "Посмотреть в оригинальном профиле", "account.cancel_follow_request": "Отозвать запрос на подписку", + "account.copy": "Скопировать ссылку на профиль", "account.direct": "Лично упоминать @{name}", "account.disable_notifications": "Не уведомлять о постах от @{name}", "account.domain_blocked": "Домен заблокирован", @@ -191,6 +192,7 @@ "conversation.mark_as_read": "Отметить как прочитанное", "conversation.open": "Просмотр беседы", "conversation.with": "С {names}", + "copy_icon_button.copied": "Скопировано в буфер обмена", "copypaste.copied": "Скопировано", "copypaste.copy_to_clipboard": "Копировать в буфер обмена", "directory.federated": "Со всей федерации", @@ -222,6 +224,7 @@ "emoji_button.search_results": "Результаты поиска", "emoji_button.symbols": "Символы", "emoji_button.travel": "Путешествия и места", + "empty_column.account_hides_collections": "Данный пользователь решил не предоставлять эту информацию", "empty_column.account_suspended": "Учетная запись заблокирована", "empty_column.account_timeline": "Здесь нет постов!", "empty_column.account_unavailable": "Профиль недоступен", @@ -389,6 +392,7 @@ "lists.search": "Искать среди подписок", "lists.subheading": "Ваши списки", "load_pending": "{count, plural, one {# новый элемент} few {# новых элемента} other {# новых элементов}}", + "loading_indicator.label": "Загрузка…", "media_gallery.toggle_visible": "Показать/скрыть {number, plural, =1 {изображение} other {изображения}}", "moved_to_account_banner.text": "Ваша учетная запись {disabledAccount} в настоящее время заморожена, потому что вы переехали на {movedToAccount}.", "mute_modal.duration": "Продолжительность", @@ -477,6 +481,17 @@ "onboarding.follows.empty": "К сожалению, сейчас нет результатов. Вы можете попробовать использовать поиск или просмотреть страницу \"Исследования\", чтобы найти людей, за которыми можно следить, или повторить попытку позже.", "onboarding.follows.lead": "Вы сами формируете свою домашнюю ленту. Чем больше людей, за которыми вы следите, тем активнее и интереснее она будет. Эти профили могут быть хорошей отправной точкой - вы всегда можете от них отказаться!", "onboarding.follows.title": "Популярно на Mastodon", + "onboarding.profile.discoverable": "Сделать мой профиль открытым", + "onboarding.profile.discoverable_hint": "Если вы соглашаетесь на открытость на Mastodon, ваши сообщения могут появляться в результатах поиска и трендах, а ваш профиль может быть предложен людям со схожими с вами интересами.", + "onboarding.profile.display_name": "Отображаемое имя", + "onboarding.profile.display_name_hint": "Ваше полное имя или псевдоним…", + "onboarding.profile.lead": "Вы всегда можете завершить это позже в настройках, где доступны еще более широкие возможности настройки.", + "onboarding.profile.note": "О себе", + "onboarding.profile.note_hint": "Вы можете @упоминать других людей или использовать #хэштеги…", + "onboarding.profile.save_and_continue": "Сохранить и продолжить", + "onboarding.profile.title": "Настройка профиля", + "onboarding.profile.upload_avatar": "Загрузить фотографию профиля", + "onboarding.profile.upload_header": "Загрузить заголовок профиля", "onboarding.share.lead": "Расскажите людям, как они могут найти вас на Mastodon!", "onboarding.share.message": "Я {username} на #Mastodon! Следуйте за мной по адресу {url}", "onboarding.share.next_steps": "Возможные дальнейшие шаги:", @@ -520,6 +535,7 @@ "privacy.unlisted.short": "Скрытый", "privacy_policy.last_updated": "Последнее обновление {date}", "privacy_policy.title": "Политика конфиденциальности", + "recommended": "Рекомендуется", "refresh": "Обновить", "regeneration_indicator.label": "Загрузка…", "regeneration_indicator.sublabel": "Один момент, мы подготавливаем вашу ленту!", @@ -590,6 +606,7 @@ "search.quick_action.status_search": "Посты, соответствующие {x}", "search.search_or_paste": "Поиск (или вставьте URL)", "search_popout.full_text_search_disabled_message": "Недоступно на {domain}.", + "search_popout.full_text_search_logged_out_message": "Доступно только при авторизации.", "search_popout.language_code": "Код языка по стандарту ISO", "search_popout.options": "Параметры поиска", "search_popout.quick_actions": "Быстрые действия", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index d60509143..c020dc362 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "โพสต์ที่ตรงกับ {x}", "search.search_or_paste": "ค้นหาหรือวาง URL", "search_popout.full_text_search_disabled_message": "ไม่พร้อมใช้งานใน {domain}", + "search_popout.full_text_search_logged_out_message": "พร้อมใช้งานเฉพาะเมื่อเข้าสู่ระบบแล้วเท่านั้น", "search_popout.language_code": "รหัสภาษา ISO", "search_popout.options": "ตัวเลือกการค้นหา", "search_popout.quick_actions": "การกระทำด่วน", diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 870da2a9a..44843b219 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -611,7 +611,7 @@ nl: created_at: Gerapporteerd op delete_and_resolve: Bericht verwijderen forwarded: Doorgestuurd - forwarded_replies_explanation: Dit rapport komt van een externe gebruiker en gaat over externe inhoud. Het is naar je doorgestuurd omdat de gerapporteerde inhoud een reactie is op een van uw gebruikers. + forwarded_replies_explanation: Dit rapport komt van een externe gebruiker en gaat over externe inhoud. Het is naar je doorgestuurd omdat de gerapporteerde inhoud een reactie is op een van jouw gebruikers. forwarded_to: Doorgestuurd naar %{domain} mark_as_resolved: Markeer als opgelost mark_as_sensitive: Als gevoelig markeren diff --git a/config/locales/ru.yml b/config/locales/ru.yml index c380776b5..b1c86494c 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -635,6 +635,7 @@ ru: created_at: Создана delete_and_resolve: Удалить посты forwarded: Переслано + forwarded_replies_explanation: Этот отчёт получен от удаленного пользователя и касается удаленного содержимого. Он был направлен вам, так как содержимое сообщения является ответом одному из ваших пользователей. forwarded_to: Переслано на %{domain} mark_as_resolved: Отметить как решённую mark_as_sensitive: Отметить как деликатное @@ -1080,6 +1081,7 @@ ru: clicking_this_link: нажатие на эту ссылку login_link: войти proceed_to_login_html: Теперь вы можете перейти к %{login_link}. + redirect_to_app_html: Вы должны были перенаправлены на приложение %{app_name}. Если этого не произошло, попробуйте %{clicking_this_link} или вернитесь к приложению вручную. registration_complete: Ваша регистрация на %{domain} завершена! welcome_title: Добро пожаловать, %{name}! wrong_email_hint: Если этот адрес электронной почты неверен, вы можете изменить его в настройках аккаунта. @@ -1415,6 +1417,7 @@ ru: '86400': 1 день expires_in_prompt: Никогда generate: Сгенерировать + invalid: Это приглашение недействительно invited_by: 'Вас пригласил(а):' max_uses: few: "%{count} раза" From c824d98ceccda299190ebe1364ffd8bd2a8e330c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 28 Nov 2023 10:17:00 +0100 Subject: [PATCH 14/40] chore(deps): update dependency fabrication to v2.31.0 (#28089) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 8c571e6ce..972adae38 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -272,7 +272,7 @@ GEM et-orbi (1.2.7) tzinfo excon (0.104.0) - fabrication (2.30.0) + fabrication (2.31.0) faker (3.2.2) i18n (>= 1.8.11, < 2) faraday (1.10.3) From baf3b71e3b881a2143c983ce71646ae3a8262086 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 28 Nov 2023 04:17:26 -0500 Subject: [PATCH 15/40] Extract `path_without_format` private methd in accounts controller (#28091) --- app/controllers/accounts_controller.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index b0f973172..850bf881f 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -85,14 +85,18 @@ class AccountsController < ApplicationController helper_method :rss_url def media_requested? - request.path.split('.').first.end_with?('/media') && !tag_requested? + path_without_format.end_with?('/media') && !tag_requested? end def replies_requested? - request.path.split('.').first.end_with?('/with_replies') && !tag_requested? + path_without_format.end_with?('/with_replies') && !tag_requested? end def tag_requested? - request.path.split('.').first.end_with?(Addressable::URI.parse("/tagged/#{params[:tag]}").normalize) + path_without_format.end_with?(Addressable::URI.parse("/tagged/#{params[:tag]}").normalize) + end + + def path_without_format + request.path.split('.').first end end From 8ebc94dd22a18c28c4c9763b909e92e6ba64e242 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Tue, 28 Nov 2023 11:03:32 +0100 Subject: [PATCH 16/40] Ignore `@svgr/webpack` updates as they require a Webpacker upgrade (#28098) --- .github/renovate.json5 | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 77b64fdd3..895dbfbad 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -22,6 +22,7 @@ 'react-hotkeys', // Requires code changes // Requires Webpacker upgrade or replacement + '@svgr/webpack', '@types/webpack', 'babel-loader', 'compression-webpack-plugin', From a80530d1df39f549b3fa2e4f84669c4851bea443 Mon Sep 17 00:00:00 2001 From: Michael Stanclift Date: Tue, 28 Nov 2023 04:04:40 -0600 Subject: [PATCH 17/40] Dockerfile rewrite based on Ruby image with performance optimizations and size reduction, dedicated Streaming image (#26850) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: “Michael <“mx@vmstan.com> Co-authored-by: Emelia Smith --- .github/workflows/build-container-image.yml | 3 + .github/workflows/build-nightly.yml | 23 ++ .github/workflows/build-push-pr.yml | 17 ++ .github/workflows/build-releases.yml | 22 ++ .github/workflows/test-image-build.yml | 14 + Dockerfile | 295 +++++++++++++++----- streaming/.dockerignore | 7 + streaming/Dockerfile | 102 +++++++ 8 files changed, 419 insertions(+), 64 deletions(-) create mode 100644 streaming/.dockerignore create mode 100644 streaming/Dockerfile diff --git a/.github/workflows/build-container-image.yml b/.github/workflows/build-container-image.yml index 29868c72f..e100e1582 100644 --- a/.github/workflows/build-container-image.yml +++ b/.github/workflows/build-container-image.yml @@ -21,6 +21,8 @@ on: type: string labels: type: string + file_to_build: + type: string jobs: build-image: @@ -86,6 +88,7 @@ jobs: - uses: docker/build-push-action@v5 with: context: . + file: ${{ inputs.file_to_build }} build-args: | MASTODON_VERSION_PRERELEASE=${{ inputs.version_prerelease }} MASTODON_VERSION_METADATA=${{ inputs.version_metadata }} diff --git a/.github/workflows/build-nightly.yml b/.github/workflows/build-nightly.yml index 1790d5c84..7c6f74b45 100644 --- a/.github/workflows/build-nightly.yml +++ b/.github/workflows/build-nightly.yml @@ -25,6 +25,7 @@ jobs: needs: compute-suffix uses: ./.github/workflows/build-container-image.yml with: + file_to_build: Dockerfile platforms: linux/amd64,linux/arm64 use_native_arm64_builder: true cache: false @@ -41,3 +42,25 @@ jobs: type=raw,value=nightly type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }} secrets: inherit + + build-image-streaming: + needs: compute-suffix + uses: ./.github/workflows/build-container-image.yml + with: + file_to_build: streaming/Dockerfile + platforms: linux/amd64,linux/arm64 + use_native_arm64_builder: true + cache: false + push_to_images: | + tootsuite/mastodon-streaming + ghcr.io/mastodon/mastodon-streaming + version_prerelease: ${{ needs.compute-suffix.outputs.prerelease }} + labels: | + org.opencontainers.image.description=Nightly build image used for testing purposes + flavor: | + latest=auto + tags: | + type=raw,value=edge + type=raw,value=nightly + type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }} + secrets: inherit diff --git a/.github/workflows/build-push-pr.yml b/.github/workflows/build-push-pr.yml index 1f647e2a1..72baed512 100644 --- a/.github/workflows/build-push-pr.yml +++ b/.github/workflows/build-push-pr.yml @@ -29,6 +29,7 @@ jobs: needs: compute-suffix uses: ./.github/workflows/build-container-image.yml with: + file_to_build: Dockerfile platforms: linux/amd64,linux/arm64 use_native_arm64_builder: true push_to_images: | @@ -39,3 +40,19 @@ jobs: tags: | type=ref,event=pr secrets: inherit + + build-image-streaming: + needs: compute-suffix + uses: ./.github/workflows/build-container-image.yml + with: + file_to_build: streaming/Dockerfile + platforms: linux/amd64,linux/arm64 + use_native_arm64_builder: true + push_to_images: | + ghcr.io/mastodon/mastodon-streaming + version_metadata: ${{ needs.compute-suffix.outputs.metadata }} + flavor: | + latest=auto + tags: | + type=ref,event=pr + secrets: inherit diff --git a/.github/workflows/build-releases.yml b/.github/workflows/build-releases.yml index 3b82eef9d..3f0bef32a 100644 --- a/.github/workflows/build-releases.yml +++ b/.github/workflows/build-releases.yml @@ -12,6 +12,7 @@ jobs: build-image: uses: ./.github/workflows/build-container-image.yml with: + file_to_build: Dockerfile platforms: linux/amd64,linux/arm64 use_native_arm64_builder: true push_to_images: | @@ -27,3 +28,24 @@ jobs: type=pep440,pattern={{raw}} type=pep440,pattern=v{{major}}.{{minor}} secrets: inherit + + build-image-streaming: + if: startsWith(github.ref, 'refs/tags/v4.3.') + uses: ./.github/workflows/build-container-image.yml + with: + file_to_build: streaming/Dockerfile + platforms: linux/amd64,linux/arm64 + use_native_arm64_builder: true + push_to_images: | + tootsuite/mastodon-streaming + ghcr.io/mastodon/mastodon-streaming + # Do not use cache when building releases, so apt update is always ran and the release always contain the latest packages + cache: false + # Only tag with latest when ran against the latest stable branch + # This needs to be updated after each minor version release + flavor: | + latest=${{ startsWith(github.ref, 'refs/tags/v4.3.') }} + tags: | + type=pep440,pattern={{raw}} + type=pep440,pattern=v{{major}}.{{minor}} + secrets: inherit diff --git a/.github/workflows/test-image-build.yml b/.github/workflows/test-image-build.yml index 778e34177..980e07189 100644 --- a/.github/workflows/test-image-build.yml +++ b/.github/workflows/test-image-build.yml @@ -7,6 +7,7 @@ on: - .github/workflows/build-releases.yml - .github/workflows/test-image-build.yml - Dockerfile + - streaming/Dockerfile permissions: contents: read @@ -18,4 +19,17 @@ jobs: uses: ./.github/workflows/build-container-image.yml with: + file_to_build: Dockerfile platforms: linux/amd64 # Testing only on native platform so it is performant + cache: true + + build-image-streaming: + concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-streaming + cancel-in-progress: true + + uses: ./.github/workflows/build-container-image.yml + with: + file_to_build: streaming/Dockerfile + platforms: linux/amd64 # Testing only on native platform so it is performant + cache: true diff --git a/Dockerfile b/Dockerfile index 7e032073b..623a4d4ea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,20 +1,182 @@ # syntax=docker/dockerfile:1.4 -# This needs to be bookworm-slim because the Ruby image is built on bookworm-slim -ARG NODE_VERSION="20.9-bookworm-slim" -FROM ghcr.io/moritzheiber/ruby-jemalloc:3.2.2-slim as ruby -FROM node:${NODE_VERSION} as build +# Please see https://docs.docker.com/engine/reference/builder for information about +# the extended buildx capabilities used in this file. +# Make sure multiarch TARGETPLATFORM is available for interpolation +# See: https://docs.docker.com/build/building/multi-platform/ +ARG TARGETPLATFORM=${TARGETPLATFORM} +ARG BUILDPLATFORM=${BUILDPLATFORM} -COPY --link --from=ruby /opt/ruby /opt/ruby +# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.2.2"] +ARG RUBY_VERSION="3.2.2" +# # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"] +ARG NODE_MAJOR_VERSION="20" +# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"] +ARG DEBIAN_VERSION="bookworm" +# Node image to use for base image based on combined variables (ex: 20-bookworm-slim) +FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim as node +# Ruby image to use for base image based on combined variables (ex: 3.2.2-slim-bookworm) +FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} as ruby -ENV DEBIAN_FRONTEND="noninteractive" \ - PATH="${PATH}:/opt/ruby/bin" +# Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA +# Example: v4.2.0-nightly.2023.11.09+something +# Overwrite existance of 'alpha.0' in version.rb [--build-arg MASTODON_VERSION_PRERELEASE="nightly.2023.11.09"] +ARG MASTODON_VERSION_PRERELEASE="" +# Append build metadata or fork information to version.rb [--build-arg MASTODON_VERSION_METADATA="something"] +ARG MASTODON_VERSION_METADATA="" -SHELL ["/bin/bash", "-o", "pipefail", "-c"] +# Allow Ruby on Rails to serve static files +# See: https://docs.joinmastodon.org/admin/config/#rails_serve_static_files +ARG RAILS_SERVE_STATIC_FILES="true" +# Allow to use YJIT compiler +# See: https://github.com/ruby/ruby/blob/master/doc/yjit/yjit.md +ARG RUBY_YJIT_ENABLE="1" +# Timezone used by the Docker container and runtime, change with [--build-arg TZ=Europe/Berlin] +ARG TZ="Etc/UTC" +# Linux UID (user id) for the mastodon user, change with [--build-arg UID=1234] +ARG UID="991" +# Linux GID (group id) for the mastodon user, change with [--build-arg GID=1234] +ARG GID="991" +# Apply Mastodon build options based on options above +ENV \ +# Apply Mastodon version information + MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \ + MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}" \ +# Apply Mastodon static files and YJIT options + RAILS_SERVE_STATIC_FILES=${RAILS_SERVE_STATIC_FILES} \ + RUBY_YJIT_ENABLE=${RUBY_YJIT_ENABLE} \ +# Apply timezone + TZ=${TZ} + +ENV \ +# Configure the IP to bind Mastodon to when serving traffic + BIND="0.0.0.0" \ +# Use production settings for Yarn, Node and related nodejs based tools + NODE_ENV="production" \ +# Use production settings for Ruby on Rails + RAILS_ENV="production" \ +# Add Ruby and Mastodon installation to the PATH + DEBIAN_FRONTEND="noninteractive" \ + PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin" \ +# Optimize jemalloc 5.x performance + MALLOC_CONF="narenas:2,background_thread:true,thp:never,dirty_decay_ms:1000,muzzy_decay_ms:0" + +# Set default shell used for running commands +SHELL ["/bin/bash", "-o", "pipefail", "-o", "errexit", "-c"] + +ARG TARGETPLATFORM + +RUN echo "Target platform is $TARGETPLATFORM" + +RUN \ +# Sets timezone + echo "${TZ}" > /etc/localtime; \ +# Creates mastodon user/group and sets home directory + groupadd -g "${GID}" mastodon; \ + useradd -l -u "${UID}" -g "${GID}" -m -d /opt/mastodon mastodon; \ +# Creates /mastodon symlink to /opt/mastodon + ln -s /opt/mastodon /mastodon; + +# Set /opt/mastodon as working directory WORKDIR /opt/mastodon +# hadolint ignore=DL3008,DL3005 +RUN \ +# Mount Apt cache and lib directories from Docker buildx caches +--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ +--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ +# Apt update & upgrade to check for security updates to Debian image + apt-get update; \ + apt-get dist-upgrade -yq; \ +# Install jemalloc, curl and other necessary components + apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + ffmpeg \ + file \ + imagemagick \ + libjemalloc2 \ + patchelf \ + procps \ + tini \ + tzdata \ + ; \ +# Patch Ruby to use jemalloc + patchelf --add-needed libjemalloc.so.2 /usr/local/bin/ruby; \ +# Discard patchelf after use + apt-get purge -y \ + patchelf \ + ; + +# Create temporary build layer from base image +FROM ruby as build + +# Copy Node package configuration files into working directory +COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/ +COPY .yarn /opt/mastodon/.yarn + +COPY --from=node /usr/local/bin /usr/local/bin +COPY --from=node /usr/local/lib /usr/local/lib + +ARG TARGETPLATFORM + # hadolint ignore=DL3008 +RUN \ +# Mount Apt cache and lib directories from Docker buildx caches +--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ +--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ +# Install build tools and bundler dependencies from APT + apt-get update; \ + apt-get install -y --no-install-recommends \ + g++ \ + gcc \ + git \ + libgdbm-dev \ + libgmp-dev \ + libicu-dev \ + libidn-dev \ + libpq-dev \ + libssl-dev \ + make \ + shared-mime-info \ + zlib1g-dev \ + ; + +RUN \ +# Configure Corepack + rm /usr/local/bin/yarn*; \ + corepack enable; \ + corepack prepare --activate; + +# Create temporary bundler specific build layer from build layer +FROM build as bundler + +ARG TARGETPLATFORM + +# Copy Gemfile config into working directory +COPY Gemfile* /opt/mastodon/ + +RUN \ +# Mount Ruby Gem caches +--mount=type=cache,id=gem-cache-${TARGETPLATFORM},target=/usr/local/bundle/cache/,sharing=locked \ +# Configure bundle to prevent changes to Gemfile and Gemfile.lock + bundle config set --global frozen "true"; \ +# Configure bundle to not cache downloaded Gems + bundle config set --global cache_all "false"; \ +# Configure bundle to only process production Gems + bundle config set --local without "development test"; \ +# Configure bundle to not warn about root user + bundle config set silence_root_warning "true"; \ +# Download and install required Gems + bundle install -j"$(nproc)"; + +# Create temporary node specific build layer from build layer +FROM build as yarn + +ARG TARGETPLATFORM + +# Copy Node package configuration files into working directory RUN apt-get update && \ apt-get -yq dist-upgrade && \ apt-get install -y --no-install-recommends build-essential \ @@ -41,72 +203,77 @@ COPY Gemfile* package.json yarn.lock .yarnrc.yml /opt/mastodon/ COPY streaming/package.json /opt/mastodon/streaming/ COPY .yarn /opt/mastodon/.yarn -RUN bundle install -j"$(nproc)" +# hadolint ignore=DL3008 +RUN \ +--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \ +--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \ +# Install Node packages + yarn workspaces focus --production @mastodon/mastodon; -RUN yarn workspaces focus --all --production && \ - yarn cache clean +# Create temporary assets build layer from build layer +FROM build as precompiler -FROM node:${NODE_VERSION} +# Copy Mastodon sources into precompiler layer +COPY . /opt/mastodon/ -# Use those args to specify your own version flags & suffixes -ARG MASTODON_VERSION_PRERELEASE="" -ARG MASTODON_VERSION_METADATA="" +# Copy bundler and node packages from build layer to container +COPY --from=yarn /opt/mastodon /opt/mastodon/ +COPY --from=bundler /opt/mastodon /opt/mastodon/ +COPY --from=bundler /usr/local/bundle/ /usr/local/bundle/ -ARG UID="991" -ARG GID="991" +ARG TARGETPLATFORM -COPY --link --from=ruby /opt/ruby /opt/ruby +RUN \ +# Use Ruby on Rails to create Mastodon assets + OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder bundle exec rails assets:precompile; \ +# Cleanup temporary files + rm -fr /opt/mastodon/tmp; -SHELL ["/bin/bash", "-o", "pipefail", "-c"] +# Prep final Mastodon Ruby layer +FROM ruby as mastodon -ENV DEBIAN_FRONTEND="noninteractive" \ - PATH="${PATH}:/opt/ruby/bin:/opt/mastodon/bin" +ARG TARGETPLATFORM -# Ignoring these here since we don't want to pin any versions and the Debian image removes apt-get content after use -# hadolint ignore=DL3008,DL3009 -RUN apt-get update && \ - echo "Etc/UTC" > /etc/localtime && \ - groupadd -g "${GID}" mastodon && \ - useradd -l -u "$UID" -g "${GID}" -m -d /opt/mastodon mastodon && \ - apt-get -y --no-install-recommends install whois \ - wget \ - procps \ - libssl3 \ - libpq5 \ - imagemagick \ - ffmpeg \ - libjemalloc2 \ - libicu72 \ - libidn12 \ - libyaml-0-2 \ - file \ - ca-certificates \ - tzdata \ - libreadline8 \ - tini && \ - ln -s /opt/mastodon /mastodon && \ - corepack enable +# hadolint ignore=DL3008 +RUN \ +# Mount Apt cache and lib directories from Docker buildx caches +--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ +--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ +# Mount Corepack and Yarn caches from Docker buildx caches +--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \ +--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \ +# Apt update install non-dev versions of necessary components + apt-get update; \ + apt-get install -y --no-install-recommends \ + libssl3 \ + libpq5 \ + libicu72 \ + libidn12 \ + libreadline8 \ + libyaml-0-2 \ + ; -# Note: no, cleaning here since Debian does this automatically -# See the file /etc/apt/apt.conf.d/docker-clean within the Docker image's filesystem +# Copy Mastodon sources into final layer +COPY . /opt/mastodon/ -COPY --chown=mastodon:mastodon . /opt/mastodon -COPY --chown=mastodon:mastodon --from=build /opt/mastodon /opt/mastodon +# Copy compiled assets to layer +COPY --from=precompiler /opt/mastodon/public/packs /opt/mastodon/public/packs +COPY --from=precompiler /opt/mastodon/public/assets /opt/mastodon/public/assets +# Copy bundler components to layer +COPY --from=bundler /usr/local/bundle/ /usr/local/bundle/ -ENV RAILS_ENV="production" \ - NODE_ENV="production" \ - RAILS_SERVE_STATIC_FILES="true" \ - BIND="0.0.0.0" \ - MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \ - MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}" +RUN \ +# Precompile bootsnap code for faster Rails startup + bundle exec bootsnap precompile --gemfile app/ lib/; -# Set the run user +RUN \ +# Pre-create and chown system volume to Mastodon user + mkdir -p /opt/mastodon/public/system; \ + chown mastodon:mastodon /opt/mastodon/public/system; + +# Set the running user for resulting container USER mastodon -WORKDIR /opt/mastodon - -# Precompile assets -RUN OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder rails assets:precompile - -# Set the work dir and the container entry point -ENTRYPOINT ["/usr/bin/tini", "--"] -EXPOSE 3000 4000 +# Expose default Puma ports +EXPOSE 3000 +# Set container tini as default entry point +ENTRYPOINT ["/usr/bin/tini", "--"] \ No newline at end of file diff --git a/streaming/.dockerignore b/streaming/.dockerignore new file mode 100644 index 000000000..ea611a7b8 --- /dev/null +++ b/streaming/.dockerignore @@ -0,0 +1,7 @@ +.env +.env.* +.gitignore +node_modules +.DS_Store +*.swp +*~ diff --git a/streaming/Dockerfile b/streaming/Dockerfile new file mode 100644 index 000000000..ee62e9ec7 --- /dev/null +++ b/streaming/Dockerfile @@ -0,0 +1,102 @@ +# syntax=docker/dockerfile:1.4 + +# Please see https://docs.docker.com/engine/reference/builder for information about +# the extended buildx capabilities used in this file. +# Make sure multiarch TARGETPLATFORM is available for interpolation +# See: https://docs.docker.com/build/building/multi-platform/ +ARG TARGETPLATFORM=${TARGETPLATFORM} +ARG BUILDPLATFORM=${BUILDPLATFORM} + +# Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"] +ARG NODE_MAJOR_VERSION="20" +# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"] +ARG DEBIAN_VERSION="bookworm" +# Node image to use for base image based on combined variables (ex: 20-bookworm-slim) +FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim as streaming + +# Timezone used by the Docker container and runtime, change with [--build-arg TZ=Europe/Berlin] +ARG TZ="Etc/UTC" +# Linux UID (user id) for the mastodon user, change with [--build-arg UID=1234] +ARG UID="991" +# Linux GID (group id) for the mastodon user, change with [--build-arg GID=1234] +ARG GID="991" + +# Apply Mastodon build options based on options above +ENV \ +# Apply Mastodon version information + MASTODON_VERSION_PRERELEASE="${MASTODON_VERSION_PRERELEASE}" \ + MASTODON_VERSION_METADATA="${MASTODON_VERSION_METADATA}" \ +# Apply timezone + TZ=${TZ} + +ENV \ +# Configure the IP to bind Mastodon to when serving traffic + BIND="0.0.0.0" \ +# Explicitly set PORT to match the exposed port + PORT=4000 \ +# Use production settings for Yarn, Node and related nodejs based tools + NODE_ENV="production" \ +# Add Ruby and Mastodon installation to the PATH + DEBIAN_FRONTEND="noninteractive" + +# Set default shell used for running commands +SHELL ["/bin/bash", "-o", "pipefail", "-o", "errexit", "-c"] + +ARG TARGETPLATFORM + +RUN echo "Target platform is ${TARGETPLATFORM}" + +RUN \ +# Sets timezone + echo "${TZ}" > /etc/localtime; \ +# Creates mastodon user/group and sets home directory + groupadd -g "${GID}" mastodon; \ + useradd -l -u "${UID}" -g "${GID}" -m -d /opt/mastodon mastodon; \ +# Creates symlink for /mastodon folder + ln -s /opt/mastodon /mastodon; + +# hadolint ignore=DL3008,DL3005 +RUN \ +# Mount Apt cache and lib directories from Docker buildx caches +--mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ +--mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ +# upgrade to check for security updates to Debian image + apt-get update; \ + apt-get dist-upgrade -yq; \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + tzdata \ + ; + +# Set /opt/mastodon as working directory +WORKDIR /opt/mastodon + +# Copy Node package configuration files from build system to container +COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/ +COPY .yarn /opt/mastodon/.yarn +# Copy Streaming source code from build system to container +COPY ./streaming /opt/mastodon/streaming + +RUN \ +# Mount local Corepack and Yarn caches from Docker buildx caches +--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \ +--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \ + # Configure Corepack + rm /usr/local/bin/yarn*; \ + corepack enable; \ + corepack prepare --activate; + +RUN \ +# Mount Corepack and Yarn caches from Docker buildx caches +--mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \ +--mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \ +# Install Node packages + yarn workspaces focus --production @mastodon/streaming; + +# Set the running user for resulting container +USER mastodon +# Expose default Streaming ports +EXPOSE 4000 +# Run streaming when started +CMD [ node ./streaming/index.js ] \ No newline at end of file From 4949b6da585335fc277a28efee1d7a99c1c697ab Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Tue, 28 Nov 2023 15:09:21 +0100 Subject: [PATCH 18/40] Fix streaming eslint configuration (#28055) --- .eslintrc.js | 19 ++++++++----------- package.json | 1 + streaming/.eslintrc.js | 32 ++++++++++++++++++++++++++++++++ streaming/package.json | 8 ++++++-- streaming/tsconfig.json | 11 +++++++++++ yarn.lock | 20 ++++++++++++++++++++ 6 files changed, 78 insertions(+), 13 deletions(-) create mode 100644 streaming/.eslintrc.js create mode 100644 streaming/tsconfig.json diff --git a/.eslintrc.js b/.eslintrc.js index 70506f60c..a9aa86605 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,7 @@ -module.exports = { +// @ts-check +const { defineConfig } = require('eslint-define-config'); + +module.exports = defineConfig({ root: true, extends: [ @@ -193,6 +196,7 @@ module.exports = { 'error', { devDependencies: [ + '.eslintrc.js', 'config/webpack/**', 'app/javascript/mastodon/performance.js', 'app/javascript/mastodon/test_setup.js', @@ -299,6 +303,7 @@ module.exports = { overrides: [ { files: [ + '.eslintrc.js', '*.config.js', '.*rc.js', 'ide-helper.js', @@ -372,14 +377,6 @@ module.exports = { env: { jest: true, }, - }, - { - files: [ - 'streaming/**/*', - ], - rules: { - 'import/no-commonjs': 'off', - }, - }, + } ], -}; +}); diff --git a/package.json b/package.json index 5fe190c69..2f324f77a 100644 --- a/package.json +++ b/package.json @@ -184,6 +184,7 @@ "babel-jest": "^29.5.0", "eslint": "^8.41.0", "eslint-config-prettier": "^9.0.0", + "eslint-define-config": "^2.0.0", "eslint-import-resolver-typescript": "^3.5.5", "eslint-plugin-formatjs": "^4.10.1", "eslint-plugin-import": "~2.29.0", diff --git a/streaming/.eslintrc.js b/streaming/.eslintrc.js new file mode 100644 index 000000000..5e2d233c6 --- /dev/null +++ b/streaming/.eslintrc.js @@ -0,0 +1,32 @@ +// @ts-check +const { defineConfig } = require('eslint-define-config'); + +module.exports = defineConfig({ + extends: ['../.eslintrc.js'], + env: { + browser: false, + }, + parserOptions: { + project: true, + tsconfigRootDir: __dirname, + ecmaFeatures: { + jsx: false, + }, + ecmaVersion: 2021, + }, + rules: { + 'import/no-commonjs': 'off', + 'import/no-extraneous-dependencies': [ + 'error', + { + devDependencies: [ + 'streaming/.eslintrc.js', + ], + optionalDependencies: false, + peerDependencies: false, + includeTypes: true, + packageDir: __dirname, + }, + ], + }, +}); diff --git a/streaming/package.json b/streaming/package.json index 52245aeeb..0cfc5b327 100644 --- a/streaming/package.json +++ b/streaming/package.json @@ -12,7 +12,8 @@ "url": "https://github.com/mastodon/mastodon.git" }, "scripts": { - "start": "node ./index.js" + "start": "node ./index.js", + "check:types": "tsc --noEmit" }, "dependencies": { "dotenv": "^16.0.3", @@ -30,7 +31,10 @@ "@types/express": "^4.17.17", "@types/npmlog": "^7.0.0", "@types/pg": "^8.6.6", - "@types/uuid": "^9.0.0" + "@types/uuid": "^9.0.0", + "@types/ws": "^8.5.9", + "eslint-define-config": "^2.0.0", + "typescript": "^5.0.4" }, "optionalDependencies": { "bufferutil": "^4.0.7", diff --git a/streaming/tsconfig.json b/streaming/tsconfig.json new file mode 100644 index 000000000..032274d85 --- /dev/null +++ b/streaming/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "target": "esnext", + "module": "CommonJS", + "moduleResolution": "node", + "noUnusedParameters": false, + "paths": {} + }, + "include": ["./*.js", "./.eslintrc.js"] +} diff --git a/yarn.lock b/yarn.lock index 98dbfbb68..0dd9a627c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2362,6 +2362,7 @@ __metadata: escape-html: "npm:^1.0.3" eslint: "npm:^8.41.0" eslint-config-prettier: "npm:^9.0.0" + eslint-define-config: "npm:^2.0.0" eslint-import-resolver-typescript: "npm:^3.5.5" eslint-plugin-formatjs: "npm:^4.10.1" eslint-plugin-import: "npm:~2.29.0" @@ -2469,8 +2470,10 @@ __metadata: "@types/npmlog": "npm:^7.0.0" "@types/pg": "npm:^8.6.6" "@types/uuid": "npm:^9.0.0" + "@types/ws": "npm:^8.5.9" bufferutil: "npm:^4.0.7" dotenv: "npm:^16.0.3" + eslint-define-config: "npm:^2.0.0" express: "npm:^4.18.2" ioredis: "npm:^5.3.2" jsdom: "npm:^23.0.0" @@ -2478,6 +2481,7 @@ __metadata: pg: "npm:^8.5.0" pg-connection-string: "npm:^2.6.0" prom-client: "npm:^15.0.0" + typescript: "npm:^5.0.4" utf-8-validate: "npm:^6.0.3" uuid: "npm:^9.0.0" ws: "npm:^8.12.1" @@ -3644,6 +3648,15 @@ __metadata: languageName: node linkType: hard +"@types/ws@npm:^8.5.9": + version: 8.5.9 + resolution: "@types/ws@npm:8.5.9" + dependencies: + "@types/node": "npm:*" + checksum: 678bdd6461c4653f2975c537fb673cb1918c331558e2d2422b69761c9ced67200bb07c664e2593f3864077a891cb7c13ef2a40d303b4aacb06173d095d8aa3ce + languageName: node + linkType: hard + "@types/yargs-parser@npm:*": version: 21.0.2 resolution: "@types/yargs-parser@npm:21.0.2" @@ -7302,6 +7315,13 @@ __metadata: languageName: node linkType: hard +"eslint-define-config@npm:^2.0.0": + version: 2.0.0 + resolution: "eslint-define-config@npm:2.0.0" + checksum: 617c3143bc1ed8df0b20ae632d428d5f241dbb04483631e1410c58fe65ba3e503cf94631c5973115482b58ba464d052422a718c0f4d49182f8d13ffbb36bf1d6 + languageName: node + linkType: hard + "eslint-import-resolver-node@npm:^0.3.9": version: 0.3.9 resolution: "eslint-import-resolver-node@npm:0.3.9" From a4de0e364b9f73299ab121340c0f5ab27125be9e Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Tue, 28 Nov 2023 15:24:41 +0100 Subject: [PATCH 19/40] Refactor streaming to simplify for logging change (#28056) --- streaming/index.js | 104 +++++------------------------------------- streaming/metrics.js | 105 +++++++++++++++++++++++++++++++++++++++++++ streaming/utils.js | 22 +++++++++ 3 files changed, 139 insertions(+), 92 deletions(-) create mode 100644 streaming/metrics.js create mode 100644 streaming/utils.js diff --git a/streaming/index.js b/streaming/index.js index e3b63b53a..fb3e3fb2b 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -12,10 +12,12 @@ const { JSDOM } = require('jsdom'); const log = require('npmlog'); const pg = require('pg'); const dbUrlToConfig = require('pg-connection-string').parse; -const metrics = require('prom-client'); const uuid = require('uuid'); const WebSocket = require('ws'); +const { setupMetrics } = require('./metrics'); +const { isTruthy } = require("./utils"); + const environment = process.env.NODE_ENV || 'development'; // Correctly detect and load .env or .env.production file based on environment: @@ -196,78 +198,15 @@ const startServer = async () => { const redisClient = await createRedisClient(redisConfig); const { redisPrefix } = redisConfig; - // Collect metrics from Node.js - metrics.collectDefaultMetrics(); - - new metrics.Gauge({ - name: 'pg_pool_total_connections', - help: 'The total number of clients existing within the pool', - collect() { - this.set(pgPool.totalCount); - }, - }); - - new metrics.Gauge({ - name: 'pg_pool_idle_connections', - help: 'The number of clients which are not checked out but are currently idle in the pool', - collect() { - this.set(pgPool.idleCount); - }, - }); - - new metrics.Gauge({ - name: 'pg_pool_waiting_queries', - help: 'The number of queued requests waiting on a client when all clients are checked out', - collect() { - this.set(pgPool.waitingCount); - }, - }); - - const connectedClients = new metrics.Gauge({ - name: 'connected_clients', - help: 'The number of clients connected to the streaming server', - labelNames: ['type'], - }); - - const connectedChannels = new metrics.Gauge({ - name: 'connected_channels', - help: 'The number of channels the streaming server is streaming to', - labelNames: [ 'type', 'channel' ] - }); - - const redisSubscriptions = new metrics.Gauge({ - name: 'redis_subscriptions', - help: 'The number of Redis channels the streaming server is subscribed to', - }); - - const redisMessagesReceived = new metrics.Counter({ - name: 'redis_messages_received_total', - help: 'The total number of messages the streaming server has received from redis subscriptions' - }); - - const messagesSent = new metrics.Counter({ - name: 'messages_sent_total', - help: 'The total number of messages the streaming server sent to clients per connection type', - labelNames: [ 'type' ] - }); - - // Prime the gauges so we don't loose metrics between restarts: - redisSubscriptions.set(0); - connectedClients.set({ type: 'websocket' }, 0); - connectedClients.set({ type: 'eventsource' }, 0); - - // For each channel, initialize the gauges at zero; There's only a finite set of channels available - CHANNEL_NAMES.forEach(( channel ) => { - connectedChannels.set({ type: 'websocket', channel }, 0); - connectedChannels.set({ type: 'eventsource', channel }, 0); - }); - - // Prime the counters so that we don't loose metrics between restarts. - // Unfortunately counters don't support the set() API, so instead I'm using - // inc(0) to achieve the same result. - redisMessagesReceived.inc(0); - messagesSent.inc({ type: 'websocket' }, 0); - messagesSent.inc({ type: 'eventsource' }, 0); + const metrics = setupMetrics(CHANNEL_NAMES, pgPool); + // TODO: migrate all metrics to metrics.X.method() instead of just X.method() + const { + connectedClients, + connectedChannels, + redisSubscriptions, + redisMessagesReceived, + messagesSent, + } = metrics; // When checking metrics in the browser, the favicon is requested this // prevents the request from falling through to the API Router, which would @@ -388,25 +327,6 @@ const startServer = async () => { } }; - const FALSE_VALUES = [ - false, - 0, - '0', - 'f', - 'F', - 'false', - 'FALSE', - 'off', - 'OFF', - ]; - - /** - * @param {any} value - * @returns {boolean} - */ - const isTruthy = value => - value && !FALSE_VALUES.includes(value); - /** * @param {any} req * @param {any} res diff --git a/streaming/metrics.js b/streaming/metrics.js new file mode 100644 index 000000000..d05b4c9b1 --- /dev/null +++ b/streaming/metrics.js @@ -0,0 +1,105 @@ +// @ts-check + +const metrics = require('prom-client'); + +/** + * @typedef StreamingMetrics + * @property {metrics.Registry} register + * @property {metrics.Gauge<"type">} connectedClients + * @property {metrics.Gauge<"type" | "channel">} connectedChannels + * @property {metrics.Gauge} redisSubscriptions + * @property {metrics.Counter} redisMessagesReceived + * @property {metrics.Counter<"type">} messagesSent + */ + +/** + * + * @param {string[]} channels + * @param {import('pg').Pool} pgPool + * @returns {StreamingMetrics} + */ +function setupMetrics(channels, pgPool) { + // Collect metrics from Node.js + metrics.collectDefaultMetrics(); + + new metrics.Gauge({ + name: 'pg_pool_total_connections', + help: 'The total number of clients existing within the pool', + collect() { + this.set(pgPool.totalCount); + }, + }); + + new metrics.Gauge({ + name: 'pg_pool_idle_connections', + help: 'The number of clients which are not checked out but are currently idle in the pool', + collect() { + this.set(pgPool.idleCount); + }, + }); + + new metrics.Gauge({ + name: 'pg_pool_waiting_queries', + help: 'The number of queued requests waiting on a client when all clients are checked out', + collect() { + this.set(pgPool.waitingCount); + }, + }); + + const connectedClients = new metrics.Gauge({ + name: 'connected_clients', + help: 'The number of clients connected to the streaming server', + labelNames: ['type'], + }); + + const connectedChannels = new metrics.Gauge({ + name: 'connected_channels', + help: 'The number of channels the streaming server is streaming to', + labelNames: [ 'type', 'channel' ] + }); + + const redisSubscriptions = new metrics.Gauge({ + name: 'redis_subscriptions', + help: 'The number of Redis channels the streaming server is subscribed to', + }); + + const redisMessagesReceived = new metrics.Counter({ + name: 'redis_messages_received_total', + help: 'The total number of messages the streaming server has received from redis subscriptions' + }); + + const messagesSent = new metrics.Counter({ + name: 'messages_sent_total', + help: 'The total number of messages the streaming server sent to clients per connection type', + labelNames: [ 'type' ] + }); + + // Prime the gauges so we don't loose metrics between restarts: + redisSubscriptions.set(0); + connectedClients.set({ type: 'websocket' }, 0); + connectedClients.set({ type: 'eventsource' }, 0); + + // For each channel, initialize the gauges at zero; There's only a finite set of channels available + channels.forEach(( channel ) => { + connectedChannels.set({ type: 'websocket', channel }, 0); + connectedChannels.set({ type: 'eventsource', channel }, 0); + }); + + // Prime the counters so that we don't loose metrics between restarts. + // Unfortunately counters don't support the set() API, so instead I'm using + // inc(0) to achieve the same result. + redisMessagesReceived.inc(0); + messagesSent.inc({ type: 'websocket' }, 0); + messagesSent.inc({ type: 'eventsource' }, 0); + + return { + register: metrics.register, + connectedClients, + connectedChannels, + redisSubscriptions, + redisMessagesReceived, + messagesSent, + }; +} + +exports.setupMetrics = setupMetrics; diff --git a/streaming/utils.js b/streaming/utils.js new file mode 100644 index 000000000..ad8dd4889 --- /dev/null +++ b/streaming/utils.js @@ -0,0 +1,22 @@ +// @ts-check + +const FALSE_VALUES = [ + false, + 0, + '0', + 'f', + 'F', + 'false', + 'FALSE', + 'off', + 'OFF', +]; + +/** + * @param {any} value + * @returns {boolean} + */ +const isTruthy = value => + value && !FALSE_VALUES.includes(value); + +exports.isTruthy = isTruthy; From cdc789424355617c800dc3b589b36fdfdc01b796 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Tue, 28 Nov 2023 15:47:32 +0100 Subject: [PATCH 20/40] Fix devcontainer by not forcing `NODE_ENV` (#28099) --- .devcontainer/post-create.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index 20f3437f4..82a2ccbb6 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -24,4 +24,4 @@ RAILS_ENV=development ./bin/rails db:setup RAILS_ENV=development ./bin/rails assets:precompile # Precompile assets for test -RAILS_ENV=test NODE_ENV=tests ./bin/rails assets:precompile +RAILS_ENV=test ./bin/rails assets:precompile From 1142f4c79e3eaf4450ed727de0f480e300e8b9a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josh=20Goldberg=20=E2=9C=A8?= Date: Tue, 28 Nov 2023 18:47:55 +0100 Subject: [PATCH 21/40] Converted app/javascript/mastodon/utils/ folder to TypeScript (#27895) --- .../{base64-test.js => base64-test.ts} | 0 .../__tests__/{html-test.js => html-test.s} | 0 app/javascript/mastodon/utils/config.js | 10 ----- app/javascript/mastodon/utils/config.ts | 13 ++++++ app/javascript/mastodon/utils/html.js | 6 --- app/javascript/mastodon/utils/html.ts | 9 +++++ .../mastodon/utils/{icons.jsx => icons.tsx} | 14 ++++++- .../mastodon/utils/{log_out.js => log_out.ts} | 0 .../mastodon/utils/notifications.js | 30 -------------- .../mastodon/utils/notifications.ts | 13 ++++++ .../{react_router.jsx => react_router.tsx} | 40 +++++++++++-------- .../utils/{scrollbar.js => scrollbar.ts} | 15 +++---- package.json | 1 + yarn.lock | 8 ++++ 14 files changed, 84 insertions(+), 75 deletions(-) rename app/javascript/mastodon/utils/__tests__/{base64-test.js => base64-test.ts} (100%) rename app/javascript/mastodon/utils/__tests__/{html-test.js => html-test.s} (100%) delete mode 100644 app/javascript/mastodon/utils/config.js create mode 100644 app/javascript/mastodon/utils/config.ts delete mode 100644 app/javascript/mastodon/utils/html.js create mode 100644 app/javascript/mastodon/utils/html.ts rename app/javascript/mastodon/utils/{icons.jsx => icons.tsx} (69%) rename app/javascript/mastodon/utils/{log_out.js => log_out.ts} (100%) delete mode 100644 app/javascript/mastodon/utils/notifications.js create mode 100644 app/javascript/mastodon/utils/notifications.ts rename app/javascript/mastodon/utils/{react_router.jsx => react_router.tsx} (53%) rename app/javascript/mastodon/utils/{scrollbar.js => scrollbar.ts} (70%) diff --git a/app/javascript/mastodon/utils/__tests__/base64-test.js b/app/javascript/mastodon/utils/__tests__/base64-test.ts similarity index 100% rename from app/javascript/mastodon/utils/__tests__/base64-test.js rename to app/javascript/mastodon/utils/__tests__/base64-test.ts diff --git a/app/javascript/mastodon/utils/__tests__/html-test.js b/app/javascript/mastodon/utils/__tests__/html-test.s similarity index 100% rename from app/javascript/mastodon/utils/__tests__/html-test.js rename to app/javascript/mastodon/utils/__tests__/html-test.s diff --git a/app/javascript/mastodon/utils/config.js b/app/javascript/mastodon/utils/config.js deleted file mode 100644 index 932cd0cbf..000000000 --- a/app/javascript/mastodon/utils/config.js +++ /dev/null @@ -1,10 +0,0 @@ -import ready from '../ready'; - -export let assetHost = ''; - -ready(() => { - const cdnHost = document.querySelector('meta[name=cdn-host]'); - if (cdnHost) { - assetHost = cdnHost.content || ''; - } -}); diff --git a/app/javascript/mastodon/utils/config.ts b/app/javascript/mastodon/utils/config.ts new file mode 100644 index 000000000..9222c89d1 --- /dev/null +++ b/app/javascript/mastodon/utils/config.ts @@ -0,0 +1,13 @@ +import ready from '../ready'; + +export let assetHost = ''; + +// eslint-disable-next-line @typescript-eslint/no-floating-promises +ready(() => { + const cdnHost = document.querySelector( + 'meta[name=cdn-host]', + ); + if (cdnHost) { + assetHost = cdnHost.content || ''; + } +}); diff --git a/app/javascript/mastodon/utils/html.js b/app/javascript/mastodon/utils/html.js deleted file mode 100644 index 247e98c88..000000000 --- a/app/javascript/mastodon/utils/html.js +++ /dev/null @@ -1,6 +0,0 @@ -// NB: This function can still return unsafe HTML -export const unescapeHTML = (html) => { - const wrapper = document.createElement('div'); - wrapper.innerHTML = html.replace(//g, '\n').replace(/<\/p>

/g, '\n\n').replace(/<[^>]*>/g, ''); - return wrapper.textContent; -}; diff --git a/app/javascript/mastodon/utils/html.ts b/app/javascript/mastodon/utils/html.ts new file mode 100644 index 000000000..0145a0455 --- /dev/null +++ b/app/javascript/mastodon/utils/html.ts @@ -0,0 +1,9 @@ +// NB: This function can still return unsafe HTML +export const unescapeHTML = (html: string) => { + const wrapper = document.createElement('div'); + wrapper.innerHTML = html + .replace(//g, '\n') + .replace(/<\/p>

/g, '\n\n') + .replace(/<[^>]*>/g, ''); + return wrapper.textContent; +}; diff --git a/app/javascript/mastodon/utils/icons.jsx b/app/javascript/mastodon/utils/icons.tsx similarity index 69% rename from app/javascript/mastodon/utils/icons.jsx rename to app/javascript/mastodon/utils/icons.tsx index be566032e..6e432e32f 100644 --- a/app/javascript/mastodon/utils/icons.jsx +++ b/app/javascript/mastodon/utils/icons.tsx @@ -1,13 +1,23 @@ // Copied from emoji-mart for consistency with emoji picker and since // they don't export the icons in the package export const loupeIcon = ( - + ); export const deleteIcon = ( - + ); diff --git a/app/javascript/mastodon/utils/log_out.js b/app/javascript/mastodon/utils/log_out.ts similarity index 100% rename from app/javascript/mastodon/utils/log_out.js rename to app/javascript/mastodon/utils/log_out.ts diff --git a/app/javascript/mastodon/utils/notifications.js b/app/javascript/mastodon/utils/notifications.js deleted file mode 100644 index 42623ac7c..000000000 --- a/app/javascript/mastodon/utils/notifications.js +++ /dev/null @@ -1,30 +0,0 @@ -// Handles browser quirks, based on -// https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API - -const checkNotificationPromise = () => { - try { - // eslint-disable-next-line promise/valid-params, promise/catch-or-return - Notification.requestPermission().then(); - } catch(e) { - return false; - } - - return true; -}; - -const handlePermission = (permission, callback) => { - // Whatever the user answers, we make sure Chrome stores the information - if(!('permission' in Notification)) { - Notification.permission = permission; - } - - callback(Notification.permission); -}; - -export const requestNotificationPermission = (callback) => { - if (checkNotificationPromise()) { - Notification.requestPermission().then((permission) => handlePermission(permission, callback)).catch(console.warn); - } else { - Notification.requestPermission((permission) => handlePermission(permission, callback)); - } -}; diff --git a/app/javascript/mastodon/utils/notifications.ts b/app/javascript/mastodon/utils/notifications.ts new file mode 100644 index 000000000..08f677f8f --- /dev/null +++ b/app/javascript/mastodon/utils/notifications.ts @@ -0,0 +1,13 @@ +/** + * Tries Notification.requestPermission, console warning instead of rejecting on error. + * @param callback Runs with the permission result on completion. + */ +export const requestNotificationPermission = async ( + callback: NotificationPermissionCallback, +) => { + try { + callback(await Notification.requestPermission()); + } catch (error) { + console.warn(error); + } +}; diff --git a/app/javascript/mastodon/utils/react_router.jsx b/app/javascript/mastodon/utils/react_router.tsx similarity index 53% rename from app/javascript/mastodon/utils/react_router.jsx rename to app/javascript/mastodon/utils/react_router.tsx index fa8f0db2b..0682fee55 100644 --- a/app/javascript/mastodon/utils/react_router.jsx +++ b/app/javascript/mastodon/utils/react_router.tsx @@ -1,8 +1,8 @@ -import PropTypes from "prop-types"; +import PropTypes from 'prop-types'; -import { __RouterContext } from "react-router"; +import { __RouterContext } from 'react-router'; -import hoistStatics from "hoist-non-react-statics"; +import hoistStatics from 'hoist-non-react-statics'; export const WithRouterPropTypes = { match: PropTypes.object.isRequired, @@ -16,31 +16,37 @@ export const WithOptionalRouterPropTypes = { history: PropTypes.object, }; +export interface OptionalRouterProps { + ref: unknown; + wrappedComponentRef: unknown; +} + // This is copied from https://github.com/remix-run/react-router/blob/v5.3.4/packages/react-router/modules/withRouter.js // but does not fail if called outside of a React Router context -export function withOptionalRouter(Component) { - const displayName = `withRouter(${Component.displayName || Component.name})`; - const C = props => { +export function withOptionalRouter< + ComponentType extends React.ComponentType, +>(Component: ComponentType) { + const displayName = `withRouter(${Component.displayName ?? Component.name})`; + const C = (props: React.ComponentProps) => { const { wrappedComponentRef, ...remainingProps } = props; return ( <__RouterContext.Consumer> - {context => { - if(context) + {(context) => { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (context) { return ( + // @ts-expect-error - Dynamic covariant generic components are tough to type. ); - else - return ( - - ); + } else { + // @ts-expect-error - Dynamic covariant generic components are tough to type. + return ; + } }} ); @@ -53,8 +59,8 @@ export function withOptionalRouter(Component) { wrappedComponentRef: PropTypes.oneOfType([ PropTypes.string, PropTypes.func, - PropTypes.object - ]) + PropTypes.object, + ]), }; return hoistStatics(C, Component); diff --git a/app/javascript/mastodon/utils/scrollbar.js b/app/javascript/mastodon/utils/scrollbar.ts similarity index 70% rename from app/javascript/mastodon/utils/scrollbar.js rename to app/javascript/mastodon/utils/scrollbar.ts index ca87dd76f..d505df124 100644 --- a/app/javascript/mastodon/utils/scrollbar.js +++ b/app/javascript/mastodon/utils/scrollbar.ts @@ -1,11 +1,7 @@ import { isMobile } from '../is_mobile'; -/** @type {number | null} */ -let cachedScrollbarWidth = null; +let cachedScrollbarWidth: number | null = null; -/** - * @returns {number} - */ const getActualScrollbarWidth = () => { const outer = document.createElement('div'); outer.style.visibility = 'hidden'; @@ -16,20 +12,19 @@ const getActualScrollbarWidth = () => { outer.appendChild(inner); const scrollbarWidth = outer.offsetWidth - inner.offsetWidth; - outer.parentNode.removeChild(outer); + outer.remove(); return scrollbarWidth; }; -/** - * @returns {number} - */ export const getScrollbarWidth = () => { if (cachedScrollbarWidth !== null) { return cachedScrollbarWidth; } - const scrollbarWidth = isMobile(window.innerWidth) ? 0 : getActualScrollbarWidth(); + const scrollbarWidth = isMobile(window.innerWidth) + ? 0 + : getActualScrollbarWidth(); cachedScrollbarWidth = scrollbarWidth; return scrollbarWidth; diff --git a/package.json b/package.json index 2f324f77a..543af8a4b 100644 --- a/package.json +++ b/package.json @@ -161,6 +161,7 @@ "@types/object-assign": "^4.0.30", "@types/prop-types": "^15.7.5", "@types/punycode": "^2.1.0", + "@types/rails__ujs": "^6.0.4", "@types/react": "^18.2.7", "@types/react-dom": "^18.2.4", "@types/react-helmet": "^6.1.6", diff --git a/yarn.lock b/yarn.lock index 0dd9a627c..11c2724d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2317,6 +2317,7 @@ __metadata: "@types/object-assign": "npm:^4.0.30" "@types/prop-types": "npm:^15.7.5" "@types/punycode": "npm:^2.1.0" + "@types/rails__ujs": "npm:^6.0.4" "@types/react": "npm:^18.2.7" "@types/react-dom": "npm:^18.2.4" "@types/react-helmet": "npm:^6.1.6" @@ -3349,6 +3350,13 @@ __metadata: languageName: node linkType: hard +"@types/rails__ujs@npm:^6.0.4": + version: 6.0.4 + resolution: "@types/rails__ujs@npm:6.0.4" + checksum: 7477cb03a0e1339b9cd5c8ac4a197a153e2ff48742b2f527c5a39dcdf80f01493011e368483290d3717662c63066fada3ab203a335804cbb3573cf575f37007e + languageName: node + linkType: hard + "@types/range-parser@npm:*": version: 1.2.7 resolution: "@types/range-parser@npm:1.2.7" From 3a7f10c3f10e6a7ab154030a2abf5a1a68c1b8f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josh=20Goldberg=20=E2=9C=A8?= Date: Tue, 28 Nov 2023 19:20:10 +0100 Subject: [PATCH 22/40] Converted hashtag.jsx to TypeScript (#27872) Co-authored-by: Claire Co-authored-by: Renaud Chaput --- .eslintrc.js | 3 +- .../mastodon/components/admin/Trends.jsx | 2 +- .../mastodon/components/hashtag.jsx | 120 --------------- .../mastodon/components/hashtag.tsx | 145 ++++++++++++++++++ .../account/components/featured_tags.jsx | 2 +- .../mastodon/features/followed_tags/index.jsx | 2 +- 6 files changed, 149 insertions(+), 125 deletions(-) delete mode 100644 app/javascript/mastodon/components/hashtag.jsx create mode 100644 app/javascript/mastodon/components/hashtag.tsx diff --git a/.eslintrc.js b/.eslintrc.js index a9aa86605..176879034 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -284,7 +284,6 @@ module.exports = defineConfig({ 'formatjs/no-id': 'off', // IDs are used for translation keys 'formatjs/no-invalid-icu': 'error', 'formatjs/no-literal-string-in-jsx': 'off', // Should be looked at, but mainly flagging punctuation outside of strings - 'formatjs/no-multiple-plurals': 'off', // Only used by hashtag.jsx 'formatjs/no-multiple-whitespaces': 'error', 'formatjs/no-offset': 'error', 'formatjs/no-useless-message': 'error', @@ -354,7 +353,7 @@ module.exports = defineConfig({ '@typescript-eslint/consistent-type-definitions': ['warn', 'interface'], '@typescript-eslint/consistent-type-exports': 'error', '@typescript-eslint/consistent-type-imports': 'error', - "@typescript-eslint/prefer-nullish-coalescing": ['error', {ignorePrimitives: {boolean: true}}], + "@typescript-eslint/prefer-nullish-coalescing": ['error', { ignorePrimitives: { boolean: true } }], 'jsdoc/require-jsdoc': 'off', diff --git a/app/javascript/mastodon/components/admin/Trends.jsx b/app/javascript/mastodon/components/admin/Trends.jsx index 49976276e..c69b4a8cb 100644 --- a/app/javascript/mastodon/components/admin/Trends.jsx +++ b/app/javascript/mastodon/components/admin/Trends.jsx @@ -6,7 +6,7 @@ import { FormattedMessage } from 'react-intl'; import classNames from 'classnames'; import api from 'mastodon/api'; -import Hashtag from 'mastodon/components/hashtag'; +import { Hashtag } from 'mastodon/components/hashtag'; export default class Trends extends PureComponent { diff --git a/app/javascript/mastodon/components/hashtag.jsx b/app/javascript/mastodon/components/hashtag.jsx deleted file mode 100644 index 14bb4ddc6..000000000 --- a/app/javascript/mastodon/components/hashtag.jsx +++ /dev/null @@ -1,120 +0,0 @@ -// @ts-check -import PropTypes from 'prop-types'; -import { Component } from 'react'; - -import { FormattedMessage } from 'react-intl'; - -import classNames from 'classnames'; -import { Link } from 'react-router-dom'; - -import ImmutablePropTypes from 'react-immutable-proptypes'; - -import { Sparklines, SparklinesCurve } from 'react-sparklines'; - -import { ShortNumber } from 'mastodon/components/short_number'; -import { Skeleton } from 'mastodon/components/skeleton'; - -class SilentErrorBoundary extends Component { - - static propTypes = { - children: PropTypes.node, - }; - - state = { - error: false, - }; - - componentDidCatch() { - this.setState({ error: true }); - } - - render() { - if (this.state.error) { - return null; - } - - return this.props.children; - } - -} - -/** - * Used to render counter of how much people are talking about hashtag - * @type {(displayNumber: JSX.Element, pluralReady: number) => JSX.Element} - */ -export const accountsCountRenderer = (displayNumber, pluralReady) => ( - {displayNumber}, - days: 2, - }} - /> -); - -// @ts-expect-error -export const ImmutableHashtag = ({ hashtag }) => ( - day.get('uses')).toArray()} - /> -); - -ImmutableHashtag.propTypes = { - hashtag: ImmutablePropTypes.map.isRequired, -}; - -// @ts-expect-error -const Hashtag = ({ name, to, people, uses, history, className, description, withGraph }) => ( -

-
- - {name ? <>#{name} : } - - - {description ? ( - {description} - ) : ( - typeof people !== 'undefined' ? : - )} -
- - {typeof uses !== 'undefined' && ( -
- -
- )} - - {withGraph && ( -
- - 0)}> - - - -
- )} -
-); - -Hashtag.propTypes = { - name: PropTypes.string, - to: PropTypes.string, - people: PropTypes.number, - description: PropTypes.node, - uses: PropTypes.number, - history: PropTypes.arrayOf(PropTypes.number), - className: PropTypes.string, - withGraph: PropTypes.bool, -}; - -Hashtag.defaultProps = { - withGraph: true, -}; - -export default Hashtag; diff --git a/app/javascript/mastodon/components/hashtag.tsx b/app/javascript/mastodon/components/hashtag.tsx new file mode 100644 index 000000000..8963e4a40 --- /dev/null +++ b/app/javascript/mastodon/components/hashtag.tsx @@ -0,0 +1,145 @@ +import type { JSX } from 'react'; +import { Component } from 'react'; + +import { FormattedMessage } from 'react-intl'; + +import classNames from 'classnames'; +import { Link } from 'react-router-dom'; + +import type Immutable from 'immutable'; + +import { Sparklines, SparklinesCurve } from 'react-sparklines'; + +import { ShortNumber } from 'mastodon/components/short_number'; +import { Skeleton } from 'mastodon/components/skeleton'; + +interface SilentErrorBoundaryProps { + children: React.ReactNode; +} + +class SilentErrorBoundary extends Component { + state = { + error: false, + }; + + componentDidCatch() { + this.setState({ error: true }); + } + + render() { + if (this.state.error) { + return null; + } + + return this.props.children; + } +} + +/** + * Used to render counter of how much people are talking about hashtag + * @param displayNumber Counter number to display + * @param pluralReady Whether the count is plural + * @returns Formatted counter of how much people are talking about hashtag + */ +export const accountsCountRenderer = ( + displayNumber: JSX.Element, + pluralReady: number, +) => ( + {displayNumber}, + days: 2, + }} + /> +); + +interface ImmutableHashtagProps { + hashtag: Immutable.Map; +} + +export const ImmutableHashtag = ({ hashtag }: ImmutableHashtagProps) => ( + + > + ) + .reverse() + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + .map((day) => day.get('uses')!) + .toArray()} + /> +); + +export interface HashtagProps { + className?: string; + description?: React.ReactNode; + history?: number[]; + name: string; + people: number; + to: string; + uses?: number; + withGraph?: boolean; +} + +export const Hashtag: React.FC = ({ + name, + to, + people, + uses, + history, + className, + description, + withGraph = true, +}) => ( +
+
+ + {name ? ( + <> + #{name} + + ) : ( + + )} + + + {description ? ( + {description} + ) : typeof people !== 'undefined' ? ( + + ) : ( + + )} +
+ + {typeof uses !== 'undefined' && ( +
+ +
+ )} + + {withGraph && ( +
+ + 0)} + > + + + +
+ )} +
+); diff --git a/app/javascript/mastodon/features/account/components/featured_tags.jsx b/app/javascript/mastodon/features/account/components/featured_tags.jsx index 4d7dd8656..56a9efac0 100644 --- a/app/javascript/mastodon/features/account/components/featured_tags.jsx +++ b/app/javascript/mastodon/features/account/components/featured_tags.jsx @@ -5,7 +5,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import Hashtag from 'mastodon/components/hashtag'; +import { Hashtag } from 'mastodon/components/hashtag'; const messages = defineMessages({ lastStatusAt: { id: 'account.featured_tags.last_status_at', defaultMessage: 'Last post on {date}' }, diff --git a/app/javascript/mastodon/features/followed_tags/index.jsx b/app/javascript/mastodon/features/followed_tags/index.jsx index 7042f2438..dec53f012 100644 --- a/app/javascript/mastodon/features/followed_tags/index.jsx +++ b/app/javascript/mastodon/features/followed_tags/index.jsx @@ -13,7 +13,7 @@ import { debounce } from 'lodash'; import { expandFollowedHashtags, fetchFollowedHashtags } from 'mastodon/actions/tags'; import ColumnHeader from 'mastodon/components/column_header'; -import Hashtag from 'mastodon/components/hashtag'; +import { Hashtag } from 'mastodon/components/hashtag'; import ScrollableList from 'mastodon/components/scrollable_list'; import Column from 'mastodon/features/ui/components/column'; From b45fe15c06c020ee9e5303e4640f12b1db20ff29 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 28 Nov 2023 13:36:16 -0500 Subject: [PATCH 23/40] Update temple to version 0.10.3 (#28086) --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 972adae38..793869157 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -755,7 +755,7 @@ GEM attr_required (>= 0.0.5) httpclient (>= 2.4) sysexits (1.2.0) - temple (0.10.2) + temple (0.10.3) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) terrapin (0.6.0) From b9492d84a0f367ec6eb4cb609958fab5f850608e Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 28 Nov 2023 13:36:21 -0500 Subject: [PATCH 24/40] Update `bcrypt` to version 3.1.20 (#28084) --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 793869157..7440f1b32 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -156,7 +156,7 @@ GEM nokogiri (~> 1, >= 1.10.8) base64 (0.2.0) bcp47_spec (0.2.1) - bcrypt (3.1.19) + bcrypt (3.1.20) better_errors (2.10.1) erubi (>= 1.0.0) rack (>= 0.9.0) From 6b46bf99539112cb119958a5d79ffa46fe9c0a9c Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 28 Nov 2023 13:37:54 -0500 Subject: [PATCH 25/40] Handle scenario when webfinger response `subject` is missing host value (#28088) --- app/services/resolve_account_service.rb | 4 +++- spec/services/resolve_account_service_spec.rb | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb index 6204fefd6..078a0423f 100644 --- a/app/services/resolve_account_service.rb +++ b/app/services/resolve_account_service.rb @@ -100,7 +100,9 @@ class ResolveAccountService < BaseService end def split_acct(acct) - acct.delete_prefix('acct:').split('@') + acct.delete_prefix('acct:').split('@').tap do |parts| + raise Webfinger::Error, 'Webfinger response is missing user or host value' unless parts.size == 2 + end end def fetch_account! diff --git a/spec/services/resolve_account_service_spec.rb b/spec/services/resolve_account_service_spec.rb index f446d0ca6..9f5fdca29 100644 --- a/spec/services/resolve_account_service_spec.rb +++ b/spec/services/resolve_account_service_spec.rb @@ -144,6 +144,19 @@ RSpec.describe ResolveAccountService, type: :service do end end + context 'with webfinger response subject missing a host value' do + let(:body) { Oj.dump({ subject: 'user@' }) } + let(:url) { 'https://host.example/.well-known/webfinger?resource=acct:user@host.example' } + + before do + stub_request(:get, url).to_return(status: 200, body: body) + end + + it 'returns nil with incomplete subject in response' do + expect(subject.call('user@host.example')).to be_nil + end + end + context 'with an ActivityPub account' do it 'returns new remote account' do account = subject.call('foo@ap.example.com') From 7a3b41eb54f24545854da6bb364f240fceff3c2f Mon Sep 17 00:00:00 2001 From: Michael Stanclift Date: Tue, 28 Nov 2023 14:44:04 -0600 Subject: [PATCH 26/40] Fix incorrect apt-get install block in Dockerfile (#28112) --- Dockerfile | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/Dockerfile b/Dockerfile index 623a4d4ea..73267f380 100644 --- a/Dockerfile +++ b/Dockerfile @@ -177,29 +177,7 @@ FROM build as yarn ARG TARGETPLATFORM # Copy Node package configuration files into working directory -RUN apt-get update && \ - apt-get -yq dist-upgrade && \ - apt-get install -y --no-install-recommends build-essential \ - git \ - libicu-dev \ - libidn-dev \ - libpq-dev \ - libjemalloc-dev \ - zlib1g-dev \ - libgdbm-dev \ - libgmp-dev \ - libssl-dev \ - libyaml-dev \ - ca-certificates \ - libreadline8 \ - python3 \ - shared-mime-info && \ - bundle config set --local deployment 'true' && \ - bundle config set --local without 'development test' && \ - bundle config set silence_root_warning true && \ - corepack enable - -COPY Gemfile* package.json yarn.lock .yarnrc.yml /opt/mastodon/ +COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/ COPY streaming/package.json /opt/mastodon/streaming/ COPY .yarn /opt/mastodon/.yarn From c40cfc5d0905651dcf3c1e5fa04c0bd06da6e9d1 Mon Sep 17 00:00:00 2001 From: Michael Stanclift Date: Tue, 28 Nov 2023 16:23:44 -0600 Subject: [PATCH 27/40] Fix apt cache not being properly utilized in Dockerfile (#28115) --- Dockerfile | 4 ++-- streaming/Dockerfile | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 73267f380..ed5ebf1e0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -70,6 +70,8 @@ ARG TARGETPLATFORM RUN echo "Target platform is $TARGETPLATFORM" RUN \ +# Remove automatic apt cache Docker cleanup scripts + rm -f /etc/apt/apt.conf.d/docker-clean; \ # Sets timezone echo "${TZ}" > /etc/localtime; \ # Creates mastodon user/group and sets home directory @@ -127,7 +129,6 @@ RUN \ --mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ --mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ # Install build tools and bundler dependencies from APT - apt-get update; \ apt-get install -y --no-install-recommends \ g++ \ gcc \ @@ -221,7 +222,6 @@ RUN \ --mount=type=cache,id=corepack-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/corepack,sharing=locked \ --mount=type=cache,id=yarn-cache-${TARGETPLATFORM},target=/usr/local/share/.cache/yarn,sharing=locked \ # Apt update install non-dev versions of necessary components - apt-get update; \ apt-get install -y --no-install-recommends \ libssl3 \ libpq5 \ diff --git a/streaming/Dockerfile b/streaming/Dockerfile index ee62e9ec7..6e0a84771 100644 --- a/streaming/Dockerfile +++ b/streaming/Dockerfile @@ -47,6 +47,8 @@ ARG TARGETPLATFORM RUN echo "Target platform is ${TARGETPLATFORM}" RUN \ +# Remove automatic apt cache Docker cleanup scripts + rm -f /etc/apt/apt.conf.d/docker-clean; \ # Sets timezone echo "${TZ}" > /etc/localtime; \ # Creates mastodon user/group and sets home directory @@ -60,7 +62,7 @@ RUN \ # Mount Apt cache and lib directories from Docker buildx caches --mount=type=cache,id=apt-cache-${TARGETPLATFORM},target=/var/cache/apt,sharing=locked \ --mount=type=cache,id=apt-lib-${TARGETPLATFORM},target=/var/lib/apt,sharing=locked \ -# upgrade to check for security updates to Debian image +# Upgrade to check for security updates to Debian image apt-get update; \ apt-get dist-upgrade -yq; \ apt-get install -y --no-install-recommends \ From 603b245cc62acba0d8f71ad4c31d2f1676e90190 Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Wed, 29 Nov 2023 09:34:36 +0100 Subject: [PATCH 28/40] Add VAPID public key to instance serializer (#28006) Co-authored-by: Renaud Chaput --- app/serializers/rest/application_serializer.rb | 5 ++++- app/serializers/rest/instance_serializer.rb | 4 ++++ spec/serializers/rest/instance_serializer_spec.rb | 6 ++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/serializers/rest/application_serializer.rb b/app/serializers/rest/application_serializer.rb index e4806a3c9..635508a17 100644 --- a/app/serializers/rest/application_serializer.rb +++ b/app/serializers/rest/application_serializer.rb @@ -2,7 +2,10 @@ class REST::ApplicationSerializer < ActiveModel::Serializer attributes :id, :name, :website, :scopes, :redirect_uri, - :client_id, :client_secret, :vapid_key + :client_id, :client_secret + + # NOTE: Deprecated in 4.3.0, needs to be removed in 5.0.0 + attribute :vapid_key def id object.id.to_s diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb index 14aeda946..d7ed381e1 100644 --- a/app/serializers/rest/instance_serializer.rb +++ b/app/serializers/rest/instance_serializer.rb @@ -48,6 +48,10 @@ class REST::InstanceSerializer < ActiveModel::Serializer status: object.status_page_url, }, + vapid: { + public_key: Rails.configuration.x.vapid_public_key, + }, + accounts: { max_featured_tags: FeaturedTag::LIMIT, }, diff --git a/spec/serializers/rest/instance_serializer_spec.rb b/spec/serializers/rest/instance_serializer_spec.rb index 8ac32f224..d8f2536d2 100644 --- a/spec/serializers/rest/instance_serializer_spec.rb +++ b/spec/serializers/rest/instance_serializer_spec.rb @@ -10,5 +10,11 @@ describe REST::InstanceSerializer do it 'returns recent usage data' do expect(serialization['usage']).to eq({ 'users' => { 'active_month' => 0 } }) end + + it 'returns the VAPID public key' do + expect(serialization['configuration']['vapid']).to eq({ + 'public_key' => Rails.configuration.x.vapid_public_key, + }) + end end end From 3e1e41054ba40294ecf70c1216759fc378f46ee0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 29 Nov 2023 10:00:07 +0100 Subject: [PATCH 29/40] chore(deps): update dependency pghero to v3.4.0 (#28117) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 7440f1b32..40f85c7d4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -522,7 +522,7 @@ GEM pastel (0.8.0) tty-color (~> 0.5) pg (1.5.4) - pghero (3.3.4) + pghero (3.4.0) activerecord (>= 6) posix-spawn (0.3.15) premailer (1.21.0) From 186895fc887d8729185fc51f994dca93a30592b1 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 29 Nov 2023 05:00:52 -0500 Subject: [PATCH 30/40] Refactor, lint fix, and bug fix on admin/roles/form partial (#27558) --- app/helpers/admin/roles_helper.rb | 24 ++++++++++++++++++++++++ app/models/user_role.rb | 6 +++--- app/views/admin/roles/_form.html.haml | 2 +- 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 app/helpers/admin/roles_helper.rb diff --git a/app/helpers/admin/roles_helper.rb b/app/helpers/admin/roles_helper.rb new file mode 100644 index 000000000..7b4702e26 --- /dev/null +++ b/app/helpers/admin/roles_helper.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module Admin + module RolesHelper + def privilege_label(privilege) + safe_join( + [ + t("admin.roles.privileges.#{privilege}"), + content_tag(:span, t("admin.roles.privileges.#{privilege}_description"), class: 'hint'), + ] + ) + end + + def disable_permissions?(permissions) + permissions.filter { |privilege| role_flag_value(privilege).zero? } + end + + private + + def role_flag_value(privilege) + UserRole::FLAGS[privilege] & current_user.role.computed_permissions + end + end +end diff --git a/app/models/user_role.rb b/app/models/user_role.rb index 5472646c6..89354da54 100644 --- a/app/models/user_role.rb +++ b/app/models/user_role.rb @@ -49,7 +49,7 @@ class UserRole < ApplicationRecord invite_users ).freeze, - moderation: %w( + moderation: %i( view_dashboard view_audit_log manage_users @@ -63,7 +63,7 @@ class UserRole < ApplicationRecord manage_invites ).freeze, - administration: %w( + administration: %i( manage_settings manage_rules manage_roles @@ -72,7 +72,7 @@ class UserRole < ApplicationRecord manage_announcements ).freeze, - devops: %w( + devops: %i( view_devops ).freeze, diff --git a/app/views/admin/roles/_form.html.haml b/app/views/admin/roles/_form.html.haml index 240033214..46a1c537a 100644 --- a/app/views/admin/roles/_form.html.haml +++ b/app/views/admin/roles/_form.html.haml @@ -31,6 +31,6 @@ - (form.object.everyone? ? UserRole::Flags::CATEGORIES.slice(:invites) : UserRole::Flags::CATEGORIES).each do |category, permissions| %h4= t(category, scope: 'admin.roles.categories') - = form.input :permissions_as_keys, collection: permissions, wrapper: :with_block_label, include_blank: false, label_method: ->(privilege) { safe_join([t("admin.roles.privileges.#{privilege}"), content_tag(:span, t("admin.roles.privileges.#{privilege}_description"), class: 'hint')]) }, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', label: false, hint: false, disabled: permissions.filter { |privilege| UserRole::FLAGS[privilege] & current_user.role.computed_permissions == 0 } + = form.input :permissions_as_keys, collection: permissions, wrapper: :with_block_label, include_blank: false, label_method: ->(privilege) { privilege_label(privilege) }, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', label: false, hint: false, disabled: disable_permissions?(permissions) %hr.spacer/ From 9b47c5d53c24cd5bd9ee84169f4f05bb81f3ed88 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 29 Nov 2023 05:02:59 -0500 Subject: [PATCH 31/40] Extract helper methods for labels from filters/_filter_fields (#27574) --- app/helpers/filters_helper.rb | 12 ++++++++++++ app/views/filters/_filter_fields.html.haml | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 app/helpers/filters_helper.rb diff --git a/app/helpers/filters_helper.rb b/app/helpers/filters_helper.rb new file mode 100644 index 000000000..22a1c172d --- /dev/null +++ b/app/helpers/filters_helper.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module FiltersHelper + def filter_action_label(action) + safe_join( + [ + t("simple_form.labels.filters.actions.#{action}"), + content_tag(:span, t("simple_form.hints.filters.actions.#{action}"), class: 'hint'), + ] + ) + end +end diff --git a/app/views/filters/_filter_fields.html.haml b/app/views/filters/_filter_fields.html.haml index 0690e8dd5..a3260816e 100644 --- a/app/views/filters/_filter_fields.html.haml +++ b/app/views/filters/_filter_fields.html.haml @@ -10,7 +10,7 @@ %hr.spacer/ .fields-group - = f.input :filter_action, as: :radio_buttons, collection: %i(warn hide), include_blank: false, wrapper: :with_block_label, label_method: ->(action) { safe_join([t("simple_form.labels.filters.actions.#{action}"), content_tag(:span, t("simple_form.hints.filters.actions.#{action}"), class: 'hint')]) }, hint: t('simple_form.hints.filters.action'), required: true + = f.input :filter_action, as: :radio_buttons, collection: %i(warn hide), include_blank: false, wrapper: :with_block_label, label_method: ->(action) { filter_action_label(action) }, hint: t('simple_form.hints.filters.action'), required: true %hr.spacer/ From 72b7cd349ccffb557d2c55f4ba76b525ff47ef9e Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 29 Nov 2023 05:06:19 -0500 Subject: [PATCH 32/40] Extract helper methods for form label in admin/ area views (#27575) --- app/helpers/admin/account_actions_helper.rb | 12 ++++++++++++ app/helpers/admin/accounts_helper.rb | 19 +++++++++++++++++++ app/helpers/admin/ip_blocks_helper.rb | 12 ++++++++++++ .../admin/settings/discovery_helper.rb | 15 +++++++++++++++ app/views/admin/account_actions/new.html.haml | 2 +- app/views/admin/accounts/index.html.haml | 2 +- app/views/admin/ip_blocks/new.html.haml | 2 +- .../admin/settings/discovery/show.html.haml | 2 +- 8 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 app/helpers/admin/account_actions_helper.rb create mode 100644 app/helpers/admin/accounts_helper.rb create mode 100644 app/helpers/admin/ip_blocks_helper.rb create mode 100644 app/helpers/admin/settings/discovery_helper.rb diff --git a/app/helpers/admin/account_actions_helper.rb b/app/helpers/admin/account_actions_helper.rb new file mode 100644 index 000000000..e132680a6 --- /dev/null +++ b/app/helpers/admin/account_actions_helper.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Admin::AccountActionsHelper + def account_action_type_label(type) + safe_join( + [ + I18n.t("simple_form.labels.admin_account_action.types.#{type}"), + content_tag(:span, I18n.t("simple_form.hints.admin_account_action.types.#{type}"), class: 'hint'), + ] + ) + end +end diff --git a/app/helpers/admin/accounts_helper.rb b/app/helpers/admin/accounts_helper.rb new file mode 100644 index 000000000..a936797e8 --- /dev/null +++ b/app/helpers/admin/accounts_helper.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Admin::AccountsHelper + def admin_accounts_moderation_options + [ + [t('admin.accounts.moderation.active'), 'active'], + [t('admin.accounts.moderation.silenced'), 'silenced'], + [t('admin.accounts.moderation.disabled'), 'disabled'], + [t('admin.accounts.moderation.suspended'), 'suspended'], + [safe_join([t('admin.accounts.moderation.pending'), "(#{pending_user_count_label})"], ' '), 'pending'], + ] + end + + private + + def pending_user_count_label + number_with_delimiter User.pending.count + end +end diff --git a/app/helpers/admin/ip_blocks_helper.rb b/app/helpers/admin/ip_blocks_helper.rb new file mode 100644 index 000000000..4aae3aae7 --- /dev/null +++ b/app/helpers/admin/ip_blocks_helper.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Admin::IpBlocksHelper + def ip_blocks_severity_label(severity) + safe_join( + [ + I18n.t("simple_form.labels.ip_block.severities.#{severity}"), + content_tag(:span, I18n.t("simple_form.hints.ip_block.severities.#{severity}"), class: 'hint'), + ] + ) + end +end diff --git a/app/helpers/admin/settings/discovery_helper.rb b/app/helpers/admin/settings/discovery_helper.rb new file mode 100644 index 000000000..0aa4d4368 --- /dev/null +++ b/app/helpers/admin/settings/discovery_helper.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Admin::Settings::DiscoveryHelper + def discovery_warning_hint_text + authorized_fetch_overridden? ? t('admin.settings.security.authorized_fetch_overridden_hint') : nil + end + + def discovery_hint_text + t('admin.settings.security.authorized_fetch_hint') + end + + def discovery_recommended_value + authorized_fetch_overridden? ? :overridden : nil + end +end diff --git a/app/views/admin/account_actions/new.html.haml b/app/views/admin/account_actions/new.html.haml index 2a0cae15a..4cb4401c7 100644 --- a/app/views/admin/account_actions/new.html.haml +++ b/app/views/admin/account_actions/new.html.haml @@ -5,7 +5,7 @@ = f.input :report_id, as: :hidden .fields-group - = f.input :type, as: :radio_buttons, collection: Admin::AccountAction.types_for_account(@account), include_blank: false, wrapper: :with_block_label, label_method: ->(type) { safe_join([I18n.t("simple_form.labels.admin_account_action.types.#{type}"), content_tag(:span, I18n.t("simple_form.hints.admin_account_action.types.#{type}"), class: 'hint')]) }, hint: t('simple_form.hints.admin_account_action.type_html', acct: @account.pretty_acct) + = f.input :type, as: :radio_buttons, collection: Admin::AccountAction.types_for_account(@account), include_blank: false, wrapper: :with_block_label, label_method: ->(type) { account_action_type_label(type) }, hint: t('simple_form.hints.admin_account_action.type_html', acct: @account.pretty_acct) - if @account.local? %hr.spacer/ diff --git a/app/views/admin/accounts/index.html.haml b/app/views/admin/accounts/index.html.haml index 9cec8d632..835444189 100644 --- a/app/views/admin/accounts/index.html.haml +++ b/app/views/admin/accounts/index.html.haml @@ -10,7 +10,7 @@ .filter-subset.filter-subset--with-select %strong= t('admin.accounts.moderation.title') .input.select.optional - = select_tag :status, options_for_select([[t('admin.accounts.moderation.active'), 'active'], [t('admin.accounts.moderation.silenced'), 'silenced'], [t('admin.accounts.moderation.disabled'), 'disabled'], [t('admin.accounts.moderation.suspended'), 'suspended'], [safe_join([t('admin.accounts.moderation.pending'), "(#{number_with_delimiter(User.pending.count)})"], ' '), 'pending']], params[:status]), prompt: I18n.t('generic.all') + = select_tag :status, options_for_select(admin_accounts_moderation_options, params[:status]), prompt: I18n.t('generic.all') .filter-subset.filter-subset--with-select %strong= t('admin.accounts.role') .input.select.optional diff --git a/app/views/admin/ip_blocks/new.html.haml b/app/views/admin/ip_blocks/new.html.haml index 405c73c90..ecaf04315 100644 --- a/app/views/admin/ip_blocks/new.html.haml +++ b/app/views/admin/ip_blocks/new.html.haml @@ -11,7 +11,7 @@ = f.input :expires_in, wrapper: :with_block_label, collection: [1.day, 2.weeks, 1.month, 6.months, 1.year, 3.years].map(&:to_i), label_method: ->(i) { I18n.t("admin.ip_blocks.expires_in.#{i}") }, prompt: I18n.t('invites.expires_in_prompt') .fields-group - = f.input :severity, as: :radio_buttons, collection: IpBlock.severities.keys, include_blank: false, wrapper: :with_block_label, label_method: ->(severity) { safe_join([I18n.t("simple_form.labels.ip_block.severities.#{severity}"), content_tag(:span, I18n.t("simple_form.hints.ip_block.severities.#{severity}"), class: 'hint')]) } + = f.input :severity, as: :radio_buttons, collection: IpBlock.severities.keys, include_blank: false, wrapper: :with_block_label, label_method: ->(severity) { ip_blocks_severity_label(severity) } .fields-group = f.input :comment, as: :string, wrapper: :with_block_label diff --git a/app/views/admin/settings/discovery/show.html.haml b/app/views/admin/settings/discovery/show.html.haml index 62011d5c5..59fc3226a 100644 --- a/app/views/admin/settings/discovery/show.html.haml +++ b/app/views/admin/settings/discovery/show.html.haml @@ -42,7 +42,7 @@ %h4= t('admin.settings.security.federation_authentication') .fields-group - = f.input :authorized_fetch, as: :boolean, wrapper: :with_label, label: t('admin.settings.security.authorized_fetch'), warning_hint: authorized_fetch_overridden? ? t('admin.settings.security.authorized_fetch_overridden_hint') : nil, hint: t('admin.settings.security.authorized_fetch_hint'), disabled: authorized_fetch_overridden?, recommended: authorized_fetch_overridden? ? :overridden : nil + = f.input :authorized_fetch, as: :boolean, wrapper: :with_label, label: t('admin.settings.security.authorized_fetch'), warning_hint: discovery_warning_hint_text, hint: discovery_hint_text, disabled: authorized_fetch_overridden?, recommended: discovery_recommended_value %h4= t('admin.settings.discovery.follow_recommendations') From 31bef99b9edf8ad52182f9dcc5012d3c799b9fe4 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 29 Nov 2023 05:08:55 -0500 Subject: [PATCH 33/40] Move lib/mastodon/premailer_webpack_strategy to lib/ (#27636) --- .rubocop_todo.yml | 2 +- config/initializers/premailer_rails.rb | 2 +- lib/{mastodon => }/premailer_webpack_strategy.rb | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename lib/{mastodon => }/premailer_webpack_strategy.rb (100%) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 167204604..a79f88f97 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -307,7 +307,7 @@ Style/FetchEnvVar: - 'config/initializers/devise.rb' - 'config/initializers/paperclip.rb' - 'config/initializers/vapid.rb' - - 'lib/mastodon/premailer_webpack_strategy.rb' + - 'lib/premailer_webpack_strategy.rb' - 'lib/mastodon/redis_config.rb' - 'lib/tasks/repo.rake' - 'spec/features/profile_spec.rb' diff --git a/config/initializers/premailer_rails.rb b/config/initializers/premailer_rails.rb index 98b208271..52576ef88 100644 --- a/config/initializers/premailer_rails.rb +++ b/config/initializers/premailer_rails.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative '../../lib/mastodon/premailer_webpack_strategy' +require_relative '../../lib/premailer_webpack_strategy' Premailer::Rails.config.merge!(remove_ids: true, adapter: :nokogiri, diff --git a/lib/mastodon/premailer_webpack_strategy.rb b/lib/premailer_webpack_strategy.rb similarity index 100% rename from lib/mastodon/premailer_webpack_strategy.rb rename to lib/premailer_webpack_strategy.rb From a1636fce7f2eb630b6c8d0a4524b1687b61e3496 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 29 Nov 2023 05:10:21 -0500 Subject: [PATCH 34/40] Move lib/devise/* to lib/devise/strategies/* (#27638) --- .rubocop_todo.yml | 8 ++++---- config/application.rb | 4 ++-- .../{ => strategies}/two_factor_ldap_authenticatable.rb | 0 .../{ => strategies}/two_factor_pam_authenticatable.rb | 0 4 files changed, 6 insertions(+), 6 deletions(-) rename lib/devise/{ => strategies}/two_factor_ldap_authenticatable.rb (100%) rename lib/devise/{ => strategies}/two_factor_pam_authenticatable.rb (100%) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index a79f88f97..43af4f670 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -357,8 +357,8 @@ Style/GuardClause: - 'config/initializers/devise.rb' - 'db/migrate/20170901141119_truncate_preview_cards.rb' - 'db/post_migrate/20220704024901_migrate_settings_to_user_roles.rb' - - 'lib/devise/two_factor_ldap_authenticatable.rb' - - 'lib/devise/two_factor_pam_authenticatable.rb' + - 'lib/devise/strategies/two_factor_ldap_authenticatable.rb' + - 'lib/devise/strategies/two_factor_pam_authenticatable.rb' - 'lib/mastodon/cli/accounts.rb' - 'lib/mastodon/cli/maintenance.rb' - 'lib/mastodon/cli/media.rb' @@ -493,8 +493,8 @@ Style/SafeNavigation: # SupportedStyles: only_raise, only_fail, semantic Style/SignalException: Exclude: - - 'lib/devise/two_factor_ldap_authenticatable.rb' - - 'lib/devise/two_factor_pam_authenticatable.rb' + - 'lib/devise/strategies/two_factor_ldap_authenticatable.rb' + - 'lib/devise/strategies/two_factor_pam_authenticatable.rb' # This cop supports unsafe autocorrection (--autocorrect-all). Style/SingleArgumentDig: diff --git a/config/application.rb b/config/application.rb index 387827784..99ee4ffd7 100644 --- a/config/application.rb +++ b/config/application.rb @@ -39,8 +39,8 @@ require_relative '../lib/mastodon/snowflake' require_relative '../lib/mastodon/version' require_relative '../lib/mastodon/rack_middleware' require_relative '../lib/public_file_server_middleware' -require_relative '../lib/devise/two_factor_ldap_authenticatable' -require_relative '../lib/devise/two_factor_pam_authenticatable' +require_relative '../lib/devise/strategies/two_factor_ldap_authenticatable' +require_relative '../lib/devise/strategies/two_factor_pam_authenticatable' require_relative '../lib/chewy/settings_extensions' require_relative '../lib/chewy/index_extensions' require_relative '../lib/chewy/strategy/mastodon' diff --git a/lib/devise/two_factor_ldap_authenticatable.rb b/lib/devise/strategies/two_factor_ldap_authenticatable.rb similarity index 100% rename from lib/devise/two_factor_ldap_authenticatable.rb rename to lib/devise/strategies/two_factor_ldap_authenticatable.rb diff --git a/lib/devise/two_factor_pam_authenticatable.rb b/lib/devise/strategies/two_factor_pam_authenticatable.rb similarity index 100% rename from lib/devise/two_factor_pam_authenticatable.rb rename to lib/devise/strategies/two_factor_pam_authenticatable.rb From 291dc04e67f963313958a23de7ba935fa7130996 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 29 Nov 2023 05:38:05 -0500 Subject: [PATCH 35/40] Remove un-needed `action` and `template` options to `render` in controllers (#28022) --- .../admin/account_moderation_notes_controller.rb | 2 +- app/controllers/admin/relays_controller.rb | 2 +- app/controllers/admin/report_notes_controller.rb | 2 +- app/controllers/concerns/challengable_concern.rb | 2 +- app/controllers/disputes/appeals_controller.rb | 2 +- app/controllers/filters_controller.rb | 4 ++-- app/controllers/statuses_cleanup_controller.rb | 2 +- spec/controllers/concerns/challengable_concern_spec.rb | 6 +++--- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/controllers/admin/account_moderation_notes_controller.rb b/app/controllers/admin/account_moderation_notes_controller.rb index 4f36f33f4..8b6c1a445 100644 --- a/app/controllers/admin/account_moderation_notes_controller.rb +++ b/app/controllers/admin/account_moderation_notes_controller.rb @@ -16,7 +16,7 @@ module Admin @moderation_notes = @account.targeted_moderation_notes.latest @warnings = @account.strikes.custom.latest - render template: 'admin/accounts/show' + render 'admin/accounts/show' end end diff --git a/app/controllers/admin/relays_controller.rb b/app/controllers/admin/relays_controller.rb index c1297c8b9..c89380215 100644 --- a/app/controllers/admin/relays_controller.rb +++ b/app/controllers/admin/relays_controller.rb @@ -24,7 +24,7 @@ module Admin @relay.enable! redirect_to admin_relays_path else - render action: :new + render :new end end diff --git a/app/controllers/admin/report_notes_controller.rb b/app/controllers/admin/report_notes_controller.rb index 3fd815b60..b5f04a1ca 100644 --- a/app/controllers/admin/report_notes_controller.rb +++ b/app/controllers/admin/report_notes_controller.rb @@ -26,7 +26,7 @@ module Admin @form = Admin::StatusBatchAction.new @statuses = @report.statuses.with_includes - render template: 'admin/reports/show' + render 'admin/reports/show' end end diff --git a/app/controllers/concerns/challengable_concern.rb b/app/controllers/concerns/challengable_concern.rb index 2995a25e0..09874fb40 100644 --- a/app/controllers/concerns/challengable_concern.rb +++ b/app/controllers/concerns/challengable_concern.rb @@ -43,7 +43,7 @@ module ChallengableConcern def render_challenge @body_classes = 'lighter' - render template: 'auth/challenges/new', layout: 'auth' + render 'auth/challenges/new', layout: 'auth' end def challenge_passed? diff --git a/app/controllers/disputes/appeals_controller.rb b/app/controllers/disputes/appeals_controller.rb index eefd92b5a..98b58d211 100644 --- a/app/controllers/disputes/appeals_controller.rb +++ b/app/controllers/disputes/appeals_controller.rb @@ -11,7 +11,7 @@ class Disputes::AppealsController < Disputes::BaseController redirect_to disputes_strike_path(@strike), notice: I18n.t('disputes.strikes.appealed_msg') rescue ActiveRecord::RecordInvalid => e @appeal = e.record - render template: 'disputes/strikes/show' + render 'disputes/strikes/show' end private diff --git a/app/controllers/filters_controller.rb b/app/controllers/filters_controller.rb index bbe177ead..bd9964426 100644 --- a/app/controllers/filters_controller.rb +++ b/app/controllers/filters_controller.rb @@ -25,7 +25,7 @@ class FiltersController < ApplicationController if @filter.save redirect_to filters_path else - render action: :new + render :new end end @@ -33,7 +33,7 @@ class FiltersController < ApplicationController if @filter.update(resource_params) redirect_to filters_path else - render action: :edit + render :edit end end diff --git a/app/controllers/statuses_cleanup_controller.rb b/app/controllers/statuses_cleanup_controller.rb index 19ae971ce..4a3fc10ca 100644 --- a/app/controllers/statuses_cleanup_controller.rb +++ b/app/controllers/statuses_cleanup_controller.rb @@ -14,7 +14,7 @@ class StatusesCleanupController < ApplicationController if @policy.update(resource_params) redirect_to statuses_cleanup_path, notice: I18n.t('generic.changes_saved_msg') else - render action: :show + render :show end rescue ActionController::ParameterMissing # Do nothing diff --git a/spec/controllers/concerns/challengable_concern_spec.rb b/spec/controllers/concerns/challengable_concern_spec.rb index 3324bdd24..169e2122f 100644 --- a/spec/controllers/concerns/challengable_concern_spec.rb +++ b/spec/controllers/concerns/challengable_concern_spec.rb @@ -85,7 +85,7 @@ RSpec.describe ChallengableConcern do before { get :foo } it 'renders challenge' do - expect(response).to render_template('auth/challenges/new') + expect(response).to render_template('auth/challenges/new', layout: :auth) end # See Auth::ChallengesControllerSpec @@ -95,7 +95,7 @@ RSpec.describe ChallengableConcern do before { post :bar } it 'renders challenge' do - expect(response).to render_template('auth/challenges/new') + expect(response).to render_template('auth/challenges/new', layout: :auth) end it 'accepts correct password' do @@ -106,7 +106,7 @@ RSpec.describe ChallengableConcern do it 'rejects wrong password' do post :bar, params: { form_challenge: { current_password: 'dddfff888123' } } - expect(response.body).to render_template('auth/challenges/new') + expect(response.body).to render_template('auth/challenges/new', layout: :auth) expect(session[:challenge_passed_at]).to be_nil end end From e48ecd29294ec2790fd38fd1a35b8490d1350c4e Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 29 Nov 2023 05:39:59 -0500 Subject: [PATCH 36/40] Remove `default_scope` from `Admin::ActionLog` (#28026) --- app/controllers/admin/action_logs_controller.rb | 2 +- app/models/admin/action_log.rb | 4 ++-- app/models/admin/action_log_filter.rb | 12 ++++++++---- app/models/report.rb | 10 +++++----- ...on_log_fabricator.rb => action_log_fabricator.rb} | 2 +- spec/models/report_spec.rb | 6 +++--- 6 files changed, 20 insertions(+), 16 deletions(-) rename spec/fabricators/{admin_action_log_fabricator.rb => action_log_fabricator.rb} (68%) diff --git a/app/controllers/admin/action_logs_controller.rb b/app/controllers/admin/action_logs_controller.rb index 42edec15a..37a00ad22 100644 --- a/app/controllers/admin/action_logs_controller.rb +++ b/app/controllers/admin/action_logs_controller.rb @@ -6,7 +6,7 @@ module Admin def index authorize :audit_log, :index? - @auditable_accounts = Account.where(id: Admin::ActionLog.reorder(nil).select('distinct account_id')).select(:id, :username) + @auditable_accounts = Account.where(id: Admin::ActionLog.select('distinct account_id')).select(:id, :username) end private diff --git a/app/models/admin/action_log.rb b/app/models/admin/action_log.rb index f2c121d75..49ae67980 100644 --- a/app/models/admin/action_log.rb +++ b/app/models/admin/action_log.rb @@ -24,12 +24,12 @@ class Admin::ActionLog < ApplicationRecord belongs_to :account belongs_to :target, polymorphic: true, optional: true - default_scope -> { order('id desc') } - before_validation :set_human_identifier before_validation :set_route_param before_validation :set_permalink + scope :latest, -> { order(id: :desc) } + def action super.to_sym end diff --git a/app/models/admin/action_log_filter.rb b/app/models/admin/action_log_filter.rb index 011797462..d413cb386 100644 --- a/app/models/admin/action_log_filter.rb +++ b/app/models/admin/action_log_filter.rb @@ -72,7 +72,7 @@ class Admin::ActionLogFilter end def results - scope = Admin::ActionLog.includes(:target) + scope = latest_action_logs.includes(:target) params.each do |key, value| next if key.to_s == 'page' @@ -88,14 +88,18 @@ class Admin::ActionLogFilter def scope_for(key, value) case key when 'action_type' - Admin::ActionLog.where(ACTION_TYPE_MAP[value.to_sym]) + latest_action_logs.where(ACTION_TYPE_MAP[value.to_sym]) when 'account_id' - Admin::ActionLog.where(account_id: value) + latest_action_logs.where(account_id: value) when 'target_account_id' account = Account.find_or_initialize_by(id: value) - Admin::ActionLog.where(target: [account, account.user].compact) + latest_action_logs.where(target: [account, account.user].compact) else raise Mastodon::InvalidParameterError, "Unknown filter: #{key}" end end + + def latest_action_logs + Admin::ActionLog.latest + end end diff --git a/app/models/report.rb b/app/models/report.rb index 81ad721df..c565362cc 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -131,25 +131,25 @@ class Report < ApplicationRecord Admin::ActionLog.where( target_type: 'Report', target_id: id - ).unscope(:order).arel, + ).arel, Admin::ActionLog.where( target_type: 'Account', target_id: target_account_id - ).unscope(:order).arel, + ).arel, Admin::ActionLog.where( target_type: 'Status', target_id: status_ids - ).unscope(:order).arel, + ).arel, Admin::ActionLog.where( target_type: 'AccountWarning', target_id: AccountWarning.where(report_id: id).select(:id) - ).unscope(:order).arel, + ).arel, ].reduce { |union, query| Arel::Nodes::UnionAll.new(union, query) } - Admin::ActionLog.from(Arel::Nodes::As.new(subquery, Admin::ActionLog.arel_table)) + Admin::ActionLog.latest.from(Arel::Nodes::As.new(subquery, Admin::ActionLog.arel_table)) end private diff --git a/spec/fabricators/admin_action_log_fabricator.rb b/spec/fabricators/action_log_fabricator.rb similarity index 68% rename from spec/fabricators/admin_action_log_fabricator.rb rename to spec/fabricators/action_log_fabricator.rb index 3acedbffd..ce52cb73a 100644 --- a/spec/fabricators/admin_action_log_fabricator.rb +++ b/spec/fabricators/action_log_fabricator.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -Fabricator('Admin::ActionLog') do +Fabricator(:action_log, from: Admin::ActionLog) do account { Fabricate.build(:account) } action 'MyString' target nil diff --git a/spec/models/report_spec.rb b/spec/models/report_spec.rb index 0093dcd8d..c514c63b3 100644 --- a/spec/models/report_spec.rb +++ b/spec/models/report_spec.rb @@ -110,9 +110,9 @@ describe Report do let(:status) { Fabricate(:status) } before do - Fabricate('Admin::ActionLog', target_type: 'Report', account_id: target_account.id, target_id: report.id, created_at: 2.days.ago) - Fabricate('Admin::ActionLog', target_type: 'Account', account_id: target_account.id, target_id: report.target_account_id, created_at: 2.days.ago) - Fabricate('Admin::ActionLog', target_type: 'Status', account_id: target_account.id, target_id: status.id, created_at: 2.days.ago) + Fabricate(:action_log, target_type: 'Report', account_id: target_account.id, target_id: report.id, created_at: 2.days.ago) + Fabricate(:action_log, target_type: 'Account', account_id: target_account.id, target_id: report.target_account_id, created_at: 2.days.ago) + Fabricate(:action_log, target_type: 'Status', account_id: target_account.id, target_id: status.id, created_at: 2.days.ago) end it 'returns right logs' do From 6e55ff964325694c9a06914e59733babfc4854c7 Mon Sep 17 00:00:00 2001 From: Filippo Giunchedi Date: Thu, 30 Nov 2023 11:46:06 +0100 Subject: [PATCH 37/40] Change Vagrant to install Node 20 (#28100) Co-authored-by: Filippo Giunchedi --- Vagrantfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index e2c66a476..6f0f51109 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -10,7 +10,11 @@ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main' # Add repo for NodeJS -curl -sL https://deb.nodesource.com/setup_16.x | sudo bash - +sudo mkdir -p /etc/apt/keyrings +curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg +NODE_MAJOR=20 +echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list +sudo apt-get update # Add firewall rule to redirect 80 to PORT and save sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]} From b696ca6b1a0fee1e56fcf70f4c561ff2661ad81d Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 30 Nov 2023 05:48:46 -0500 Subject: [PATCH 38/40] Move self destruct CLI command definition code to module (#28131) --- lib/mastodon/cli/federation.rb | 74 ++++++++++++++++++++++++++++++++++ lib/mastodon/cli/main.rb | 62 +--------------------------- 2 files changed, 76 insertions(+), 60 deletions(-) create mode 100644 lib/mastodon/cli/federation.rb diff --git a/lib/mastodon/cli/federation.rb b/lib/mastodon/cli/federation.rb new file mode 100644 index 000000000..1b4cb467a --- /dev/null +++ b/lib/mastodon/cli/federation.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require 'tty-prompt' + +module Mastodon::CLI + module Federation + extend ActiveSupport::Concern + + included do + desc 'self-destruct', 'Erase the server from the federation' + long_desc <<~LONG_DESC + Erase the server from the federation by broadcasting account delete + activities to all known other servers. This allows a "clean exit" from + running a Mastodon server, as it leaves next to no cache behind on + other servers. + + This command is always interactive and requires confirmation twice. + + No local data is actually deleted, because emptying the + database or removing files is much faster through other, external + means, such as e.g. deleting the entire VPS. However, because other + servers will delete data about local users, but no local data will be + updated (such as e.g. followers), there will be a state mismatch + that will lead to glitches and issues if you then continue to run and use + the server. + + So either you know exactly what you are doing, or you are starting + from a blank slate afterwards by manually clearing out all the local + data! + LONG_DESC + def self_destruct + if SelfDestructHelper.self_destruct? + prompt.ok('Self-destruct mode is already enabled for this Mastodon server') + + pending_accounts = Account.local.without_suspended.count + Account.local.suspended.joins(:deletion_request).count + sidekiq_stats = Sidekiq::Stats.new + + if pending_accounts.positive? + prompt.warn("#{pending_accounts} accounts are still pending deletion.") + elsif sidekiq_stats.enqueued.positive? + prompt.warn('Deletion notices are still being processed') + elsif sidekiq_stats.retry_size.positive? + prompt.warn('At least one delivery attempt for each deletion notice has been made, but some have failed and are scheduled for retry') + else + prompt.ok('Every deletion notice has been sent! You can safely delete all data and decomission your servers!') + end + + exit(0) + end + + exit(1) unless prompt.ask('Type in the domain of the server to confirm:', required: true) == Rails.configuration.x.local_domain + + prompt.warn('This operation WILL NOT be reversible.') + prompt.warn('While the data won\'t be erased locally, the server will be in a BROKEN STATE afterwards.') + prompt.warn('The deletion process itself may take a long time, and will be handled by Sidekiq, so do not shut it down until it has finished (you will be able to re-run this command to see the state of the self-destruct process).') + + exit(1) if prompt.no?('Are you sure you want to proceed?') + + self_destruct_value = Rails.application.message_verifier('self-destruct').generate(Rails.configuration.x.local_domain) + prompt.ok('To switch Mastodon to self-destruct mode, add the following variable to your evironment (e.g. by adding a line to your `.env.production`) and restart all Mastodon processes:') + prompt.ok(" SELF_DESTRUCT=#{self_destruct_value}") + prompt.ok("\nYou can re-run this command to see the state of the self-destruct process.") + rescue TTY::Reader::InputInterrupt + exit(1) + end + + private + + def prompt + @prompt ||= TTY::Prompt.new + end + end + end +end diff --git a/lib/mastodon/cli/main.rb b/lib/mastodon/cli/main.rb index 64f1646f4..ef40b81f3 100644 --- a/lib/mastodon/cli/main.rb +++ b/lib/mastodon/cli/main.rb @@ -8,6 +8,7 @@ require_relative 'canonical_email_blocks' require_relative 'domains' require_relative 'email_domain_blocks' require_relative 'emoji' +require_relative 'federation' require_relative 'feeds' require_relative 'ip_blocks' require_relative 'maintenance' @@ -65,66 +66,7 @@ module Mastodon::CLI desc 'maintenance SUBCOMMAND ...ARGS', 'Various maintenance utilities' subcommand 'maintenance', Maintenance - desc 'self-destruct', 'Erase the server from the federation' - long_desc <<~LONG_DESC - Erase the server from the federation by broadcasting account delete - activities to all known other servers. This allows a "clean exit" from - running a Mastodon server, as it leaves next to no cache behind on - other servers. - - This command is always interactive and requires confirmation twice. - - No local data is actually deleted, because emptying the - database or removing files is much faster through other, external - means, such as e.g. deleting the entire VPS. However, because other - servers will delete data about local users, but no local data will be - updated (such as e.g. followers), there will be a state mismatch - that will lead to glitches and issues if you then continue to run and use - the server. - - So either you know exactly what you are doing, or you are starting - from a blank slate afterwards by manually clearing out all the local - data! - LONG_DESC - def self_destruct - require 'tty-prompt' - - prompt = TTY::Prompt.new - - if SelfDestructHelper.self_destruct? - prompt.ok('Self-destruct mode is already enabled for this Mastodon server') - - pending_accounts = Account.local.without_suspended.count + Account.local.suspended.joins(:deletion_request).count - sidekiq_stats = Sidekiq::Stats.new - - if pending_accounts.positive? - prompt.warn("#{pending_accounts} accounts are still pending deletion.") - elsif sidekiq_stats.enqueued.positive? - prompt.warn('Deletion notices are still being processed') - elsif sidekiq_stats.retry_size.positive? - prompt.warn('At least one delivery attempt for each deletion notice has been made, but some have failed and are scheduled for retry') - else - prompt.ok('Every deletion notice has been sent! You can safely delete all data and decomission your servers!') - end - - exit(0) - end - - exit(1) unless prompt.ask('Type in the domain of the server to confirm:', required: true) == Rails.configuration.x.local_domain - - prompt.warn('This operation WILL NOT be reversible.') - prompt.warn('While the data won\'t be erased locally, the server will be in a BROKEN STATE afterwards.') - prompt.warn('The deletion process itself may take a long time, and will be handled by Sidekiq, so do not shut it down until it has finished (you will be able to re-run this command to see the state of the self-destruct process).') - - exit(1) if prompt.no?('Are you sure you want to proceed?') - - self_destruct_value = Rails.application.message_verifier('self-destruct').generate(Rails.configuration.x.local_domain) - prompt.ok('To switch Mastodon to self-destruct mode, add the following variable to your evironment (e.g. by adding a line to your `.env.production`) and restart all Mastodon processes:') - prompt.ok(" SELF_DESTRUCT=#{self_destruct_value}") - prompt.ok("\nYou can re-run this command to see the state of the self-destruct process.") - rescue TTY::Reader::InputInterrupt - exit(1) - end + include Federation map %w(--version -v) => :version From c761cc4738c74519c65a99c5ab24874584605d2d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 Nov 2023 11:53:49 +0100 Subject: [PATCH 39/40] fix(deps): update babel monorepo to v7.23.5 (#28122) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 260 +++++++++++++++++++++++++++--------------------------- 1 file changed, 130 insertions(+), 130 deletions(-) diff --git a/yarn.lock b/yarn.lock index 11c2724d5..69464dfa2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -42,55 +42,55 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.22.13": - version: 7.22.13 - resolution: "@babel/code-frame@npm:7.22.13" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/code-frame@npm:7.23.5" dependencies: - "@babel/highlight": "npm:^7.22.13" + "@babel/highlight": "npm:^7.23.4" chalk: "npm:^2.4.2" - checksum: f4cc8ae1000265677daf4845083b72f88d00d311adb1a93c94eb4b07bf0ed6828a81ae4ac43ee7d476775000b93a28a9cddec18fbdc5796212d8dcccd5de72bd + checksum: a10e843595ddd9f97faa99917414813c06214f4d9205294013e20c70fbdf4f943760da37dec1d998bf3e6fc20fa2918a47c0e987a7e458663feb7698063ad7c6 languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9, @babel/compat-data@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/compat-data@npm:7.23.3" - checksum: c6af331753c34ee8a5678bc94404320826cb56b1dda3efc1311ec8fb0774e78225132f3c1acc988440ace667f14a838e297a822692b95758aa63da406e1f97a1 +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9, @babel/compat-data@npm:^7.23.3, @babel/compat-data@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/compat-data@npm:7.23.5" + checksum: 081278ed46131a890ad566a59c61600a5f9557bd8ee5e535890c8548192532ea92590742fd74bd9db83d74c669ef8a04a7e1c85cdea27f960233e3b83c3a957c languageName: node linkType: hard "@babel/core@npm:^7.10.4, @babel/core@npm:^7.11.1, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.22.1": - version: 7.23.3 - resolution: "@babel/core@npm:7.23.3" + version: 7.23.5 + resolution: "@babel/core@npm:7.23.5" dependencies: "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.22.13" - "@babel/generator": "npm:^7.23.3" + "@babel/code-frame": "npm:^7.23.5" + "@babel/generator": "npm:^7.23.5" "@babel/helper-compilation-targets": "npm:^7.22.15" "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helpers": "npm:^7.23.2" - "@babel/parser": "npm:^7.23.3" + "@babel/helpers": "npm:^7.23.5" + "@babel/parser": "npm:^7.23.5" "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.3" - "@babel/types": "npm:^7.23.3" + "@babel/traverse": "npm:^7.23.5" + "@babel/types": "npm:^7.23.5" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 08d43b749e24052d12713a7fb1f0c0d1275d4fb056d00846faeb8da79ecf6d0ba91a11b6afec407b8b0f9388d00e2c2f485f282bef0ade4d6d0a17de191a4287 + checksum: 311a512a870ee330a3f9a7ea89e5df790b2b5af0b1bd98b10b4edc0de2ac440f0df4d69ea2c0ee38a4b89041b9a495802741d93603be7d4fd834ec8bb6970bd2 languageName: node linkType: hard -"@babel/generator@npm:^7.23.3, @babel/generator@npm:^7.7.2": - version: 7.23.3 - resolution: "@babel/generator@npm:7.23.3" +"@babel/generator@npm:^7.23.5, @babel/generator@npm:^7.7.2": + version: 7.23.5 + resolution: "@babel/generator@npm:7.23.5" dependencies: - "@babel/types": "npm:^7.23.3" + "@babel/types": "npm:^7.23.5" "@jridgewell/gen-mapping": "npm:^0.3.2" "@jridgewell/trace-mapping": "npm:^0.3.17" jsesc: "npm:^2.5.1" - checksum: d5fff1417eecfada040e01a7c77a4968e81c436aeb35815ce85b4e80cd01e731423613d61033044a6cb5563bb8449ee260e3379b63eb50b38ec0a9ea9c00abfd + checksum: 14c6e874f796c4368e919bed6003bb0adc3ce837760b08f9e646d20aeb5ae7d309723ce6e4f06bcb4a2b5753145446c8e4425851380f695e40e71e1760f49e7b languageName: node linkType: hard @@ -310,10 +310,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-string-parser@npm:7.22.5" - checksum: 6b0ff8af724377ec41e5587fffa7605198da74cb8e7d8d48a36826df0c0ba210eb9fedb3d9bef4d541156e0bd11040f021945a6cbb731ccec4aefb4affa17aa4 +"@babel/helper-string-parser@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/helper-string-parser@npm:7.23.4" + checksum: f348d5637ad70b6b54b026d6544bd9040f78d24e7ec245a0fc42293968181f6ae9879c22d89744730d246ce8ec53588f716f102addd4df8bbc79b73ea10004ac languageName: node linkType: hard @@ -324,10 +324,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helper-validator-option@npm:7.22.15" - checksum: e9661bf80ba18e2dd978217b350fb07298e57ac417f4f1ab9fa011505e20e4857f2c3b4b538473516a9dc03af5ce3a831e5ed973311c28326f4c330b6be981c2 +"@babel/helper-validator-option@npm:^7.22.15, @babel/helper-validator-option@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/helper-validator-option@npm:7.23.5" + checksum: af45d5c0defb292ba6fd38979e8f13d7da63f9623d8ab9ededc394f67eb45857d2601278d151ae9affb6e03d5d608485806cd45af08b4468a0515cf506510e94 languageName: node linkType: hard @@ -342,34 +342,34 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.23.2": - version: 7.23.2 - resolution: "@babel/helpers@npm:7.23.2" +"@babel/helpers@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/helpers@npm:7.23.5" dependencies: "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.2" - "@babel/types": "npm:^7.23.0" - checksum: 3a6a939c5277a27486e7c626812f0643b35d1c053ac2eb66911f5ae6c0a4e4bcdd40750eba36b766b0ee8a753484287f50ae56232a5f8f2947116723e44b9e35 + "@babel/traverse": "npm:^7.23.5" + "@babel/types": "npm:^7.23.5" + checksum: a37e2728eb4378a4888e5d614e28de7dd79b55ac8acbecd0e5c761273e2a02a8f33b34b1932d9069db55417ace2937cbf8ec37c42f1030ce6d228857d7ccaa4f languageName: node linkType: hard -"@babel/highlight@npm:^7.22.13": - version: 7.22.20 - resolution: "@babel/highlight@npm:7.22.20" +"@babel/highlight@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/highlight@npm:7.23.4" dependencies: "@babel/helper-validator-identifier": "npm:^7.22.20" chalk: "npm:^2.4.2" js-tokens: "npm:^4.0.0" - checksum: f3c3a193afad23434297d88e81d1d6c0c2cf02423de2139ada7ce0a7fc62d8559abf4cc996533c1a9beca7fc990010eb8d544097f75e818ac113bf39ed810aa2 + checksum: fbff9fcb2f5539289c3c097d130e852afd10d89a3a08ac0b5ebebbc055cc84a4bcc3dcfed463d488cde12dd0902ef1858279e31d7349b2e8cee43913744bda33 languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/parser@npm:7.23.3" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/parser@npm:7.23.5" bin: parser: ./bin/babel-parser.js - checksum: 0fe11eadd4146a9155305b5bfece0f8223a3b1b97357ffa163c0156940de92e76cd0e7a173de819b8692767147e62f33389b312d1537f84cede51092672df6ef + checksum: 3356aa90d7bafb4e2c7310e7c2c3d443c4be4db74913f088d3d577a1eb914ea4188e05fd50a47ce907a27b755c4400c4e3cbeee73dbeb37761f6ca85954f5a20 languageName: node linkType: hard @@ -661,9 +661,9 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-async-generator-functions@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.3" +"@babel/plugin-transform-async-generator-functions@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.4" dependencies: "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-plugin-utils": "npm:^7.22.5" @@ -671,7 +671,7 @@ __metadata: "@babel/plugin-syntax-async-generators": "npm:^7.8.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e846f282658e097fce4fccf3ee29289bf05f0654846a5994727a36f0cdc2e47abdffd4be4fa65787e94aa975824fae894c90afbfdc8caacd46c12c7f43e99d7f + checksum: f2eef4de609975a3f7da7832576b5ffc93e43c80f87e1a99e886b0f8591096cfc4c37e2d5f52fdeaa2a9c09a25a59f3e621159abaca75d3193922a5c0e4cbe0c languageName: node linkType: hard @@ -699,14 +699,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-block-scoping@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-block-scoping@npm:7.23.3" +"@babel/plugin-transform-block-scoping@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-block-scoping@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ccaeded7954c196811d22a35322579254cda52676e823682b6234885a3aaf88fe0d5152dacaec43db9031dcf35a050a5343e36028e5905b0ba9c02d36b30a57f + checksum: 83006804dddf980ab1bcd6d67bc381e24b58c776507c34f990468f820d0da71dba3697355ca4856532fa2eeb2a1e3e73c780f03760b5507a511cbedb0308e276 languageName: node linkType: hard @@ -722,22 +722,22 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-class-static-block@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-class-static-block@npm:7.23.3" +"@babel/plugin-transform-class-static-block@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-class-static-block@npm:7.23.4" dependencies: "@babel/helper-create-class-features-plugin": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" peerDependencies: "@babel/core": ^7.12.0 - checksum: 89cdb66d7bc834cd51659eb7286a6bee23add0bc114943d68c4b6c0c834178cf0d55183df0cf508fec9c55ed4155641360e6f55a91c16fe826ccaf1adf381922 + checksum: fdca96640ef29d8641a7f8de106f65f18871b38cc01c0f7b696d2b49c76b77816b30a812c08e759d06dd10b4d9b3af6b5e4ac22a2017a88c4077972224b77ab0 languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-classes@npm:7.23.3" +"@babel/plugin-transform-classes@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/plugin-transform-classes@npm:7.23.5" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" "@babel/helper-compilation-targets": "npm:^7.22.15" @@ -750,7 +750,7 @@ __metadata: globals: "npm:^11.1.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 88bfd332db0ba5cbfb8557a2ba5a7185151aebc9cfe3035b014aa6d795556acbe672bb8c78da3c9fd1d23f55a333d14b5daa127ef037f5ced5198b6d79a146d6 + checksum: 07988f52b4893151887d1ea6ff79e5fe834078c5731bd09babd5659edbbae21ea4e2de326a02443a63fd776b4c945da6177f07875b56fe66e0b7899e830a9e92 languageName: node linkType: hard @@ -800,15 +800,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-dynamic-import@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-dynamic-import@npm:7.23.3" +"@babel/plugin-transform-dynamic-import@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-dynamic-import": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: df3fd130312dc53d068fa76333991dce5e86987b023af8c3b502bd7d36a8e67da6f718e61dc838576a9fbacd06628e29607ee22d9bae30705485c14130eab201 + checksum: 19ae4a4a2ca86d35224734c41c48b2aa6a13139f3cfa1cbd18c0e65e461de8b65687dec7e52b7a72bb49db04465394c776aa1b13a2af5dc975b2a0cde3dcab67 languageName: node linkType: hard @@ -824,15 +824,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-export-namespace-from@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-export-namespace-from@npm:7.23.3" +"@babel/plugin-transform-export-namespace-from@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-export-namespace-from": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 390c6626dcda99023629049d92090242b4575351a4a7b47f97febabd2381f2cd0f624de661d8de8d1f715fedd63753cfd1feddead19e5960c27b88e447465b81 + checksum: 38bf04f851e36240bbe83ace4169da626524f4107bfb91f05b4ad93a5fb6a36d5b3d30b8883c1ba575ccfc1bac7938e90ca2e3cb227f7b3f4a9424beec6fd4a7 languageName: node linkType: hard @@ -860,15 +860,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-json-strings@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-json-strings@npm:7.23.3" +"@babel/plugin-transform-json-strings@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-json-strings@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-json-strings": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e1cef6a485b9da32aba9449fb459dac062dfc401f3d6ad48e7fbdcb73bbe470c995cc15ce5c421b95efe1e9a90d5507eb606360fe10b6d8cb869dd5dae7a2562 + checksum: 39e82223992a9ad857722ae051291935403852ad24b0dd64c645ca1c10517b6bf9822377d88643fed8b3e61a4e3f7e5ae41cf90eb07c40a786505d47d5970e54 languageName: node linkType: hard @@ -883,15 +883,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-logical-assignment-operators@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.23.3" +"@babel/plugin-transform-logical-assignment-operators@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 23b7588b26d420c8b132bd08916d49871ca0c8db892f6b58637b10e2a0d918163d413c505db880a9157fc2e61d089040f139298a60d837ccbd0efca0474ac7ca + checksum: 87b034dd13143904e405887e6125d76c27902563486efc66b7d9a9d8f9406b76c6ac42d7b37224014af5783d7edb465db0cdecd659fa3227baad0b3a6a35deff languageName: node linkType: hard @@ -980,7 +980,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.3, @babel/plugin-transform-nullish-coalescing-operator@npm:^7.23.3": +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.3, @babel/plugin-transform-nullish-coalescing-operator@npm:^7.23.4": version: 7.23.4 resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.23.4" dependencies: @@ -992,21 +992,21 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-numeric-separator@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-numeric-separator@npm:7.23.3" +"@babel/plugin-transform-numeric-separator@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-numeric-separator": "npm:^7.10.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: d3748cce20e8752e61dfda55e275c699459a3ff8d0bb46585da813136e04066b1ce70b71beef504fcdc8d4cca3c955112cea96d5e9fd5a42a5bc8956d05236c2 + checksum: e34902da4f5588dc4812c92cb1f6a5e3e3647baf7b4623e30942f551bf1297621abec4e322ebfa50b320c987c0f34d9eb4355b3d289961d9035e2126e3119c12 languageName: node linkType: hard -"@babel/plugin-transform-object-rest-spread@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-object-rest-spread@npm:7.23.3" +"@babel/plugin-transform-object-rest-spread@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.23.4" dependencies: "@babel/compat-data": "npm:^7.23.3" "@babel/helper-compilation-targets": "npm:^7.22.15" @@ -1015,7 +1015,7 @@ __metadata: "@babel/plugin-transform-parameters": "npm:^7.23.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 31ab631aaba945c118662943e5f1f54a21f07d64f06e06b25d55871168c460f3eeeccdf7b05aa74a1340e2cfbe781ad3c7ceccd0c2585d39f7b73ba11ebaa9d0 + checksum: b56017992ffe7fcd1dd9a9da67c39995a141820316266bcf7d77dc912980d228ccbd3f36191d234f5cc389b09157b5d2a955e33e8fb368319534affd1c72b262 languageName: node linkType: hard @@ -1031,28 +1031,28 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-optional-catch-binding@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.23.3" +"@babel/plugin-transform-optional-catch-binding@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-optional-catch-binding": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 85ac1e94ee8f21648816151628ff931cc16143ec8c904649a1ecfd8960160290eccc5a197b4ae3ee7a1c7a27a7c4189e61b4de24483d5bad4040784afe2d206f + checksum: 4ef61812af0e4928485e28301226ce61139a8b8cea9e9a919215ebec4891b9fea2eb7a83dc3090e2679b7d7b2c8653da601fbc297d2addc54a908b315173991e languageName: node linkType: hard -"@babel/plugin-transform-optional-chaining@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.3" +"@babel/plugin-transform-optional-chaining@npm:^7.23.3, @babel/plugin-transform-optional-chaining@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 2b358962169d871392aa292a67527e5335909438da0ddbb0d19e7838c0f8a2081cc751a49e6e534ac4d6c932254531a205ac22b197f64fc4c89f41bf9f595497 + checksum: 305b773c29ad61255b0e83ec1e92b2f7af6aa58be4cba1e3852bddaa14f7d2afd7b4438f41c28b179d6faac7eb8d4fb5530a17920294f25d459b8f84406bfbfb languageName: node linkType: hard @@ -1079,9 +1079,9 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-private-property-in-object@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-private-property-in-object@npm:7.23.3" +"@babel/plugin-transform-private-property-in-object@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.23.4" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" "@babel/helper-create-class-features-plugin": "npm:^7.22.15" @@ -1089,7 +1089,7 @@ __metadata: "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 9211dd25a6e87a01535f2d97a663fa6de3472b963c8dcfaacce229a2e3fa6500f2e9fc690bc100a540fc7b66c8364faf7ef19b32e9c9b9791e4561b742c15ed3 + checksum: 8d31b28f24204b4d13514cd3a8f3033abf575b1a6039759ddd6e1d82dd33ba7281f9bc85c9f38072a665d69bfa26dc40737eefaf9d397b024654a483d2357bf5 languageName: node linkType: hard @@ -1333,13 +1333,13 @@ __metadata: linkType: hard "@babel/preset-env@npm:^7.11.0, @babel/preset-env@npm:^7.12.1, @babel/preset-env@npm:^7.22.4": - version: 7.23.3 - resolution: "@babel/preset-env@npm:7.23.3" + version: 7.23.5 + resolution: "@babel/preset-env@npm:7.23.5" dependencies: - "@babel/compat-data": "npm:^7.23.3" + "@babel/compat-data": "npm:^7.23.5" "@babel/helper-compilation-targets": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-validator-option": "npm:^7.22.15" + "@babel/helper-validator-option": "npm:^7.23.5" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.23.3" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.23.3" "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.23.3" @@ -1363,25 +1363,25 @@ __metadata: "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" "@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6" "@babel/plugin-transform-arrow-functions": "npm:^7.23.3" - "@babel/plugin-transform-async-generator-functions": "npm:^7.23.3" + "@babel/plugin-transform-async-generator-functions": "npm:^7.23.4" "@babel/plugin-transform-async-to-generator": "npm:^7.23.3" "@babel/plugin-transform-block-scoped-functions": "npm:^7.23.3" - "@babel/plugin-transform-block-scoping": "npm:^7.23.3" + "@babel/plugin-transform-block-scoping": "npm:^7.23.4" "@babel/plugin-transform-class-properties": "npm:^7.23.3" - "@babel/plugin-transform-class-static-block": "npm:^7.23.3" - "@babel/plugin-transform-classes": "npm:^7.23.3" + "@babel/plugin-transform-class-static-block": "npm:^7.23.4" + "@babel/plugin-transform-classes": "npm:^7.23.5" "@babel/plugin-transform-computed-properties": "npm:^7.23.3" "@babel/plugin-transform-destructuring": "npm:^7.23.3" "@babel/plugin-transform-dotall-regex": "npm:^7.23.3" "@babel/plugin-transform-duplicate-keys": "npm:^7.23.3" - "@babel/plugin-transform-dynamic-import": "npm:^7.23.3" + "@babel/plugin-transform-dynamic-import": "npm:^7.23.4" "@babel/plugin-transform-exponentiation-operator": "npm:^7.23.3" - "@babel/plugin-transform-export-namespace-from": "npm:^7.23.3" + "@babel/plugin-transform-export-namespace-from": "npm:^7.23.4" "@babel/plugin-transform-for-of": "npm:^7.23.3" "@babel/plugin-transform-function-name": "npm:^7.23.3" - "@babel/plugin-transform-json-strings": "npm:^7.23.3" + "@babel/plugin-transform-json-strings": "npm:^7.23.4" "@babel/plugin-transform-literals": "npm:^7.23.3" - "@babel/plugin-transform-logical-assignment-operators": "npm:^7.23.3" + "@babel/plugin-transform-logical-assignment-operators": "npm:^7.23.4" "@babel/plugin-transform-member-expression-literals": "npm:^7.23.3" "@babel/plugin-transform-modules-amd": "npm:^7.23.3" "@babel/plugin-transform-modules-commonjs": "npm:^7.23.3" @@ -1389,15 +1389,15 @@ __metadata: "@babel/plugin-transform-modules-umd": "npm:^7.23.3" "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.22.5" "@babel/plugin-transform-new-target": "npm:^7.23.3" - "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.23.3" - "@babel/plugin-transform-numeric-separator": "npm:^7.23.3" - "@babel/plugin-transform-object-rest-spread": "npm:^7.23.3" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.23.4" + "@babel/plugin-transform-numeric-separator": "npm:^7.23.4" + "@babel/plugin-transform-object-rest-spread": "npm:^7.23.4" "@babel/plugin-transform-object-super": "npm:^7.23.3" - "@babel/plugin-transform-optional-catch-binding": "npm:^7.23.3" - "@babel/plugin-transform-optional-chaining": "npm:^7.23.3" + "@babel/plugin-transform-optional-catch-binding": "npm:^7.23.4" + "@babel/plugin-transform-optional-chaining": "npm:^7.23.4" "@babel/plugin-transform-parameters": "npm:^7.23.3" "@babel/plugin-transform-private-methods": "npm:^7.23.3" - "@babel/plugin-transform-private-property-in-object": "npm:^7.23.3" + "@babel/plugin-transform-private-property-in-object": "npm:^7.23.4" "@babel/plugin-transform-property-literals": "npm:^7.23.3" "@babel/plugin-transform-regenerator": "npm:^7.23.3" "@babel/plugin-transform-reserved-words": "npm:^7.23.3" @@ -1418,7 +1418,7 @@ __metadata: semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 36b02a86817ab5474bb74a8d62a110723b0b05904a52ddc5627cf89457525b8d5ac0739b8e435a6ae12ef8b90cd5fc191169898c3dc2ac9d2c84026b02f2580a + checksum: 2a0e1274dec045186e131c6433659b75492583290e8d41633c616f6bff829cb2e4b2f9a57f556283a54db3bd6aa697911e56a36f607911a29b731c445a5b5a06 languageName: node linkType: hard @@ -1502,32 +1502,32 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:7, @babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/traverse@npm:7.23.3" +"@babel/traverse@npm:7, @babel/traverse@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/traverse@npm:7.23.5" dependencies: - "@babel/code-frame": "npm:^7.22.13" - "@babel/generator": "npm:^7.23.3" + "@babel/code-frame": "npm:^7.23.5" + "@babel/generator": "npm:^7.23.5" "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-function-name": "npm:^7.23.0" "@babel/helper-hoist-variables": "npm:^7.22.5" "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.23.3" - "@babel/types": "npm:^7.23.3" + "@babel/parser": "npm:^7.23.5" + "@babel/types": "npm:^7.23.5" debug: "npm:^4.1.0" globals: "npm:^11.1.0" - checksum: 3c2784f4765185126d64fd5eebce0413b7aee6d54f779998594a343a7f973a9693a441ba27533df84e7ab7ce22f1239c6837f35e903132a1b25f7fc7a67bc30f + checksum: c5ea793080ca6719b0a1612198fd25e361cee1f3c14142d7a518d2a1eeb5c1d21f7eec1b26c20ea6e1ddd8ed12ab50b960ff95ffd25be353b6b46e1b54d6f825 languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.3, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": - version: 7.23.3 - resolution: "@babel/types@npm:7.23.3" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.5, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.23.5 + resolution: "@babel/types@npm:7.23.5" dependencies: - "@babel/helper-string-parser": "npm:^7.22.5" + "@babel/helper-string-parser": "npm:^7.23.4" "@babel/helper-validator-identifier": "npm:^7.22.20" to-fast-properties: "npm:^2.0.0" - checksum: 371a10dd9c8d8ebf48fc5d9e1b327dafd74453f8ea582dcbddd1cee5ae34e8881b743e783a86c08c04dcd1849b1842455472a911ae8a1c185484fe9b7b5f1595 + checksum: 7dd5e2f59828ed046ad0b06b039df2524a8b728d204affb4fc08da2502b9dd3140b1356b5166515d229dc811539a8b70dcd4bc507e06d62a89f4091a38d0b0fb languageName: node linkType: hard From e6fd9a59e6f7a37fcd1276c75aadfddd79c784ca Mon Sep 17 00:00:00 2001 From: Filippo Giunchedi Date: Thu, 30 Nov 2023 11:58:40 +0100 Subject: [PATCH 40/40] Fix FamiliarFollowersController test response comparison (#28121) Co-authored-by: Filippo Giunchedi --- .../api/v1/accounts/familiar_followers_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/controllers/api/v1/accounts/familiar_followers_controller_spec.rb b/spec/controllers/api/v1/accounts/familiar_followers_controller_spec.rb index 226177309..3c7c7e8b8 100644 --- a/spec/controllers/api/v1/accounts/familiar_followers_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/familiar_followers_controller_spec.rb @@ -28,7 +28,7 @@ describe Api::V1::Accounts::FamiliarFollowersController do account_ids = [account_a, account_b, account_b, account_a, account_a].map { |a| a.id.to_s } get :index, params: { id: account_ids } - expect(body_as_json.pluck(:id)).to eq [account_a.id.to_s, account_b.id.to_s] + expect(body_as_json.pluck(:id)).to contain_exactly(account_a.id.to_s, account_b.id.to_s) end end end