- {hasTimeRange && · - }
+ · {timestamp}
diff --git a/app/javascript/mastodon/locales/cy.json b/app/javascript/mastodon/locales/cy.json
index ffe15f538f..d7585b4ac2 100644
--- a/app/javascript/mastodon/locales/cy.json
+++ b/app/javascript/mastodon/locales/cy.json
@@ -457,6 +457,7 @@
"keyboard_shortcuts.toggle_hidden": "Dangos/cuddio testun tu ĂŽl i CW",
"keyboard_shortcuts.toggle_sensitivity": "Dangos/cuddio cyfryngau",
"keyboard_shortcuts.toot": "Dechrau post newydd",
+ "keyboard_shortcuts.translate": "i gyfieithu postiad",
"keyboard_shortcuts.unfocus": "Dad-ffocysu ardal cyfansoddi testun/chwilio",
"keyboard_shortcuts.up": "Symud yn uwch yn y rhestr",
"lightbox.close": "Cau",
@@ -835,6 +836,7 @@
"status.reblogs.empty": "Does neb wedi hybio'r post yma eto. Pan y bydd rhywun yn gwneud, byddent yn ymddangos yma.",
"status.redraft": "Dileu ac ailddrafftio",
"status.remove_bookmark": "Tynnu nod tudalen",
+ "status.remove_favourite": "Tynnu o'r ffefrynnau",
"status.replied_in_thread": "Atebodd mewn edefyn",
"status.replied_to": "Wedi ateb {name}",
"status.reply": "Ateb",
diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json
index 92cfb62f51..ad81e5f35a 100644
--- a/app/javascript/mastodon/locales/da.json
+++ b/app/javascript/mastodon/locales/da.json
@@ -482,6 +482,7 @@
"lists.exclusive": "Skjul medlemmer i Hjem",
"lists.exclusive_hint": "Er nogen er pÄ denne liste, skjul personen i hjemme-feeds for at undgÄ at se vedkommendes indlÊg to gange.",
"lists.find_users_to_add": "Find brugere at tilfĂžje",
+ "lists.list_members": "Liste over medlemmer",
"lists.list_members_count": "{count, plural, one {# medlem} other {# medlemmer}}",
"lists.list_name": "Listetitel",
"lists.new_list_name": "Ny listetitel",
diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json
index c4d5f7296a..91acfb0e15 100644
--- a/app/javascript/mastodon/locales/fo.json
+++ b/app/javascript/mastodon/locales/fo.json
@@ -362,6 +362,7 @@
"footer.privacy_policy": "PrivatlĂvspolitikkur",
"footer.source_code": "VĂs keldukotuna",
"footer.status": "StÞða",
+ "footer.terms_of_service": "TĂŠnastutreytir",
"generic.saved": "Goymt",
"getting_started.heading": "At byrja",
"hashtag.admin_moderation": "Lat umsjĂłnarmarkamĂłt upp fyri #{name}",
@@ -858,6 +859,7 @@
"subscribed_languages.target": "Broyt haldaramĂĄl fyri {target}",
"tabs_bar.home": "Heim",
"tabs_bar.notifications": "FrĂĄboĂ°anir",
+ "terms_of_service.title": "TĂŠnastutreytir",
"time_remaining.days": "{number, plural, one {# dagur} other {# dagar}} eftir",
"time_remaining.hours": "{number, plural, one {# tĂmi} other {# tĂmar}} eftir",
"time_remaining.minutes": "{number, plural, one {# minuttur} other {# minuttir}} eftir",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index d1ae388675..847f7871fa 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -453,10 +453,11 @@
"keyboard_shortcuts.requests": "Követési kérések liståjånak megnyitåsa",
"keyboard_shortcuts.search": "FĂłkuszĂĄlĂĄs a keresĆsĂĄvra",
"keyboard_shortcuts.spoilers": "Tartalmi figyelmeztetĂ©s mezĆ megjelenĂtĂ©se/elrejtĂ©se",
- "keyboard_shortcuts.start": "\"ElsĆ lĂ©pĂ©sek\" oszlop megnyitĂĄsa",
+ "keyboard_shortcuts.start": "âElsĆ lĂ©pĂ©sekâ oszlop megnyitĂĄsa",
"keyboard_shortcuts.toggle_hidden": "Tartalmi figyelmeztetĂ©ssel ellĂĄtott szöveg megjelenĂtĂ©se/elrejtĂ©se",
"keyboard_shortcuts.toggle_sensitivity": "MĂ©dia megjelenĂtĂ©se/elrejtĂ©se",
"keyboard_shortcuts.toot": "Ăj bejegyzĂ©s ĂrĂĄsa",
+ "keyboard_shortcuts.translate": "BejegyzĂ©s lefordĂtĂĄsa",
"keyboard_shortcuts.unfocus": "Szerkesztés/keresés fókuszból való kivétele",
"keyboard_shortcuts.up": "Mozgås felfelé a liståban",
"lightbox.close": "BezĂĄrĂĄs",
diff --git a/app/javascript/mastodon/locales/ia.json b/app/javascript/mastodon/locales/ia.json
index 0b17e60710..e2f821022e 100644
--- a/app/javascript/mastodon/locales/ia.json
+++ b/app/javascript/mastodon/locales/ia.json
@@ -457,6 +457,7 @@
"keyboard_shortcuts.toggle_hidden": "Monstrar/celar texto detra advertimento de contento",
"keyboard_shortcuts.toggle_sensitivity": "Monstrar/celar multimedia",
"keyboard_shortcuts.toot": "Initiar un nove message",
+ "keyboard_shortcuts.translate": "a traducer un message",
"keyboard_shortcuts.unfocus": "Disfocalisar le area de composition de texto/de recerca",
"keyboard_shortcuts.up": "Displaciar in alto in le lista",
"lightbox.close": "Clauder",
@@ -836,6 +837,7 @@
"status.reblogs.empty": "Necuno ha ancora impulsate iste message. Quando alcuno lo face, le impulsos apparera hic.",
"status.redraft": "Deler e reconciper",
"status.remove_bookmark": "Remover marcapagina",
+ "status.remove_favourite": "Remover del favoritos",
"status.replied_in_thread": "Respondite in le discussion",
"status.replied_to": "Respondite a {name}",
"status.reply": "Responder",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index 9593744e4b..abaf40931c 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -414,6 +414,7 @@
"interaction_modal.title.reblog": "{name} ëì êČìëŹŒì ë¶ì€íž",
"interaction_modal.title.reply": "{name} ëì êČìëŹŒì ë”êž",
"interaction_modal.title.vote": "{name} ëì íŹíì ì°žìŹ",
+ "interaction_modal.username_prompt": "ìì: {example}",
"intervals.full.days": "{number} ìŒ",
"intervals.full.hours": "{number} ìê°",
"intervals.full.minutes": "{number} ë¶",
diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json
index 1bc3c68382..9244f3509c 100644
--- a/app/javascript/mastodon/locales/lv.json
+++ b/app/javascript/mastodon/locales/lv.json
@@ -52,7 +52,7 @@
"account.mute_notifications_short": "IzslÄgt paziĆojumu skaĆu",
"account.mute_short": "ApklusinÄt",
"account.muted": "ApklusinÄts",
- "account.mutual": "SavstarpÄjs",
+ "account.mutual": "AbpusÄji",
"account.no_bio": "Apraksts nav sniegts.",
"account.open_original_page": "AtvÄrt oriÄŁinÄlo lapu",
"account.posts": "Ieraksti",
@@ -85,6 +85,7 @@
"alert.rate_limited.title": "BieĆŸums ierobeĆŸots",
"alert.unexpected.message": "RadÄs negaidÄ«ta kÄŒĆ«da.",
"alert.unexpected.title": "Ups!",
+ "alt_text_badge.title": "Alt teksts",
"announcement.announcement": "PaziĆojums",
"annual_report.summary.archetype.oracle": "OrÄkuls",
"annual_report.summary.archetype.replier": "Sabiedriskais tauriĆĆĄ",
diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json
index 6091f1679f..1a7f92be18 100644
--- a/app/javascript/mastodon/locales/nn.json
+++ b/app/javascript/mastodon/locales/nn.json
@@ -837,6 +837,7 @@
"status.reblogs.empty": "Ingen har framheva dette tutet enno. Om nokon gjer, sÄ dukkar det opp her.",
"status.redraft": "Slett & skriv pÄ nytt",
"status.remove_bookmark": "Fjern bokmerke",
+ "status.remove_favourite": "Fjern frÄ favorittar",
"status.replied_in_thread": "Svara i trÄden",
"status.replied_to": "Svarte {name}",
"status.reply": "Svar",
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index fe56267ea1..f9cb9743ac 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -406,6 +406,9 @@
"ignore_notifications_modal.not_followers_title": "Ignoruj powiadomienia od uĆŒytkownikĂłw ktĂłrzy ciÄ nie obserwujÄ
?",
"ignore_notifications_modal.not_following_title": "Ignoruj powiadomienia od uĆŒytkownikĂłw ktĂłrych nie obserwujesz?",
"ignore_notifications_modal.private_mentions_title": "Ignoruj powiadomienia o nieproszonych wzmiankach prywatnych?",
+ "interaction_modal.action.favourite": "Aby kontynuowaÄ, musisz dodaÄ do ulubionych na swoim koncie.",
+ "interaction_modal.action.follow": "Aby kontynuowaÄ, musisz obserwowaÄ ze swojego konta.",
+ "interaction_modal.no_account_yet": "Nie masz jeszcze konta?",
"interaction_modal.on_another_server": "Na innym serwerze",
"interaction_modal.on_this_server": "Na tym serwerze",
"interaction_modal.title.favourite": "Polub wpis uĆŒytkownika {name}",
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index 1505d333ba..142ae33c58 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -243,12 +243,12 @@
"dismissable_banner.explore_statuses": "Estas publicaçÔes através do fediverse estão ganhando atenção hoje. PublicaçÔes mais recentes com mais boosts e favoritos são classificados mais altamente.",
"dismissable_banner.explore_tags": "Estas hashtags estão ganhando atenção hoje no fediverse. Hashtags usadas por muitas pessoas diferentes são classificadas mais altamente.",
"dismissable_banner.public_timeline": "Estas são as publicaçÔes mais recentes das pessoas no fediverse que as pessoas do {domain} seguem.",
- "domain_block_modal.block": "Servidor de blocos.",
- "domain_block_modal.block_account_instead": "Bloco @(nome)",
+ "domain_block_modal.block": "Bloquear servidor",
+ "domain_block_modal.block_account_instead": "Bloquear @{name}",
"domain_block_modal.they_can_interact_with_old_posts": "Pessoas deste servidor podem interagir com suas publicaçÔes antigas.",
"domain_block_modal.they_cant_follow": "Ninguém deste servidor pode lhe seguir.",
"domain_block_modal.they_wont_know": "Eles nĂŁo saberĂŁo que foram bloqueados.",
- "domain_block_modal.title": "Dominio do bloco",
+ "domain_block_modal.title": "Bloquear domĂnio?",
"domain_block_modal.you_will_lose_num_followers": "VocĂȘ perderĂĄ {followersCount, plural, one {{followersCountDisplay} seguidor} other {{followersCountDisplay} seguidores}} e {followingCount, plural, one {{followingCountDisplay} pessoa que vocĂȘ segue} other {{followingCountDisplay} pessoas que vocĂȘ segue}}.",
"domain_block_modal.you_will_lose_relationships": "VocĂȘ irĂĄ perder todos os seguidores e pessoas que vocĂȘ segue neste servidor.",
"domain_block_modal.you_wont_see_posts": "VocĂȘ nĂŁo verĂĄ postagens ou notificaçÔes de usuĂĄrios neste servidor.",
diff --git a/app/javascript/mastodon/locales/pt-PT.json b/app/javascript/mastodon/locales/pt-PT.json
index ade10fc478..f7329ad97e 100644
--- a/app/javascript/mastodon/locales/pt-PT.json
+++ b/app/javascript/mastodon/locales/pt-PT.json
@@ -85,7 +85,7 @@
"alert.rate_limited.title": "Limite de tentativas",
"alert.unexpected.message": "Ocorreu um erro inesperado.",
"alert.unexpected.title": "Bolas!",
- "alt_text_badge.title": "Texto alternativo",
+ "alt_text_badge.title": "Texto descritivo",
"announcement.announcement": "Mensagem de manutenção",
"annual_report.summary.archetype.booster": "O caçador de frescura",
"annual_report.summary.archetype.lurker": "O espreitador",
@@ -244,7 +244,7 @@
"dismissable_banner.explore_tags": "Estas etiquetas estão a ganhar força no fediverso atualmente. As etiquetas que são utilizadas por mais pessoas diferentes são classificadas numa posição mais elevada.",
"dismissable_banner.public_timeline": "Estas sĂŁo as publicaçÔes pĂșblicas mais recentes de pessoas no fediverso que as pessoas em {domain} seguem.",
"domain_block_modal.block": "Bloquear servidor",
- "domain_block_modal.block_account_instead": "Bloquear antes @{name}",
+ "domain_block_modal.block_account_instead": "Em vez disso, bloquear @{name}",
"domain_block_modal.they_can_interact_with_old_posts": "As pessoas deste servidor podem interagir com as tuas publicaçÔes antigas.",
"domain_block_modal.they_cant_follow": "Ninguém deste servidor pode seguir-te.",
"domain_block_modal.they_wont_know": "Eles nĂŁo saberĂŁo que foram bloqueados.",
@@ -260,7 +260,7 @@
"domain_pill.their_username": "O identificador Ășnico dele no seu servidor. Ă possĂvel encontrar utilizadores com o mesmo nome de utilizador em servidores diferentes.",
"domain_pill.username": "Nome de utilizador",
"domain_pill.whats_in_a_handle": "Em que consiste um identificador?",
- "domain_pill.who_they_are": "Uma vez que os identificadores dizem quem é alguém e onde estå, pode interagir com as pessoas através da rede social de
plataformas que suportam ActivityPub .",
+ "domain_pill.who_they_are": "Uma vez que os identificadores dizem quem é alguém e onde estå, podes interagir com as pessoas através da rede social de
plataformas que suportam ActivityPub .",
"domain_pill.who_you_are": "Uma vez que o teu identificador indica quem és e onde estås, as pessoas podem interagir contigo através da rede social de
plataformas que suportam ActivityPub .",
"domain_pill.your_handle": "O teu identificador:",
"domain_pill.your_server": "A tua casa digital, onde se encontram todas as tuas publicaçÔes. Não gostas deste? Muda de servidor a qualquer momento e leva também os teus seguidores.",
@@ -457,6 +457,7 @@
"keyboard_shortcuts.toggle_hidden": "mostrar / esconder texto atrĂĄs do aviso de conteĂșdo",
"keyboard_shortcuts.toggle_sensitivity": "mostrar / ocultar multimédia",
"keyboard_shortcuts.toot": "criar uma nova publicação",
+ "keyboard_shortcuts.translate": "traduzir uma publicação",
"keyboard_shortcuts.unfocus": "remover o foco da ĂĄrea de texto / pesquisa",
"keyboard_shortcuts.up": "mover para cima na lista",
"lightbox.close": "Fechar",
@@ -641,10 +642,10 @@
"notifications.policy.filter_hint": "Enviar para a caixa de notificaçÔes filtradas",
"notifications.policy.filter_limited_accounts_hint": "Limitado pelos moderadores do servidor",
"notifications.policy.filter_limited_accounts_title": "Contas moderadas",
- "notifications.policy.filter_new_accounts.hint": "Criada {days, plural, one {no Ășltimo dia} other {nos Ășltimos # dias}}",
+ "notifications.policy.filter_new_accounts.hint": "Criadas {days, plural, one {no Ășltimo dia} other {nos Ășltimos # dias}}",
"notifications.policy.filter_new_accounts_title": "Novas contas",
"notifications.policy.filter_not_followers_hint": "Incluindo pessoas que te seguem hĂĄ menos de {days, plural, one {um dia} other {# dias}}",
- "notifications.policy.filter_not_followers_title": "Pessoas nĂŁo te seguem",
+ "notifications.policy.filter_not_followers_title": "Pessoas que nĂŁo te seguem",
"notifications.policy.filter_not_following_hint": "Até que os aproves manualmente",
"notifications.policy.filter_not_following_title": "Pessoas que nĂŁo segues",
"notifications.policy.filter_private_mentions_hint": "Filtrado, a não ser que seja em resposta à tua própria menção ou se seguires o remetente",
@@ -836,6 +837,7 @@
"status.reblogs.empty": "Ainda ninguém impulsionou esta publicação. Quando alguém o fizer, aparecerå aqui.",
"status.redraft": "Eliminar e reescrever",
"status.remove_bookmark": "Retirar dos marcadores",
+ "status.remove_favourite": "Remover dos favoritos",
"status.replied_in_thread": "Responder na conversa",
"status.replied_to": "Respondeu a {name}",
"status.reply": "Responder",
diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json
index d53825295f..f451caf6f9 100644
--- a/app/javascript/mastodon/locales/sv.json
+++ b/app/javascript/mastodon/locales/sv.json
@@ -141,7 +141,7 @@
"column.bookmarks": "BokmÀrken",
"column.community": "Lokal tidslinje",
"column.create_list": "Skapa lista",
- "column.direct": "Privata nÀmningar",
+ "column.direct": "Privata omnÀmnande",
"column.directory": "BlÀddra bland profiler",
"column.domain_blocks": "Blockerade domÀner",
"column.edit_list": "Redigera lista",
@@ -239,6 +239,10 @@
"disabled_account_banner.text": "Ditt konto {disabledAccount} Àr för nÀrvarande inaktiverat.",
"dismissable_banner.community_timeline": "Dessa Àr de senaste offentliga inlÀggen frÄn personer vars konton tillhandahÄlls av {domain}.",
"dismissable_banner.dismiss": "AvfÀrda",
+ "dismissable_banner.explore_links": "Dessa nyhetshistorier delas mest pÄ fediversum idag. Nyare nyhetshistorier som publiceras av fler olika personer rankas högre.",
+ "dismissable_banner.explore_statuses": "Dessa inlÀgg frÄn fediversum vinner dragkraft idag. Nyare inlÀgg som mÄnga boostar och favoritmarkerar rankas högre.",
+ "dismissable_banner.explore_tags": "De hÀr hashtaggarna vinner dragkraft i fediversum idag. Hashtaggar som anvÀnds av fler olika personer rankas högre.",
+ "dismissable_banner.public_timeline": "De hÀr Àr de aktuella publika inlÀgg frÄn personer i fediversum som personer i {domain} följer.",
"domain_block_modal.block": "Blockera server",
"domain_block_modal.block_account_instead": "Blockera @{name} istÀllet",
"domain_block_modal.they_can_interact_with_old_posts": "Personer frÄn denna server kan interagera med dina gamla inlÀgg.",
@@ -285,7 +289,7 @@
"empty_column.blocks": "Du har Ànnu ej blockerat nÄgra anvÀndare.",
"empty_column.bookmarked_statuses": "Du har inte bokmÀrkt nÄgra inlÀgg Àn. NÀr du bokmÀrker ett inlÀgg kommer det synas hÀr.",
"empty_column.community": "Den lokala tidslinjen Àr tom. Skriv nÄgot offentligt för att sÀtta bollen i rullning!",
- "empty_column.direct": "Du har inga privata nÀmningar. NÀr du skickar eller tar emot ett direktmeddelande kommer det att visas hÀr.",
+ "empty_column.direct": "Du har inga privata omnÀmninande. NÀr du skickar eller tar emot ett direktmeddelande kommer det att visas hÀr.",
"empty_column.domain_blocks": "Det finns Ànnu inga dolda domÀner.",
"empty_column.explore_statuses": "Ingenting Àr trendigt just nu. Kom tillbaka senare!",
"empty_column.favourited_statuses": "Du har inga favoritmarkerade inlÀgg Ànnu. NÀr du favoritmÀrker ett sÄ kommer det att dyka upp hÀr.",
@@ -402,7 +406,14 @@
"ignore_notifications_modal.new_accounts_title": "Vill du ignorera aviseringar frÄn nya konton?",
"ignore_notifications_modal.not_followers_title": "Vill du ignorera aviseringar frÄn personer som inte följer dig?",
"ignore_notifications_modal.not_following_title": "Vill du blockera aviseringar frÄn personer som du inte följer dig?",
- "ignore_notifications_modal.private_mentions_title": "Vill du ignorera aviseringar frÄn oönskade privata omnÀmningar?",
+ "ignore_notifications_modal.private_mentions_title": "Vill du ignorera aviseringar frÄn oombedda privata omnÀmnanden?",
+ "interaction_modal.action.favourite": "För att fortsÀtta, mÄste du favoritmarkera frÄn ditt konto.",
+ "interaction_modal.action.follow": "För att fortsÀtta, mÄste du följa frÄn ditt konto.",
+ "interaction_modal.action.reblog": "För att fortsÀtta, mÄste du boosta frÄn ditt konto.",
+ "interaction_modal.action.reply": "För att fortsÀtta, mÄste du svara frÄn ditt konto.",
+ "interaction_modal.action.vote": "För att fortsÀtta, mÄste du rösta frÄn ditt konto.",
+ "interaction_modal.go": "Vidare",
+ "interaction_modal.no_account_yet": "Har du inget konto Àn?",
"interaction_modal.on_another_server": "PĂ„ en annan server",
"interaction_modal.on_this_server": "PĂ„ denna server",
"interaction_modal.title.favourite": "Favoritmarkera {name}s inlÀgg",
@@ -410,6 +421,7 @@
"interaction_modal.title.reblog": "Boosta {name}s inlÀgg",
"interaction_modal.title.reply": "Svara pÄ {name}s inlÀgg",
"interaction_modal.title.vote": "Rösta i {name}s enkÀt",
+ "interaction_modal.username_prompt": "T.ex. {example}",
"intervals.full.days": "{number, plural, one {# dag} other {# dagar}}",
"intervals.full.hours": "{number, plural, one {# timme} other {# timmar}}",
"intervals.full.minutes": "{number, plural, one {# minut} other {# minuter}}",
@@ -419,7 +431,7 @@
"keyboard_shortcuts.column": "Fokusera kolumn",
"keyboard_shortcuts.compose": "Fokusera skrivfÀltet",
"keyboard_shortcuts.description": "Beskrivning",
- "keyboard_shortcuts.direct": "för att öppna privata nÀmningskolumnen",
+ "keyboard_shortcuts.direct": "för att öppna privata omnÀmnandekolumnen",
"keyboard_shortcuts.down": "Flytta ner i listan",
"keyboard_shortcuts.enter": "Ăppna inlĂ€gg",
"keyboard_shortcuts.favourite": "Favoritmarkera inlÀgg",
@@ -445,6 +457,7 @@
"keyboard_shortcuts.toggle_hidden": "Visa/gömma text bakom CW",
"keyboard_shortcuts.toggle_sensitivity": "Visa/gömma media",
"keyboard_shortcuts.toot": "Starta nytt inlÀgg",
+ "keyboard_shortcuts.translate": "för att översÀtta ett inlÀgg",
"keyboard_shortcuts.unfocus": "Avfokusera skrivfÀlt/sökfÀlt",
"keyboard_shortcuts.up": "Flytta uppÄt i listan",
"lightbox.close": "StÀng",
@@ -466,6 +479,7 @@
"lists.delete": "Radera lista",
"lists.done": "Klar",
"lists.edit": "Redigera lista",
+ "lists.exclusive": "Dölj medlemmar i Hem flödet",
"lists.exclusive_hint": "Om nÄgon Àr med pÄ den hÀr listan, göm dem i ditt Hemtidlinje för att undvika att se deras inlÀgg tvÄ gÄnger.",
"lists.find_users_to_add": "Hitta anvÀndare att lÀgga till",
"lists.list_members": "Lista medlemmar",
@@ -474,12 +488,14 @@
"lists.new_list_name": "Nytt listnamn",
"lists.no_lists_yet": "Ănnu inga listor.",
"lists.no_members_yet": "Inga medlemmar Ànnu.",
+ "lists.no_results_found": "Inga resultat hittades.",
"lists.remove_member": "Ta bort",
"lists.replies_policy.followed": "Alla anvÀndare som följs",
"lists.replies_policy.list": "Medlemmar i listan",
"lists.replies_policy.none": "Ingen",
"lists.save": "Spara",
"lists.search": "Sök",
+ "lists.show_replies_to": "Inkludera svar frÄn listmedlemmar till",
"load_pending": "{count, plural, one {# nytt objekt} other {# nya objekt}}",
"loading_indicator.label": "LaddarâŠ",
"media_gallery.hide": "Dölj",
@@ -500,7 +516,7 @@
"navigation_bar.bookmarks": "BokmÀrken",
"navigation_bar.community_timeline": "Lokal tidslinje",
"navigation_bar.compose": "Författa nytt inlÀgg",
- "navigation_bar.direct": "Privata nÀmningar",
+ "navigation_bar.direct": "Privata omnÀmnande",
"navigation_bar.discover": "UpptÀck",
"navigation_bar.domain_blocks": "Dolda domÀner",
"navigation_bar.explore": "Utforska",
@@ -532,12 +548,14 @@
"notification.annual_report.view": "Visa #Wrapstodon",
"notification.favourite": "{name} favoritmarkerade ditt inlÀgg",
"notification.favourite.name_and_others_with_link": "{name} och
{count, plural, one {# annan} other {# andra}} har favoritmarkerat ditt inlÀgg",
+ "notification.favourite_pm": "{name} favoritmarkerade ditt privata omnÀmnande",
+ "notification.favourite_pm.name_and_others_with_link": "{name} och
{count, plural, one {# annan} other {# andra}} favoritmarkerade ditt privata omnÀmnande",
"notification.follow": "{name} följer dig",
"notification.follow.name_and_others": "{name} och
{count, plural, one {# annan} other {# andra}} följer dig",
"notification.follow_request": "{name} har begÀrt att följa dig",
"notification.follow_request.name_and_others": "{name} och {count, plural, one {# en annan} other {# andra}} har bett att följa dig",
"notification.label.mention": "NĂ€mn",
- "notification.label.private_mention": "Privat nÀmning",
+ "notification.label.private_mention": "Privat omnÀmnande",
"notification.label.private_reply": "Privata svar",
"notification.label.reply": "Svar",
"notification.mention": "NĂ€mn",
@@ -640,6 +658,7 @@
"onboarding.follows.done": "FĂ€rdig",
"onboarding.follows.empty": "TyvÀrr kan inga resultat visas just nu. Du kan prova att anvÀnda sökfunktionen eller utforska sidan för att hitta personer att följa, eller försök igen senare.",
"onboarding.follows.search": "Sök",
+ "onboarding.follows.title": "Följ mÀnniskor för att komma igÄng",
"onboarding.profile.discoverable": "Gör min profil upptÀckbar",
"onboarding.profile.discoverable_hint": "NÀr du vÀljer att vara upptÀckbar pÄ Mastodon kan dina inlÀgg visas i sök- och trendresultat, och din profil kan föreslÄs för personer med liknande intressen som du.",
"onboarding.profile.display_name": "Visningsnamn",
@@ -677,6 +696,8 @@
"privacy_policy.title": "Integritetspolicy",
"recommended": "Rekommenderas",
"refresh": "LĂ€s om",
+ "regeneration_indicator.please_stand_by": "VÀnligen vÀnta.",
+ "regeneration_indicator.preparing_your_home_feed": "Förbereder ditt hemflödeâŠ",
"relative_time.days": "{number}d",
"relative_time.full.days": "{number, plural, one {# dag} other {# dagar}} sedan",
"relative_time.full.hours": "{number, plural, one {# timme} other {# timmar}} sedan",
@@ -760,15 +781,18 @@
"search_results.accounts": "Profiler",
"search_results.all": "Alla",
"search_results.hashtags": "Hashtaggar",
+ "search_results.no_results": "Inga resultat.",
+ "search_results.no_search_yet": "Prova att söka efter inlÀgg, profiler eller hashtags.",
"search_results.see_all": "Visa alla",
"search_results.statuses": "InlÀgg",
+ "search_results.title": "Sök efter \"{q}\"",
"server_banner.about_active_users": "Personer som anvÀnt denna server de senaste 30 dagarna (mÄnatligt aktiva anvÀndare)",
"server_banner.active_users": "aktiva anvÀndare",
"server_banner.administered_by": "Administrerad av:",
"server_banner.is_one_of_many": "{domain} Àr en av de mÄnga oberoende Mastodon-servrar som du kan anvÀnda för att delta i Fediversen.",
"server_banner.server_stats": "Serverstatistik:",
"sign_in_banner.create_account": "Skapa konto",
- "sign_in_banner.follow_anyone": "Följ vem som helst över Fediverse och se allt i kronologisk ordning. Inga algoritmer, inga annonser och inga klickbeten i sikte.",
+ "sign_in_banner.follow_anyone": "Följ vem som helst över Fediversum och se allt i kronologisk ordning. Inga algoritmer, annonser eller klickbeten i sikte.",
"sign_in_banner.mastodon_is": "Mastodon Àr det bÀsta sÀttet att hÀnga med i vad som hÀnder.",
"sign_in_banner.sign_in": "Logga in",
"sign_in_banner.sso_redirect": "Logga in eller registrera dig",
@@ -783,8 +807,8 @@
"status.copy": "Kopiera inlÀggslÀnk",
"status.delete": "Radera",
"status.detailed_status": "Detaljerad samtalsvy",
- "status.direct": "NĂ€mn @{name} privat",
- "status.direct_indicator": "Privat nÀmning",
+ "status.direct": "OmnÀmn @{name} privat",
+ "status.direct_indicator": "Privat omnÀmnande",
"status.edit": "Redigera",
"status.edited": "Senast Àndrad {date}",
"status.edited_x_times": "Redigerad {count, plural, one {{count} gÄng} other {{count} gÄnger}}",
@@ -813,6 +837,7 @@
"status.reblogs.empty": "Ingen har boostat detta inlÀgg Àn. NÀr nÄgon gör det kommer de synas hÀr.",
"status.redraft": "Radera & gör om",
"status.remove_bookmark": "Ta bort bokmÀrke",
+ "status.remove_favourite": "Ta bort frÄn Favoriter",
"status.replied_in_thread": "Svarade i trÄden",
"status.replied_to": "Svarade pÄ {name}",
"status.reply": "Svara",
@@ -834,6 +859,7 @@
"subscribed_languages.target": "Ăndra sprĂ„kprenumerationer för {target}",
"tabs_bar.home": "Hem",
"tabs_bar.notifications": "Aviseringar",
+ "terms_of_service.title": "AnvÀndarvillkor",
"time_remaining.days": "{number, plural, one {# dag} other {# dagar}} kvar",
"time_remaining.hours": "{number, plural, one {# timme} other {# timmar}} kvar",
"time_remaining.minutes": "{number, plural, one {# minut} other {# minuter}} kvar",
diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss
index d79ab2aa21..82c53de5f7 100644
--- a/app/javascript/styles/mastodon/forms.scss
+++ b/app/javascript/styles/mastodon/forms.scss
@@ -659,6 +659,10 @@ code {
}
}
}
+
+ .status-card {
+ contain: unset;
+ }
}
.block-icon {
diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb
index 23b44be372..a489928407 100644
--- a/app/lib/activitypub/tag_manager.rb
+++ b/app/lib/activitypub/tag_manager.rb
@@ -13,7 +13,7 @@ class ActivityPub::TagManager
}.freeze
def public_collection?(uri)
- uri == COLLECTIONS[:public] || uri == 'as:Public' || uri == 'Public'
+ uri == COLLECTIONS[:public] || %w(as:Public Public).include?(uri)
end
def url_for(target)
diff --git a/app/lib/application_extension.rb b/app/lib/application_extension.rb
index d7aaeba5bd..d8090d15bc 100644
--- a/app/lib/application_extension.rb
+++ b/app/lib/application_extension.rb
@@ -3,14 +3,18 @@
module ApplicationExtension
extend ActiveSupport::Concern
+ APP_NAME_LIMIT = 60
+ APP_REDIRECT_URI_LIMIT = 2_000
+ APP_WEBSITE_LIMIT = 2_000
+
included do
include Redisable
has_many :created_users, class_name: 'User', foreign_key: 'created_by_application_id', inverse_of: :created_by_application
- validates :name, length: { maximum: 60 }
- validates :website, url: true, length: { maximum: 2_000 }, if: :website?
- validates :redirect_uri, length: { maximum: 2_000 }
+ validates :name, length: { maximum: APP_NAME_LIMIT }
+ validates :redirect_uri, length: { maximum: APP_REDIRECT_URI_LIMIT }
+ validates :website, url: true, length: { maximum: APP_WEBSITE_LIMIT }, if: :website?
# The relationship used between Applications and AccessTokens is using
# dependent: delete_all, which means the ActiveRecord callback in
diff --git a/app/lib/request.rb b/app/lib/request.rb
index 3d2a0c0e31..f984f0e63e 100644
--- a/app/lib/request.rb
+++ b/app/lib/request.rb
@@ -111,16 +111,10 @@ class Request
end
begin
- # If we are using a persistent connection, we have to
- # read every response to be able to move forward at all.
- # However, simply calling #to_s or #flush may not be safe,
- # as the response body, if malicious, could be too big
- # for our memory. So we use the #body_with_limit method
- response.body_with_limit if http_client.persistent?
-
yield response if block_given?
ensure
- http_client.close unless http_client.persistent?
+ response.truncated_body if http_client.persistent? && !response.connection.finished_request?
+ http_client.close unless http_client.persistent? && response.connection.finished_request?
end
end
diff --git a/app/models/account.rb b/app/models/account.rb
index 9857746b0e..d332edc149 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -107,23 +107,23 @@ class Account < ApplicationRecord
validates_with UniqueUsernameValidator, if: -> { will_save_change_to_username? }
# Remote user validations, also applies to internal actors
- validates :username, format: { with: USERNAME_ONLY_RE }, if: -> { (!local? || actor_type == 'Application') && will_save_change_to_username? }
+ validates :username, format: { with: USERNAME_ONLY_RE }, if: -> { (remote? || actor_type_application?) && will_save_change_to_username? }
# Remote user validations
validates :uri, presence: true, unless: :local?, on: :create
# Local user validations
- validates :username, format: { with: /\A[a-z0-9_]+\z/i }, length: { maximum: USERNAME_LENGTH_LIMIT }, if: -> { local? && will_save_change_to_username? && actor_type != 'Application' }
- validates_with UnreservedUsernameValidator, if: -> { local? && will_save_change_to_username? && actor_type != 'Application' }
+ validates :username, format: { with: /\A[a-z0-9_]+\z/i }, length: { maximum: USERNAME_LENGTH_LIMIT }, if: -> { local? && will_save_change_to_username? && !actor_type_application? }
+ validates_with UnreservedUsernameValidator, if: -> { local? && will_save_change_to_username? && !actor_type_application? }
validates :display_name, length: { maximum: DISPLAY_NAME_LENGTH_LIMIT }, if: -> { local? && will_save_change_to_display_name? }
validates :note, note_length: { maximum: NOTE_LENGTH_LIMIT }, if: -> { local? && will_save_change_to_note? }
validates :fields, length: { maximum: DEFAULT_FIELDS_SIZE }, if: -> { local? && will_save_change_to_fields? }
validates_with EmptyProfileFieldNamesValidator, if: -> { local? && will_save_change_to_fields? }
- with_options on: :create do
- validates :uri, absence: true, if: :local?
- validates :inbox_url, absence: true, if: :local?
- validates :shared_inbox_url, absence: true, if: :local?
- validates :followers_url, absence: true, if: :local?
+ with_options on: :create, if: :local? do
+ validates :followers_url, absence: true
+ validates :inbox_url, absence: true
+ validates :shared_inbox_url, absence: true
+ validates :uri, absence: true
end
normalizes :username, with: ->(username) { username.squish }
@@ -186,6 +186,10 @@ class Account < ApplicationRecord
domain.nil?
end
+ def remote?
+ domain.present?
+ end
+
def moved?
moved_to_account_id.present?
end
@@ -204,6 +208,10 @@ class Account < ApplicationRecord
self.actor_type = ActiveModel::Type::Boolean.new.cast(val) ? 'Service' : 'Person'
end
+ def actor_type_application?
+ actor_type == 'Application'
+ end
+
def group?
actor_type == 'Group'
end
diff --git a/app/models/account_warning.rb b/app/models/account_warning.rb
index 7aa474887b..9058f73fb8 100644
--- a/app/models/account_warning.rb
+++ b/app/models/account_warning.rb
@@ -27,6 +27,7 @@ class AccountWarning < ApplicationRecord
suspend: 4_000,
}, suffix: :action
+ APPEAL_WINDOW = 20.days
RECENT_PERIOD = 3.months.freeze
normalizes :text, with: ->(text) { text.to_s }, apply_to_nil: true
@@ -49,6 +50,10 @@ class AccountWarning < ApplicationRecord
overruled_at.present?
end
+ def appeal_eligible?
+ created_at >= APPEAL_WINDOW.ago
+ end
+
def to_log_human_identifier
target_account.acct
end
diff --git a/app/models/appeal.rb b/app/models/appeal.rb
index fafa75e69d..6a75fec661 100644
--- a/app/models/appeal.rb
+++ b/app/models/appeal.rb
@@ -16,8 +16,6 @@
# updated_at :datetime not null
#
class Appeal < ApplicationRecord
- MAX_STRIKE_AGE = 20.days
-
TEXT_LENGTH_LIMIT = 2_000
belongs_to :account
@@ -68,6 +66,6 @@ class Appeal < ApplicationRecord
private
def validate_time_frame
- errors.add(:base, I18n.t('strikes.errors.too_late')) if strike.created_at < MAX_STRIKE_AGE.ago
+ errors.add(:base, I18n.t('strikes.errors.too_late')) unless strike.appeal_eligible?
end
end
diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb
index 32a649af40..5e84293111 100644
--- a/app/models/form/admin_settings.rb
+++ b/app/models/form/admin_settings.rb
@@ -84,6 +84,10 @@ class Form::AdminSettings
flavour_and_skin
).freeze
+ DIGEST_KEYS = %i(
+ custom_css
+ ).freeze
+
OVERRIDEN_SETTINGS = {
authorized_fetch: :authorized_fetch_mode?,
}.freeze
@@ -137,6 +141,8 @@ class Form::AdminSettings
KEYS.each do |key|
next if PSEUDO_KEYS.include?(key) || !instance_variable_defined?(:"@#{key}")
+ cache_digest_value(key) if DIGEST_KEYS.include?(key)
+
if UPLOAD_KEYS.include?(key)
public_send(key).save
else
@@ -156,6 +162,18 @@ class Form::AdminSettings
private
+ def cache_digest_value(key)
+ Rails.cache.delete(:"setting_digest_#{key}")
+
+ key_value = instance_variable_get(:"@#{key}")
+ if key_value.present?
+ Rails.cache.write(
+ :"setting_digest_#{key}",
+ Digest::SHA256.hexdigest(key_value)
+ )
+ end
+ end
+
def typecast_value(key, value)
if BOOLEAN_KEYS.include?(key)
value == '1'
diff --git a/app/models/notification_group.rb b/app/models/notification_group.rb
index 9331b9406f..bf790bf7cd 100644
--- a/app/models/notification_group.rb
+++ b/app/models/notification_group.rb
@@ -64,21 +64,31 @@ class NotificationGroup < ActiveModelSerializers::Model
binds = [
account_id,
SAMPLE_ACCOUNTS_SIZE,
- pagination_range.begin,
- pagination_range.end,
ActiveRecord::Relation::QueryAttribute.new('group_keys', group_keys, ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array.new(ActiveModel::Type::String.new)),
+ pagination_range.begin || 0,
]
+ binds << pagination_range.end unless pagination_range.end.nil?
+
+ upper_bound_cond = begin
+ if pagination_range.end.nil?
+ ''
+ elsif pagination_range.exclude_end?
+ 'AND id < $5'
+ else
+ 'AND id <= $5'
+ end
+ end
ActiveRecord::Base.connection.select_all(<<~SQL.squish, 'grouped_notifications', binds).cast_values.to_h { |k, *values| [k, values] }
SELECT
groups.group_key,
- (SELECT id FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key AND id <= $4 ORDER BY id DESC LIMIT 1),
- array(SELECT from_account_id FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key AND id <= $4 ORDER BY id DESC LIMIT $2),
- (SELECT count(*) FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key AND id <= $4) AS notifications_count,
- (SELECT id FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key AND id >= $3 ORDER BY id ASC LIMIT 1) AS min_id,
- (SELECT created_at FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key AND id <= $4 ORDER BY id DESC LIMIT 1)
+ (SELECT id FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key #{upper_bound_cond} ORDER BY id DESC LIMIT 1),
+ array(SELECT from_account_id FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key #{upper_bound_cond} ORDER BY id DESC LIMIT $2),
+ (SELECT count(*) FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key #{upper_bound_cond}) AS notifications_count,
+ (SELECT id FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key AND id >= $4 ORDER BY id ASC LIMIT 1) AS min_id,
+ (SELECT created_at FROM notifications WHERE notifications.account_id = $1 AND notifications.group_key = groups.group_key #{upper_bound_cond} ORDER BY id DESC LIMIT 1)
FROM
- unnest($5::text[]) AS groups(group_key);
+ unnest($3::text[]) AS groups(group_key);
SQL
else
binds = [
diff --git a/app/models/poll.rb b/app/models/poll.rb
index b4e0edcd0f..93ef0cc589 100644
--- a/app/models/poll.rb
+++ b/app/models/poll.rb
@@ -61,11 +61,7 @@ class Poll < ApplicationRecord
votes.where(account: account).pluck(:choice)
end
- delegate :local?, to: :account
-
- def remote?
- !local?
- end
+ delegate :local?, :remote?, to: :account
def emojis
@emojis ||= CustomEmoji.from_text(options.join(' '), account.domain)
diff --git a/app/models/trends/links.rb b/app/models/trends/links.rb
index 0f3ead43f8..57ad486631 100644
--- a/app/models/trends/links.rb
+++ b/app/models/trends/links.rb
@@ -16,7 +16,7 @@ class Trends::Links < Trends::Base
class Query < Trends::Query
def to_arel
scope = PreviewCard.joins(:trend).reorder(score: :desc)
- scope = scope.reorder(language_order_clause.desc, score: :desc) if preferred_languages.present?
+ scope = scope.merge(language_order_clause) if preferred_languages.present?
scope = scope.merge(PreviewCardTrend.allowed) if @allowed
scope = scope.offset(@offset) if @offset.present?
scope = scope.limit(@limit) if @limit.present?
@@ -26,7 +26,7 @@ class Trends::Links < Trends::Base
private
def language_order_clause
- Arel::Nodes::Case.new.when(PreviewCardTrend.arel_table[:language].in(preferred_languages)).then(1).else(0)
+ language_order_for(PreviewCardTrend)
end
end
diff --git a/app/models/trends/query.rb b/app/models/trends/query.rb
index 590e81f4fd..abed64042e 100644
--- a/app/models/trends/query.rb
+++ b/app/models/trends/query.rb
@@ -94,6 +94,13 @@ class Trends::Query
to_arel.to_a
end
+ def language_order_for(trend_class)
+ trend_class
+ .reorder(nil)
+ .in_order_of(:language, [preferred_languages], filter: false)
+ .order(score: :desc)
+ end
+
def preferred_languages
if @account&.chosen_languages.present?
@account.chosen_languages
diff --git a/app/models/trends/statuses.rb b/app/models/trends/statuses.rb
index 66dab4519f..29f31f1969 100644
--- a/app/models/trends/statuses.rb
+++ b/app/models/trends/statuses.rb
@@ -15,7 +15,7 @@ class Trends::Statuses < Trends::Base
class Query < Trends::Query
def to_arel
scope = Status.joins(:trend).reorder(score: :desc)
- scope = scope.reorder(language_order_clause.desc, score: :desc) if preferred_languages.present?
+ scope = scope.merge(language_order_clause) if preferred_languages.present?
scope = scope.merge(StatusTrend.allowed) if @allowed
scope = scope.not_excluded_by_account(@account).not_domain_blocked_by_account(@account) if @account.present?
scope = scope.offset(@offset) if @offset.present?
@@ -26,7 +26,7 @@ class Trends::Statuses < Trends::Base
private
def language_order_clause
- Arel::Nodes::Case.new.when(StatusTrend.arel_table[:language].in(preferred_languages)).then(1).else(0)
+ language_order_for(StatusTrend)
end
end
diff --git a/app/models/trends/tags.rb b/app/models/trends/tags.rb
index 18f2a9a949..84e8dde11a 100644
--- a/app/models/trends/tags.rb
+++ b/app/models/trends/tags.rb
@@ -15,7 +15,8 @@ class Trends::Tags < Trends::Base
class Query < Trends::Query
def to_arel
- scope = Tag.joins(:trend).reorder(language_order_clause.desc, score: :desc)
+ scope = Tag.joins(:trend).reorder(score: :desc)
+ scope = scope.merge(language_order_clause) if preferred_languages.present?
scope = scope.merge(TagTrend.allowed) if @allowed
scope = scope.offset(@offset) if @offset.present?
scope = scope.limit(@limit) if @limit.present?
@@ -25,7 +26,7 @@ class Trends::Tags < Trends::Base
private
def language_order_clause
- Arel::Nodes::Case.new.when(TagTrend.arel_table[:language].in(preferred_languages)).then(1).else(0)
+ language_order_for(TagTrend)
end
end
diff --git a/app/models/user_role.rb b/app/models/user_role.rb
index f9c4c14c4b..d567bf5eca 100644
--- a/app/models/user_role.rb
+++ b/app/models/user_role.rb
@@ -42,6 +42,7 @@ class UserRole < ApplicationRecord
NOBODY_POSITION = -1
POSITION_LIMIT = (2**31) - 1
+ CSS_COLORS = /\A#?(?:[A-F0-9]{3}){1,2}\z/i # CSS-style hex colors
module Flags
NONE = 0
@@ -90,7 +91,7 @@ class UserRole < ApplicationRecord
attr_writer :current_account
validates :name, presence: true, unless: :everyone?
- validates :color, format: { with: /\A#?(?:[A-F0-9]{3}){1,2}\z/i }, unless: -> { color.blank? }
+ validates :color, format: { with: CSS_COLORS }, if: :color?
validates :position, numericality: { in: (-POSITION_LIMIT..POSITION_LIMIT) }
validate :validate_permissions_elevation
@@ -101,9 +102,6 @@ class UserRole < ApplicationRecord
before_validation :set_position
scope :assignable, -> { where.not(id: EVERYONE_ROLE_ID).order(position: :asc) }
- scope :highlighted, -> { where(highlighted: true) }
- scope :with_color, -> { where.not(color: [nil, '']) }
- scope :providing_styles, -> { highlighted.with_color }
has_many :users, inverse_of: :role, foreign_key: 'role_id', dependent: :nullify
diff --git a/app/policies/account_warning_policy.rb b/app/policies/account_warning_policy.rb
index 4f8df7420e..976cae6c9c 100644
--- a/app/policies/account_warning_policy.rb
+++ b/app/policies/account_warning_policy.rb
@@ -6,7 +6,7 @@ class AccountWarningPolicy < ApplicationPolicy
end
def appeal?
- target? && record.created_at >= Appeal::MAX_STRIKE_AGE.ago
+ target? && record.appeal_eligible?
end
private
diff --git a/app/policies/admin/status_policy.rb b/app/policies/admin/status_policy.rb
index e9379c25ec..c4ba5c2606 100644
--- a/app/policies/admin/status_policy.rb
+++ b/app/policies/admin/status_policy.rb
@@ -12,7 +12,7 @@ class Admin::StatusPolicy < ApplicationPolicy
end
def show?
- role.can?(:manage_reports, :manage_users) && (record.public_visibility? || record.unlisted_visibility? || record.reported? || viewable_through_normal_policy?)
+ role.can?(:manage_reports, :manage_users) && eligible_to_show?
end
def destroy?
@@ -29,6 +29,10 @@ class Admin::StatusPolicy < ApplicationPolicy
private
+ def eligible_to_show?
+ record.distributable? || record.reported? || viewable_through_normal_policy?
+ end
+
def viewable_through_normal_policy?
StatusPolicy.new(current_account, record, @preloaded_relations).show?
end
diff --git a/app/policies/user_role_policy.rb b/app/policies/user_role_policy.rb
index 6144a0ec4a..44b5589581 100644
--- a/app/policies/user_role_policy.rb
+++ b/app/policies/user_role_policy.rb
@@ -10,10 +10,16 @@ class UserRolePolicy < ApplicationPolicy
end
def update?
- role.can?(:manage_roles) && (role.overrides?(record) || role.id == record.id)
+ role.can?(:manage_roles) && (role.overrides?(record) || self_editing?)
end
def destroy?
- !record.everyone? && role.can?(:manage_roles) && role.overrides?(record) && role.id != record.id
+ !record.everyone? && role.can?(:manage_roles) && role.overrides?(record) && !self_editing?
+ end
+
+ private
+
+ def self_editing?
+ role.id == record.id
end
end
diff --git a/app/serializers/rest/scheduled_status_serializer.rb b/app/serializers/rest/scheduled_status_serializer.rb
index 8aa0d89386..7c54f39c0d 100644
--- a/app/serializers/rest/scheduled_status_serializer.rb
+++ b/app/serializers/rest/scheduled_status_serializer.rb
@@ -8,8 +8,4 @@ class REST::ScheduledStatusSerializer < ActiveModel::Serializer
def id
object.id.to_s
end
-
- def params
- object.params.without('application_id')
- end
end
diff --git a/app/views/admin/report_notes/_report_note.html.haml b/app/views/admin/report_notes/_report_note.html.haml
index dd60f7eabd..9c8e267d62 100644
--- a/app/views/admin/report_notes/_report_note.html.haml
+++ b/app/views/admin/report_notes/_report_note.html.haml
@@ -4,7 +4,7 @@
.report-notes__item__header
%span.username
= link_to report_note.account.username, admin_account_path(report_note.account_id)
- %time.relative-formatted{ datetime: report_note.created_at.iso8601 }
+ %time.relative-formatted{ datetime: report_note.created_at.iso8601, title: report_note.created_at }
= l report_note.created_at.to_date
.report-notes__item__content
diff --git a/app/views/admin/reports/_comment.html.haml b/app/views/admin/reports/_comment.html.haml
index 8c07210af9..2b3af15c49 100644
--- a/app/views/admin/reports/_comment.html.haml
+++ b/app/views/admin/reports/_comment.html.haml
@@ -18,7 +18,7 @@
= link_to report.account.username, admin_account_path(report.account_id)
- else
= link_to report.account.domain, admin_instance_path(report.account.domain)
- %time.relative-formatted{ datetime: report.created_at.iso8601 }
+ %time.relative-formatted{ datetime: report.created_at.iso8601, title: report.created_at }
= l report.created_at.to_date
.report-notes__item__content
= simple_format(h(report.comment))
diff --git a/app/views/admin/roles/_role.html.haml b/app/views/admin/roles/_role.html.haml
index 636127354b..085bdbd156 100644
--- a/app/views/admin/roles/_role.html.haml
+++ b/app/views/admin/roles/_role.html.haml
@@ -1,7 +1,7 @@
.announcements-list__item
- if can?(:update, role)
= link_to edit_admin_role_path(role), class: 'announcements-list__item__title' do
- %span.user-role{ class: "user-role-#{role.id}" }
+ %span.user-role
= material_symbol 'group'
- if role.everyone?
@@ -10,7 +10,7 @@
= role.name
- else
%span.announcements-list__item__title
- %span.user-role{ class: "user-role-#{role.id}" }
+ %span.user-role
= material_symbol 'group'
- if role.everyone?
diff --git a/app/views/application/mailer/_checklist.html.haml b/app/views/application/mailer/_checklist.html.haml
index 91c7c98f26..4b460fa26d 100644
--- a/app/views/application/mailer/_checklist.html.haml
+++ b/app/views/application/mailer/_checklist.html.haml
@@ -29,8 +29,8 @@
%div
- if defined?(show_apps_buttons) && show_apps_buttons
.email-welcome-apps-btns
- = link_to image_tag(frontend_asset_url('images/mailer-new/store-icons/btn-app-store.png'), alt: t('user_mailer.welcome.apps_ios_action'), width: 120, height: 40), 'https://apps.apple.com/app/mastodon-for-iphone-and-ipad/id1571998974'
- = link_to image_tag(frontend_asset_url('images/mailer-new/store-icons/btn-google-play.png'), alt: t('user_mailer.welcome.apps_android_action'), width: 120, height: 40), 'https://play.google.com/store/apps/details?id=org.joinmastodon.android'
+ = link_to image_tag(frontend_asset_url('images/mailer-new/store-icons/btn-app-store.png'), alt: t('user_mailer.welcome.apps_ios_action'), width: 120, height: 40), app_store_url_ios
+ = link_to image_tag(frontend_asset_url('images/mailer-new/store-icons/btn-google-play.png'), alt: t('user_mailer.welcome.apps_android_action'), width: 120, height: 40), app_store_url_android
- elsif defined?(button_text) && defined?(button_url) && defined?(checked) && !checked
= render 'application/mailer/button', text: button_text, url: button_url, has_arrow: false
/[if mso]
diff --git a/app/views/custom_css/show.css.erb b/app/views/custom_css/show.css.erb
index 78da809ed6..d4b24b2106 100644
--- a/app/views/custom_css/show.css.erb
+++ b/app/views/custom_css/show.css.erb
@@ -2,9 +2,3 @@
<%= raw custom_css_styles %>
<%- end %>
-<%- @user_roles.each do |role| %>
-.user-role-<%= role.id %> {
- --user-role-accent: <%= role.color %>;
-}
-
-<%- end %>
diff --git a/app/views/disputes/strikes/show.html.haml b/app/views/disputes/strikes/show.html.haml
index 150dc06759..322d820a2a 100644
--- a/app/views/disputes/strikes/show.html.haml
+++ b/app/views/disputes/strikes/show.html.haml
@@ -66,7 +66,7 @@
.report-notes__item__header
%span.username
= link_to @appeal.account.username, can?(:show, @appeal.account) ? admin_account_path(@appeal.account_id) : short_account_url(@appeal.account)
- %time.relative-formatted{ datetime: @appeal.created_at.iso8601 }
+ %time.relative-formatted{ datetime: @appeal.created_at.iso8601, title: @appeal.created_at }
= l @appeal.created_at.to_date
.report-notes__item__content
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index a76dc75f63..fe73fdb5f7 100755
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -35,7 +35,7 @@
= csrf_meta_tags unless skip_csrf_meta_tags?
%meta{ name: 'style-nonce', content: request.content_security_policy_nonce }
- = stylesheet_link_tag custom_css_path, skip_pipeline: true, host: root_url, media: 'all'
+ = custom_stylesheet
= yield :header_tags
diff --git a/app/views/user_mailer/welcome.text.erb b/app/views/user_mailer/welcome.text.erb
index 144d44b842..383f436f8e 100644
--- a/app/views/user_mailer/welcome.text.erb
+++ b/app/views/user_mailer/welcome.text.erb
@@ -30,8 +30,8 @@
5. <%= t('user_mailer.welcome.apps_title') %>
<%= t('user_mailer.welcome.apps_step') %>
- * iOS: https://apps.apple.com/app/mastodon-for-iphone-and-ipad/id1571998974
- * Android: https://play.google.com/store/apps/details?id=org.joinmastodon.android
+ * iOS: <%= app_store_url_ios %>
+ * Android: <%= app_store_url_android %>
---
diff --git a/config/initializers/settings_digests.rb b/config/initializers/settings_digests.rb
new file mode 100644
index 0000000000..2a5d925c70
--- /dev/null
+++ b/config/initializers/settings_digests.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+Rails.application.config.to_prepare do
+ custom_css = begin
+ Setting.custom_css
+ rescue ActiveRecord::AdapterError # Running without a database, not migrated, no connection, etc
+ nil
+ end
+
+ if custom_css.present?
+ Rails
+ .cache
+ .write(
+ :setting_digest_custom_css,
+ Digest::SHA256.hexdigest(custom_css)
+ )
+ end
+end
diff --git a/config/locales/activerecord.cy.yml b/config/locales/activerecord.cy.yml
index 3620c1c2f6..9bc9b3b2bc 100644
--- a/config/locales/activerecord.cy.yml
+++ b/config/locales/activerecord.cy.yml
@@ -24,6 +24,8 @@ cy:
models:
account:
attributes:
+ fields:
+ fields_with_values_missing_labels: yn cynnwys gwerthoedd gyda labeli coll
username:
invalid: rhaid iddo gynnwys dim ond llythrennau, rhifau a thanlinellau
reserved: wedi ei neilltuo
diff --git a/config/locales/activerecord.gl.yml b/config/locales/activerecord.gl.yml
index 0c4941f048..8fdff40282 100644
--- a/config/locales/activerecord.gl.yml
+++ b/config/locales/activerecord.gl.yml
@@ -24,6 +24,8 @@ gl:
models:
account:
attributes:
+ fields:
+ fields_with_values_missing_labels: contén valores aos que lle faltan etiquetas
username:
invalid: sĂł letras, nĂșmeros e trazo baixo
reserved: estĂĄ reservado
diff --git a/config/locales/activerecord.hu.yml b/config/locales/activerecord.hu.yml
index 27ca9018d4..b26d1afbe3 100644
--- a/config/locales/activerecord.hu.yml
+++ b/config/locales/activerecord.hu.yml
@@ -24,6 +24,8 @@ hu:
models:
account:
attributes:
+ fields:
+ fields_with_values_missing_labels: hiĂĄnyzĂł cĂmkĂ©kkel rendelkezĆ Ă©rtĂ©keket tartalmaz
username:
invalid: csak betƱket, szåmokat vagy alåvonåst tartalmazhat
reserved: foglalt
diff --git a/config/locales/activerecord.ia.yml b/config/locales/activerecord.ia.yml
index fcb3f68278..35b28a19aa 100644
--- a/config/locales/activerecord.ia.yml
+++ b/config/locales/activerecord.ia.yml
@@ -24,6 +24,8 @@ ia:
models:
account:
attributes:
+ fields:
+ fields_with_values_missing_labels: contine valores con etiquettas perdite
username:
invalid: debe continer solmente litteras, numeros e lineettas basse
reserved: es reservate
diff --git a/config/locales/activerecord.lv.yml b/config/locales/activerecord.lv.yml
index b7e2db65e8..3fb928c89c 100644
--- a/config/locales/activerecord.lv.yml
+++ b/config/locales/activerecord.lv.yml
@@ -24,6 +24,8 @@ lv:
models:
account:
attributes:
+ fields:
+ fields_with_values_missing_labels: satur vÄrtÄ«bas ar trĆ«kstoĆĄÄm iezÄ«mÄm
username:
invalid: drÄ«kst saturÄt tikai burtus, ciparus un pasvÄ«tras
reserved: ir rezervÄts
@@ -39,6 +41,11 @@ lv:
attributes:
data:
malformed: ir nepareizi veidots
+ list_account:
+ attributes:
+ account_id:
+ taken: jau ir sarakstÄ
+ must_be_following: jÄbĆ«t kontam, kuram seko
status:
attributes:
reblog:
diff --git a/config/locales/activerecord.pt-PT.yml b/config/locales/activerecord.pt-PT.yml
index 86581331db..8b17ade2eb 100644
--- a/config/locales/activerecord.pt-PT.yml
+++ b/config/locales/activerecord.pt-PT.yml
@@ -24,6 +24,8 @@ pt-PT:
models:
account:
attributes:
+ fields:
+ fields_with_values_missing_labels: contém valores com etiquetas em falta
username:
invalid: deve conter apenas letras, nĂșmeros e traços inferiores
reserved: estĂĄ reservado
diff --git a/config/locales/activerecord.sv.yml b/config/locales/activerecord.sv.yml
index f05161992c..bf1ef22f3d 100644
--- a/config/locales/activerecord.sv.yml
+++ b/config/locales/activerecord.sv.yml
@@ -24,6 +24,8 @@ sv:
models:
account:
attributes:
+ fields:
+ fields_with_values_missing_labels: innehÄller vÀrden med saknade etiketter
username:
invalid: endast bokstÀver, siffror och understrykning
reserved: Àr reserverat
diff --git a/config/locales/activerecord.tr.yml b/config/locales/activerecord.tr.yml
index 095aa72e67..4795e629fb 100644
--- a/config/locales/activerecord.tr.yml
+++ b/config/locales/activerecord.tr.yml
@@ -25,7 +25,7 @@ tr:
account:
attributes:
fields:
- fields_with_values_missing_labels: deÄerleri eksik etiketler içeriyor
+ fields_with_values_missing_labels: etiketleri eksik deÄerler içeriyor
username:
invalid: sadece harfler, sayılar ve alt çizgiler
reserved: kullanılamaz
diff --git a/config/locales/doorkeeper.sk.yml b/config/locales/doorkeeper.sk.yml
index 774a2648f9..ba9a440a11 100644
--- a/config/locales/doorkeeper.sk.yml
+++ b/config/locales/doorkeeper.sk.yml
@@ -134,6 +134,7 @@ sk:
media: MediĂĄlne prĂlohy
mutes: StĂĆĄenia
notifications: Upozornenia
+ profile: VĂĄĆĄ Mastodon profil
push: Upozornenia push
reports: HlĂĄsenia
search: VyhÄŸadĂĄvanie
diff --git a/config/locales/fo.yml b/config/locales/fo.yml
index 00ffed90bb..441217ec0e 100644
--- a/config/locales/fo.yml
+++ b/config/locales/fo.yml
@@ -214,6 +214,7 @@ fo:
enable_user: Ger brĂșkara virknan
memorialize_account: Minnst til Konto
promote_user: VĂs fram BrĂșkara
+ publish_terms_of_service: Ătgev tĂŠnastutreytir
reject_appeal: AvvĂs mĂłtmali
reject_user: AvvĂs BrĂșkara
remove_avatar_user: Sletta Avatar
@@ -278,6 +279,7 @@ fo:
enable_user_html: "%{name} gjĂžrdi innritan virkna fyri brĂșkaran %{target}"
memorialize_account_html: "%{name} broytti kontuna hjĂĄ %{target} til eina minnissĂĂ°u"
promote_user_html: "%{name} flutti brĂșkaran %{target} fram"
+ publish_terms_of_service_html: "%{name} Ăștgav dagfĂžringar til tĂŠnastutreytirnar"
reject_appeal_html: "%{name} avvĂsti umsjĂłnarĂĄheitan frĂĄ %{target}"
reject_user_html: "%{name} avvĂsti skrĂĄseting hjĂĄ %{target}"
remove_avatar_user_html: "%{name} strikaĂ°i eftirgjĂžrda skapningin hjĂĄ %{target}"
@@ -925,6 +927,32 @@ fo:
search: Leita
title: FrĂĄmerki
updated_msg: FrĂĄmerkjastillingar dagfĂžrdar
+ terms_of_service:
+ back: Aftur til tĂŠnastutreytir
+ changelog: Hvat er broytt
+ create: BrĂșka tĂnar egnu
+ current: NĂșverandi
+ draft: Kladda
+ generate: BrĂșka leist
+ generates:
+ action: FramleiĂ°
+ chance_to_review_html: "
Framleiddu tĂŠnastutreytirnar verĂ°a ikki Ăștgivnar av sĂŠr sjĂĄlvum. TĂș fĂŠr mĂžguleika at eftirhyggja Ășrslitini. Vinarliga Ăștfyll neyĂ°ugu smĂĄlutirnar fyri at halda fram."
+ explanation_html: Leisturin viĂ° tĂŠnastutreytum er einans til kunningar og skal ikki fatast sum lĂžgfrÞðislig rĂĄĂ°geving yvirhĂžvur. Vinarliga spyr tĂn egna lĂžgfrÞðisliga rĂĄĂ°geva um tĂna stÞðu og ĂtĂžkiligu lĂžgfrÞðisligu spurningarnar hjĂĄ tĂŠr.
+ title: Uppseting av tĂŠnastutreytum
+ history: SĂžga
+ live: BeinleiĂ°is
+ no_history: Enn eru ongar skrĂĄsettar broytingar Ă tĂŠnastutreytunum.
+ no_terms_of_service_html: Ă lĂžtuni hevur tĂș ongar tĂŠnastutreytir uppsettar. Hugsanin viĂ° tĂŠnastutreytum er at veita greidleika og at verja teg ĂmĂłti mĂžguligum ĂĄbyrgdum Ă Ăłsemjum viĂ° tĂnar brĂșkarar.
+ notified_on_html: FrĂĄboĂ°an latin brĂșkarum %{date}
+ notify_users: Gev brĂșkarum frĂĄboĂ°an
+ preview:
+ explanation_html: 'TeldubrĂŠviĂ° verĂ°ur sent til
%{display_count} brĂșkarar , sum hava stovna kontu ĂĄĂ°renn %{date}. Fylgjandi tekstur kemur viĂ° Ă teldubrĂŠviĂ°:'
+ send_preview: Send undanvĂsing til %{email}
+ title: UndanvĂs frĂĄboĂ°an um tĂŠnastutreytir
+ publish: Ătgev
+ published_on_html: ĂtgiviĂ° %{date}
+ save_draft: Goym kladdu
+ title: TĂŠnastutreytir
title: Umsiting
trends:
allow: Loyv
@@ -1156,6 +1184,7 @@ fo:
set_new_password: Ăset nĂœtt loyniorĂ°
setup:
email_below_hint_html: Kekka mappuna viĂ° ruskposti ella biĂ° um ein annan. TĂș kanst rĂŠtta teldupostadressuna, um hon er skeiv.
+ email_settings_hint_html: TrĂœst ĂĄ leinkiĂ°, sum vit sendu til %{email} fyri at byrja at brĂșka Mastodon. Vit bĂĂ°a beint her.
link_not_received: Fekk tĂș einki leinki?
new_confirmation_instructions_sent: TĂș fer at mĂłttaka eitt nĂœtt teldubrĂŠv viĂ° vĂĄttanarleinkinum um nakrar fĂĄar minuttir!
title: Kekka innbakkan hjĂĄ tĂŠr
@@ -1164,6 +1193,7 @@ fo:
title: Rita inn ĂĄ %{domain}
sign_up:
manual_review: Tilmeldingar til %{domain} fara ĂgjĂžgnum eina manuella eftirkanning av okkara kjakleiĂ°arum. Fyri at hjĂĄlpa okkum at skunda undir skrĂĄsetingina, skriva eitt sindur um teg sjĂĄlva/n og hvĂ tĂș vil hava eina kontu ĂĄ %{domain}.
+ preamble: ViĂ° eini kontu ĂĄ hesum Mastodon ambĂŠtaranum ber til hjĂĄ tĂŠr at fylgja ein og hvĂžnn annan persĂłn ĂĄ fediversinum, ĂłansĂŠĂ° hvar teirra konta er hĂœst.
title: Latum okkum fĂĄa teg settan upp ĂĄ %{domain}.
status:
account_status: KontustÞða
@@ -1175,6 +1205,7 @@ fo:
view_strikes: VĂs eldri atsĂłknir mĂłti tĂni kontu
too_fast: OyĂ°ublaĂ°iĂ° innsent ov skjĂłtt, royn aftur.
use_security_key: BrĂșka trygdarlykil
+ user_agreement_html: Eg havi lisiĂ° og taki undir viĂ°
tĂŠnastutreytunum og
privatlĂvspolitikkinum
author_attribution:
example_title: TekstadĂžmi
hint_html: Skrivar tĂș tĂĂ°indi ella greinar til bloggin uttanfyri Mastodon? Her kanst tĂș stĂœra, hvussu tĂș verĂ°ur tilsipaĂ°/ur, tĂĄ iĂ° tĂtt tilfar verĂ°ur deilt ĂĄ Mastodon.
@@ -1836,6 +1867,8 @@ fo:
too_late: TaĂ° er ov seint at kĂŠra hesa atsĂłkn
tags:
does_not_match_previous_name: samsvarar ikki viĂ° undanfarna navniĂ°
+ terms_of_service:
+ title: TĂŠnastutreytir
themes:
contrast: Mastodon (hĂžgur kontrastur)
default: Mastodon (myrkt)
@@ -1896,6 +1929,15 @@ fo:
further_actions_html: Var hetta ikki tĂș, so mĂŠla vit til, at tĂș %{action} beinan vegin og at tĂș ger vĂĄttan Ă tveimum stigum virkna fyri at konta tĂn kann vera trygg.
subject: Atgongd er fingin til kontu tĂna frĂĄ eini nĂœggjari IP adressu
title: Ein nĂœggj innritan
+ terms_of_service_changed:
+ agreement: ViĂ° framhaldandi at brĂșka %{domain} góðtekur tĂș hesar treytir. Tekur tĂș ikki undir viĂ° dagfĂžrdu treytunum, so kanst tĂș til einhvĂžrja tĂĂ° uppsiga avtaluna viĂ° %{domain} viĂ° at strika kontu tĂna.
+ changelog: 'Ă stuttum merkir henda dagfĂžringin:'
+ description: 'TĂș mĂłttekur hetta teldubrĂŠviĂ°, tĂ at vit gera nakrar broytingar Ă okkara tĂŠnastutreytum ĂĄ %{domain}. Vit eggja tĂŠr til at eftirhyggja dagfĂžrdu treytirnar her:'
+ description_html: TĂș mĂłttekur hetta teldubrĂŠviĂ°, tĂ at vit gera nakrar broytingar Ă okkara tĂŠnastutreytum ĂĄ %{domain}. Vit eggja tĂŠr til at eftirhyggja
dagfĂžrdu og samlaĂ°u treytirnar her .
+ sign_off: "%{domain} toymiĂ°"
+ subject: DagfĂžringar til okkara tĂŠnastutreytir
+ subtitle: TĂŠnastutreytirnar hjĂĄ %{domain} eru viĂ° at verĂ°a broyttar
+ title: TĂœdningarmikil dagfĂžring
warning:
appeal: Innsend eina kĂŠru
appeal_description: TrĂœrt tĂș, at hetta er ein feilur, so kanst tĂș senda eina kĂŠru til starvsfĂłlkini ĂĄ %{instance}.
diff --git a/config/locales/gl.yml b/config/locales/gl.yml
index ac6581c8c9..63a2b9b340 100644
--- a/config/locales/gl.yml
+++ b/config/locales/gl.yml
@@ -1859,9 +1859,9 @@ gl:
'63113904': 2 anos
'7889238': 3 meses
min_age_label: LĂmite temporal
- min_favs: Manter as publicaciĂłns favorecidas polo menos
+ min_favs: Manter publicaciĂłns favorecidas polo menos
min_favs_hint: Non elimina ningunha das tĂșas publicaciĂłns que recibiron alomenos esta cantidade de favorecementos. Deixa en branco para eliminar publicaciĂłns independentemente do nĂșmero de favorecementos
- min_reblogs: Manter publicaciĂłns promovidas mĂĄis de
+ min_reblogs: Manter publicaciĂłns promovidas polo menos
min_reblogs_hint: Non elimina ningunha das tĂșas publicaciĂłns se foron promovidas mĂĄis deste nĂșmero de veces. Deixa en branco para eliminar publicaciĂłns independentemente do seu nĂșmero de promociĂłns
stream_entries:
sensitive_content: Contido sensible
diff --git a/config/locales/lv.yml b/config/locales/lv.yml
index 0f757c6370..2d256b475e 100644
--- a/config/locales/lv.yml
+++ b/config/locales/lv.yml
@@ -217,6 +217,7 @@ lv:
enable_user: IeslÄgt LietotÄju
memorialize_account: SaglabÄt Kontu PiemiĆai
promote_user: Izceltt LietotÄju
+ publish_terms_of_service: PublicÄt pakalpojuma izmantoĆĄanas noteikumus
reject_appeal: NoraidÄ«t ApelÄciju
reject_user: NoraidÄ«t lietotÄju
remove_avatar_user: NoĆemt profila attÄlu
@@ -273,6 +274,7 @@ lv:
enable_user_html: "%{name} iespÄjoja pieteikĆĄanos lietotÄjam %{target}"
memorialize_account_html: "%{name} pÄrvÄrta %{target} kontu par atmiĆas lapu"
promote_user_html: "%{name} paaugstinÄja lietotÄju %{target}"
+ publish_terms_of_service_html: "%{name} padarÄ«ja pieejamus pakalpojuma izmantoĆĄanas noteikumu atjauninÄjumus"
reject_appeal_html: "%{name} noraidÄ«ja satura pÄrraudzÄ«bas lÄmuma iebildumu no %{target}"
reject_user_html: "%{name} noraidÄ«ja reÄŁistrÄĆĄanos no %{target}"
remove_avatar_user_html: "%{name} noĆÄma %{target} profila attÄlu"
@@ -641,7 +643,7 @@ lv:
create_and_resolve: AtrisinÄt ar piezÄ«mi
create_and_unresolve: AtvÄrt atkÄrtoti ar piezÄ«mi
delete: DzÄst
- placeholder: Apraksti veiktÄs darbÄ«bas vai citus saistÄ«tus atjauninÄjumus...
+ placeholder: JÄapraksta veiktÄs darbÄ«bas vai jebkuri citi saistÄ«tie atjauninÄjumi...
title: Piezīmes
notes_description_html: Skati un atstÄj piezÄ«mes citiem moderatoriem un sev nÄkotnei
processed_msg: 'PÄrskats #%{id} veiksmÄ«gi apstrÄdÄts'
@@ -746,13 +748,13 @@ lv:
rules:
add_new: Pievienot noteikumu
delete: DzÄst
- description_html: Lai gan lielÄkÄ daÄŒa apgalvo, ka ir izlasÄ«juĆĄi pakalpojumu sniegĆĄanas noteikumus un piekrÄ«t tiem, parasti cilvÄki to izlasa tikai pÄc problÄmas raĆĄanÄs.
Padariet vienkÄrĆĄÄku sava servera noteikumu uztverĆĄanu, veidojot tos vienkÄrĆĄÄ sarakstÄ pa punktiem. Centieties, lai atseviĆĄÄ·i noteikumi bĆ«tu Ä«si un vienkÄrĆĄi, taÄu arÄ« nesadaliet tos daudzos atseviĆĄÄ·os vienumos.
+ description_html: Kaut arÄ« lielÄkÄ daÄŒa apgalvo, ka ir lasÄ«juĆĄi un piekrÄ«t pakalpojuma izmantoĆĄanas noteikumiem, parasti cilvÄki tos neizlasa, lÄ«dz rodas sareĆŸÄŁÄ«jumi.
Padari vienkÄrĆĄÄku sava servera noteikumu pÄrskatÄ«ĆĄanu, sniedzot tos vienkÄrĆĄÄ uzsvÄruma punktu sarakstÄ! JÄmÄÄŁina atseviĆĄÄ·us noteikumus veidot Ä«sus un vienkÄrĆĄus, bet jÄmÄÄŁina arÄ« tos nesadalÄ«t daudzos atseviĆĄÄ·os vienumos.
edit: Labot nosacījumu
- empty: Servera noteikumi vÄl nav definÄti.
+ empty: VÄl nav pievienots neviens servera noteikums.
title: Servera noteikumi
settings:
about:
- manage_rules: PÄrvaldÄ«t servera nosacÄ«jumus
+ manage_rules: PÄrvaldÄ«t servera noteikumus
preamble: Sniedz padziÄŒinÄtu informÄciju par to, kÄ serveris tiek darbinÄts, moderÄts un finansÄts.
rules_hint: Noteikumiem, kas taviem lietotÄjiem ir jÄievÄro, ir Ä«paĆĄa sadaÄŒa.
title: Par
@@ -821,6 +823,7 @@ lv:
back_to_account: AtpakaČ uz konta lapu
back_to_report: AtpakaÄŒ uz paziĆojumu lapu
batch:
+ add_to_report: 'Pievienot atskaitei #%{id}'
remove_from_report: NoĆemt no ziĆojuma
report: ZiĆojums
contents: Saturs
@@ -832,13 +835,17 @@ lv:
media:
title: Multivide
metadata: Metadati
+ no_history: Ć is ieraksts nav bijis labots
no_status_selected: Neviena ziĆa netika mainÄ«ta, jo neviena netika atlasÄ«ta
open: AtvÄrt ziĆu
original_status: OriÄŁinÄlÄ ziĆa
reblogs: Reblogi
+ replied_to_html: AtbildÄja %{acct_link}
status_changed: ZiĆa mainÄ«ta
status_title: PublicÄja @%{name}
+ title: Konta ieraksti - @%{name}
trending: AktuÄli
+ view_publicly: Skatīt publiski
visibility: Redzamība
with_media: Ar multividi
strikes:
@@ -876,8 +883,8 @@ lv:
message_html: 'Nesaderīga Elasticsearch versija: %{value}'
version_comparison: Darbojas Elasticsearch %{running_version}, tomÄr ir nepiecieĆĄama %{required_version}
rules_check:
- action: PÄrvaldÄ«t servera nosacÄ«jumus
- message_html: Tu neesi definÄjis nevienu servera nosacÄ«jumu.
+ action: PÄrvaldÄ«t servera noteikumus
+ message_html: Nav pievienots neviens servera noteikums.
sidekiq_process_check:
message_html: RindÄ(s) %{value} nedarbojas neviens Sidekiq process. LĆ«dzu, pÄrskati savu Sidekiq konfigurÄciju
software_version_check:
@@ -907,16 +914,42 @@ lv:
name: Nosaukums
newest: JaunÄkie
oldest: VecÄkie
+ open: Apskatīt publiski
reset: Atiestatīt
review: PÄrskatÄ«t stÄvokli
search: MeklÄt
title: TÄmturi
updated_msg: TÄmtura iestatÄ«jumi ir veiksmÄ«gi atjauninÄti
terms_of_service:
+ back: AtpakaÄŒ uz pakalpojuma izmantoĆĄanas noteikumiem
changelog: Kas ir mainījies
+ create: Izmantot savus
+ current: PaĆĄreizÄjie
+ draft: Melnraksts
+ generate: Izmantot sagatavi
+ generates:
+ action: Izveidot
+ chance_to_review_html: "
Izveidotie pakalpojuma izmantoĆĄanas noteikumi netiks automÄtiski publicÄti. BĆ«s iespÄja izskatÄ«t iznÄkumu. LĆ«gums norÄdÄ«t nepiecieĆĄamo informÄciju, lai turpinÄtu."
+ explanation_html: Pakalpojuma izmantoĆĄanas noteikumu sagatave tiek piedÄvÄta tikai izzinÄĆĄanas nolĆ«kam, un to nevajadzÄtu izmantot kÄ juridisku padomu jebkurÄ jautÄjumÄ. LĆ«gums sazinÄties ar savu juridisko padomdevÄju par saviem apstÄkÄŒiem un noteiktiem juridiskiem jautÄjumiem.
+ title: Pakalpojuma izmantoĆĄÄnas noteikumu uzstÄdÄ«ĆĄana
history: VÄsture
+ live: DarbÄ«bÄ
+ no_history: Nav ierakstu par pakalpojuma izmantoĆĄanas noteikumu izmaiĆÄm.
+ no_terms_of_service_html: PaĆĄlaik nav uzstÄdÄ«ti pakalpojuma izmantoĆĄanas noteikumi. Tie ir paredzÄti, lai sniegtu skaidrÄ«bu un aizsargÄtu no iespÄjamas atbildÄ«bas strÄ«dos ar lietotÄjiem.
+ notified_on_html: LietotÄjiem paziĆots %{date}
+ notify_users: PaziĆot lietotÄjiem
+ preview:
+ explanation_html: 'E-pasta ziĆojums tiks nosĆ«tÄ«ts
%{display_count} lietotÄjiem , kuri ir reÄŁistrÄjuĆĄies pirms %{date}. Ć is teksts tiks iekÄŒauts e-pasta ziĆojumÄ:'
+ send_preview: Nosƫtīt priekƥskatījumu uz %{email}
+ send_to_all:
+ one: NosĆ«tÄ«t %{display_count} e-pasta ziĆojumu
+ other: NosĆ«tÄ«t %{display_count} e-pasta ziĆojumus
+ zero: NosĆ«tÄ«t %{display_count} e-pasta ziĆojumu
+ title: PriekĆĄkatÄ«t pakalpojuma izmantoĆĄanas noteikumu paziĆojumu
publish: PublicÄt
- published_on_html: PublicÄts %{date}
+ published_on_html: PublicÄti %{date}
+ save_draft: SaglabÄt melnrakstu
+ title: Pakalpojuma izmantoĆĄanas noteikumi
title: PÄrvaldÄ«ba
trends:
allow: AtÄŒaut
@@ -1157,6 +1190,7 @@ lv:
view_strikes: Skati iepriekĆĄÄjos brÄ«dinÄjumus par savu kontu
too_fast: Veidlapa ir iesniegta pÄrÄk Ätri, mÄÄŁini vÄlreiz.
use_security_key: Lietot droĆĄÄ«bas atslÄgu
+ user_agreement_html: Es esmu izlasījis un piekrītu
pakalpojuma izmantoĆĄanas noteikumiem un
privÄtuma nosacÄ«jumiem
author_attribution:
example_title: Parauga teksts
more_from_html: VairÄk no %{name}
@@ -1777,6 +1811,8 @@ lv:
too_late: BrÄ«dinÄjuma apstrÄ«dÄĆĄanas laiks ir nokavÄts
tags:
does_not_match_previous_name: nesakrÄ«t ar iepriekĆĄÄjo nosaukumu
+ terms_of_service:
+ title: Pakalpojuma izmantoĆĄanas noteikumi
themes:
contrast: Mastodon (Augsts kontrasts)
default: Mastodon (TumĆĄs)
@@ -1826,6 +1862,15 @@ lv:
further_actions_html: Ja tas nebiji tu, iesakÄm nekavÄjoties %{action} un iespÄjot divu faktoru autentifikÄciju, lai tavs konts bĆ«tu droĆĄÄ«bÄ.
subject: Tavam kontam ir piekÄŒĆ«ts no jaunas IP adreses
title: Jauna pieteikĆĄanÄs
+ terms_of_service_changed:
+ agreement: Ar %{domain} izmantoĆĄanas tuprinÄĆĄanu tiek piekrists ĆĄiem noteikumiem. Ja ir iebildumi pret atjauninÄtajiem noteikumiem, savu piekriĆĄanu var atcelt jebkurÄ laikÄ ar sava konta izdzÄĆĄanu.
+ changelog: 'Ć eit Ä«sumÄ ir aprakstÄ«ts, ko ĆĄis atjauninÄjums nozÄ«mÄ:'
+ description: 'Ć is e-pasta ziĆojums tika saĆemts, jo mÄs veicam daĆŸas izmaiĆas savos pakalpojuma izmantoĆĄanas noteikumos %{domain}. MÄs aicinÄm pÄrskatÄ«t pilnus atjauninÄtos noteikumus ĆĄeit:'
+ description_html: Ć is e-pasta ziĆojums tika saĆemts, jo mÄs veicam daĆŸas izmaiĆas savos pakalpojuma izmantoĆĄanas noteikumos %{domain}. MÄs aicinÄm pÄrskatÄ«t
pilnus atjauninÄtos noteikumus ĆĄeit .
+ sign_off: "%{domain} komanda"
+ subject: MĆ«su pakalpojuma izmantoĆĄanas noteikumu atjauninÄjumi
+ subtitle: MainÄs %{domain} pakalpojuma izmantoĆĄanas noteikumi
+ title: SvarÄ«gs atjauninÄjums
warning:
appeal: Iesniegt apelÄciju
appeal_description: Ja uzskatÄt, ka tÄ ir kÄŒĆ«da, varat iesniegt apelÄciju %{instance} darbiniekiem.
diff --git a/config/locales/pt-PT.yml b/config/locales/pt-PT.yml
index 41fc9fbecc..bba71f165d 100644
--- a/config/locales/pt-PT.yml
+++ b/config/locales/pt-PT.yml
@@ -10,7 +10,7 @@ pt-PT:
followers:
one: Seguidor
other: Seguidores
- following: A seguir
+ following: Seguindo
instance_actor_flash: Esta conta é um ator virtual utilizado para representar o servidor em si e não um utilizador individual. à utilizada para efeitos de federação e não deve ser suspensa.
last_active: Ășltima atividade
link_verified_on: A posse desta hiperligação foi verificada em %{date}
diff --git a/config/locales/simple_form.fo.yml b/config/locales/simple_form.fo.yml
index 0c9ec51722..99bb1ccaa0 100644
--- a/config/locales/simple_form.fo.yml
+++ b/config/locales/simple_form.fo.yml
@@ -130,6 +130,17 @@ fo:
show_application: ĂansĂŠĂ°, so er altĂĂ° mĂžguligt hjĂĄ tĂŠr at sĂggja, hvĂžr app postaĂ°i tĂn post.
tag:
name: TĂș kanst einans broyta millum stĂłrar og smĂĄar stavir, til dĂžmis fyri at gera taĂ° meira lesiligt
+ terms_of_service:
+ changelog: Kunnu vera uppbygdar viĂ° Markdown syntaksi.
+ text: Kunnu vera uppbygdar viĂ° Markdown syntaksi.
+ terms_of_service_generator:
+ admin_email: LĂžgfrÞðisligar frĂĄboĂ°anir fata um rĂŠttarligar mĂłtfrĂĄboĂ°anir, ĂșrskurĂ°ir, ĂĄheitanir um at taka niĂ°ur og lĂžgfrÞðisligar ĂĄheitanir.
+ arbitration_address: Kann vera tann sami sum fysiski bĂșstaĂ°urin omanfyri ella "N/A", um teldupostur verĂ°ur brĂșktur
+ arbitration_website: Kann vera ein vevformularur ella "N/A", um teldupostur verĂ°ur brĂșktur
+ dmca_address: FyristÞðufĂłlk og -felĂžg Ă USA brĂșka bĂșstaĂ°in, iĂ° er skrĂĄsettur Ă DMCA Designated Agent Directory. Ein postsmoguskrĂĄseting er tĂžk, um biĂ°iĂ° verĂ°ur um hana beinleiĂ°is. BrĂșka DMCA Designated Agent Post Office Box Waiver Request fyri at senda teldubrĂŠv til Copyright Office og greiĂ° frĂĄ, at tĂș er ein kjakleiĂ°ari, sum virkar heimanifrĂĄ, og at tĂș er bangin fyri hevnd ella afturlĂžning fyri tĂ, tĂș ger, og at tĂș hevur tĂžrv ĂĄ at brĂșka eina postsmogu fyri at fjala heimabĂșstaĂ°in fyri almenninginum.
+ dmca_email: Kann vera sami teldupoststaĂ°ur, sum er brĂșktur til "TeldupoststaĂ°ur fyri lĂžgfrÞðisligar frĂĄboĂ°anir" omanfyri
+ domain: Makaleys eyĂ°merking av nettĂŠnastuni, sum tĂș veitir.
+ jurisdiction: Lista landiĂ°, har sum tann, iĂ° rindar rokningarnar, livir. Er taĂ° eitt felag ella ein onnur eind, lista landiĂ°, har taĂ° er skrĂĄsett, umframt bĂœin, ĂžkiĂ°, umveldiĂ° ella statin, alt eftir hvat er hĂłskandi.
user:
chosen_languages: TĂĄ hetta er valt, verĂ°a einans postar Ă valdum mĂĄlum vĂstir ĂĄ almennum tĂĂ°arlinjum
role: Leikluturin stĂœrir hvĂžrji rĂŠttindi, brĂșkarin hevur.
@@ -319,6 +330,17 @@ fo:
name: TvĂkrossur
trendable: Loyv hesum frĂĄmerki at sĂggjast undir rĂĄkum
usable: Loyv postum at brĂșka hetta frĂĄmerki lokalt
+ terms_of_service:
+ changelog: Hvat er broytt?
+ text: TĂŠnastutreytir
+ terms_of_service_generator:
+ admin_email: Teldupoststaður fyri lÞgfrÞðisligar fråboðanir
+ arbitration_address: Fysisk adressa fyri gerĂ°arrĂŠttarfrĂĄboĂ°anir
+ arbitration_website: HeimasĂĂ°a har gerĂ°arrĂŠttarfrĂĄboĂ°anir kunnu innlatast
+ dmca_address: Fysiskur bĂșstaĂ°ur fyri DMCA/copyright frĂĄboĂ°anir
+ dmca_email: TeldubĂșstaĂ°ur fyri DMCA/copyright frĂĄboĂ°anir
+ domain: NavnaĂžki
+ jurisdiction: LĂžgdĂžmi
user:
role: Leiklutur
time_zone: TĂĂ°arsona
diff --git a/config/locales/simple_form.fr.yml b/config/locales/simple_form.fr.yml
index 1b0469f7a3..62dd23f930 100644
--- a/config/locales/simple_form.fr.yml
+++ b/config/locales/simple_form.fr.yml
@@ -174,7 +174,7 @@ fr:
admin_account_action:
include_statuses: Inclure les messages signalés dans le courriel
send_email_notification: Notifier lâutilisateur par courriel
- text: Attention personnalisée
+ text: Avertissement personnalisé
type: Action
types:
disable: DĂ©sactiver
diff --git a/config/locales/simple_form.lv.yml b/config/locales/simple_form.lv.yml
index 2f4a05dca4..7c7b11c1b3 100644
--- a/config/locales/simple_form.lv.yml
+++ b/config/locales/simple_form.lv.yml
@@ -53,7 +53,7 @@ lv:
locale: LietotÄja saskarnes, e-pasta ziĆojumu un push paziĆojumu valoda
password: Izmanto vismaz 8 rakstzīmes
phrase: Tiks saskaĆots neatkarÄ«gi no ziĆas teksta reÄŁistra vai satura brÄ«dinÄjuma
- scopes: Kuriem API lietojumprogrammai bĆ«s atÄŒauta piekÄŒuve. Ja izvÄlies augstÄkÄ lÄ«meĆa tvÄrumu, tev nav jÄatlasa atseviĆĄÄ·i vienumi.
+ scopes: Kuriem API lietotnei bĆ«s ÄŒauts piekÄŒĆ«t. Ja atlasa augstÄkÄ lÄ«meĆa tvÄrumu, nav nepiecieĆĄamas atlasÄ«t atseviĆĄÄ·us.
setting_aggregate_reblogs: NerÄdÄ«t jaunus izcÄlumus ziĆÄm, kas nesen tika palielinÄtas (ietekmÄ tikai nesen saĆemtos palielinÄjumus)
setting_always_send_emails: Parasti e-pasta paziĆojumi netiek sĆ«tÄ«ti, kad aktÄ«vi izmantojat Mastodon
setting_default_sensitive: SensitÄ«va multivide pÄc noklusÄjuma ir paslÄpti, un tos var atklÄt, noklikĆĄÄ·inot
@@ -119,8 +119,8 @@ lv:
sign_up_requires_approval: JaunÄm reÄŁistrÄcijÄm bĆ«s nepiecieĆĄams tavs apstiprinÄjums
severity: IzvÄlies, kas notiks ar pieprasÄ«jumiem no ĆĄÄ«s IP adreses
rule:
- hint: IzvÄles. Sniedz vairÄk informÄcijas par nosacÄ«jumu
- text: Apraksti nosacÄ«jumus vai prasÄ«bas ĆĄÄ« servera lietotÄjiem. Centies, lai tas bĆ«tu Ä«ss un vienkÄrĆĄs
+ hint: IzvÄles. Sniedz vairÄk informÄcijas par noteikumu
+ text: JÄapraksta nosacÄ«jums vai prasÄ«ba ĆĄÄ« servera lietotÄjiem. JÄmÄÄŁina to veidot Ä«su un vienkÄrĆĄu
sessions:
otp: 'Ievadi divfaktoru kodu, ko ÄŁenerÄjusi tava tÄlruĆa lietotne, vai izmanto kÄdu no atkopĆĄanas kodiem:'
webauthn: Ja tÄ ir USB atslÄga, noteikti ievieto to un, ja nepiecieĆĄams, pieskaries tai.
@@ -317,6 +317,11 @@ lv:
name: TÄmturis
trendable: AtÄŒaut ĆĄim tÄmturim parÄdÄ«ties zem tendencÄm
usable: Ä»aut ierakstos vietÄji izmantot ĆĄo tÄmturi
+ terms_of_service:
+ changelog: Kas ir mainījies?
+ text: Pakalpojuma izmantoƥanas nosacījumi
+ terms_of_service_generator:
+ domain: DomÄna vÄrds
user:
role: Loma
time_zone: Laika josla
diff --git a/config/locales/simple_form.pt-PT.yml b/config/locales/simple_form.pt-PT.yml
index efc64d6dc6..f5a7e3a27e 100644
--- a/config/locales/simple_form.pt-PT.yml
+++ b/config/locales/simple_form.pt-PT.yml
@@ -161,7 +161,7 @@ pt-PT:
fields:
name: RĂłtulo
value: ConteĂșdo
- indexable: Incluir mensagens pĂșblicas nos resultados da pesquisa
+ indexable: Incluir mensagens pĂșblicas nos resultados de pesquisas
show_collections: Mostrar quem sigo e os meus seguidores no perfil
unlocked: Aceitar automaticamente novos seguidores
account_alias:
@@ -205,7 +205,7 @@ pt-PT:
email: Endereço de correio electrónico
expires_in: Expira em
fields: Metadados de perfil
- header: Cabeçalho
+ header: Imagem de cabeçalho
honeypot: "%{label} (nĂŁo preencher)"
inbox_url: URL da caixa de entrada do repetidor
irreversible: Expandir em vez de esconder
diff --git a/config/locales/simple_form.sv.yml b/config/locales/simple_form.sv.yml
index 0815170fcc..2d2c1c0060 100644
--- a/config/locales/simple_form.sv.yml
+++ b/config/locales/simple_form.sv.yml
@@ -130,6 +130,14 @@ sv:
show_application: Du kommer alltid att kunna se vilken app som publicerat ditt inlÀgg oavsett.
tag:
name: Du kan bara Àndra skriftlÀget av bokstÀverna, till exempel, för att göra det mer lÀsbart
+ terms_of_service:
+ changelog: Kan struktureras med Markdown syntax.
+ text: Kan struktureras med Markdown syntax.
+ terms_of_service_generator:
+ arbitration_address: Kan vara samma som fysisk adress ovan, eller âN/Aâ om du anvĂ€nder e-post
+ arbitration_website: Kan vara ett webbformulĂ€r, eller âN/Aâ om du anvĂ€nder e-post
+ dmca_email: Kan vara samma e-postadress som anvĂ€nds för âE-postadress för juridiska meddelandenâ ovan
+ jurisdiction: Lista det land dÀr vem som Àn betalar rÀkningarna bor. Om det Àr ett företag eller annan enhet, lista landet dÀr det Àr inkorporerat, och staden, regionen, territoriet eller staten pÄ lÀmpligt sÀtt.
user:
chosen_languages: Vid aktivering visas bara inlÀgg pÄ dina valda sprÄk i offentliga tidslinjer
role: Rollen styr vilka behörigheter anvÀndaren har.
@@ -151,7 +159,7 @@ sv:
name: Etikett
value: InnehÄll
indexable: Inkludera offentliga inlÀgg i sökresultaten
- show_collections: Göm följare och följeslagare pÄ profilen
+ show_collections: Visa följare och följeslagare pÄ profilen
unlocked: GodkÀnn nya följare automatiskt
account_alias:
acct: Namnet pÄ det gamla kontot
@@ -224,6 +232,7 @@ sv:
setting_hide_network: Göm ditt nÀtverk
setting_reduce_motion: Minska rörelser i animationer
setting_system_font_ui: AnvÀnd systemets standardfont
+ setting_system_scrollbars_ui: AnvÀnd systemets standardrullningsfÀlt
setting_theme: Sidans tema
setting_trends: Visa dagens trender
setting_unfollow_modal: Visa bekrÀftelse innan du slutar följa nÄgon
@@ -318,6 +327,14 @@ sv:
name: Hashtagg
trendable: TillÄt denna hashtagg att visas under trender
usable: TillÄt inlÀgg att anvÀnda denna fyrkantstagg
+ terms_of_service:
+ changelog: Vad har Àndrats?
+ text: AnvÀndarvillkor
+ terms_of_service_generator:
+ admin_email: E-postadress för juridiska meddelanden
+ dmca_address: Fysisk adress för meddelanden om DMCA/upphovsrÀtt
+ dmca_email: Fysisk adress för meddelanden om DMCA/upphovsrÀtt
+ domain: DomÀn
user:
role: Roll
time_zone: Tidszon
diff --git a/config/mastodon.yml b/config/mastodon.yml
index 2c09c59e0a..feaf8e20d8 100644
--- a/config/mastodon.yml
+++ b/config/mastodon.yml
@@ -2,3 +2,6 @@
shared:
self_destruct_value: <%= ENV.fetch('SELF_DESTRUCT', nil) %>
software_update_url: <%= ENV.fetch('UPDATE_CHECK_URL', 'https://api.joinmastodon.org/update-check') %>
+ version:
+ metadata: <%= ['glitch', ENV.fetch('MASTODON_VERSION_METADATA', nil)].compact_blank.join('.') %>
+ prerelease: <%= ENV.fetch('MASTODON_VERSION_PRERELEASE', nil) %>
diff --git a/config/routes.rb b/config/routes.rb
index 3909dd1b77..5adec04c7d 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -55,7 +55,8 @@ Rails.application.routes.draw do
get 'manifest', to: 'manifests#show', defaults: { format: 'json' }
get 'intent', to: 'intents#show'
- get 'custom.css', to: 'custom_css#show', as: :custom_css
+ get 'custom.css', to: 'custom_css#show'
+ resources :custom_css, only: :show, path: :css
get 'remote_interaction_helper', to: 'remote_interaction_helper#index'
diff --git a/docker-compose.yml b/docker-compose.yml
index 6048129318..63f17bf495 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -100,7 +100,8 @@ services:
- redis
sidekiq:
- build: .
+ # You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes
+ # build: .
image: ghcr.io/mastodon/mastodon:v4.3.2
restart: always
env_file: .env.production
diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md
new file mode 100644
index 0000000000..39f57dd402
--- /dev/null
+++ b/docs/DEVELOPMENT.md
@@ -0,0 +1,75 @@
+# Development
+
+## Overview
+
+Before starting local development, read the [CONTRIBUTING] guide to understand
+what changes are desirable and what general processes to use.
+
+## Environments
+
+### Vagrant
+
+A **Vagrant** configuration is included for development purposes. To use it,
+complete the following steps:
+
+- Install Vagrant and Virtualbox
+- Install the `vagrant-hostsupdater` plugin:
+ `vagrant plugin install vagrant-hostsupdater`
+- Run `vagrant up`
+- Run `vagrant ssh -c "cd /vagrant && bin/dev"`
+- Open `http://mastodon.local` in your browser
+
+### macOS
+
+To set up **macOS** for native development, complete the following steps:
+
+- Install [Homebrew] and run:
+ `brew install postgresql@14 redis imagemagick libidn nvm`
+ to install the required project dependencies
+- Use a Ruby version manager to activate the ruby in `.ruby-version` and run
+ `nvm use` to activate the node version from `.nvmrc`
+- Run the `bin/setup` script, which will install the required ruby gems and node
+ packages and prepare the database for local development
+- Finally, run the `bin/dev` script which will launch services via `overmind`
+ (if installed) or `foreman`
+
+### Docker
+
+For production hosting and deployment with **Docker**, use the `Dockerfile` and
+`docker-compose.yml` in the project root directory.
+
+For local development, install and launch [Docker], and run:
+
+```shell
+docker compose -f .devcontainer/compose.yaml up -d
+docker compose -f .devcontainer/compose.yaml exec app bin/setup
+docker compose -f .devcontainer/compose.yaml exec app bin/dev
+```
+
+### Dev Containers
+
+Within IDEs that support the [Development Containers] specification, start the
+"Mastodon on local machine" container from the editor. The necessary `docker
+compose` commands to build and setup the container should run automatically. For
+**Visual Studio Code** this requires installing the [Dev Container extension].
+
+### GitHub Codespaces
+
+[GitHub Codespaces] provides a web-based version of VS Code and a cloud hosted
+development environment configured with the software needed for this project.
+
+[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)][codespace]
+
+- Click the button to create a new codespace, and confirm the options
+- Wait for the environment to build (takes a few minutes)
+- When the editor is ready, run `bin/dev` in the terminal
+- Wait for an _Open in Browser_ prompt. This will open Mastodon
+- On the _Ports_ tab "stream" setting change _Port visibility_ â _Public_
+
+[codespace]: https://codespaces.new/mastodon/mastodon?quickstart=1&devcontainer_path=.devcontainer%2Fcodespaces%2Fdevcontainer.json
+[CONTRIBUTING]: CONTRIBUTING.md
+[Dev Container extension]: https://containers.dev/supporting#dev-containers
+[Development Containers]: https://containers.dev/supporting
+[Docker]: https://docs.docker.com
+[GitHub Codespaces]: https://docs.github.com/en/codespaces
+[Homebrew]: https://brew.sh
diff --git a/lib/mastodon/cli/maintenance.rb b/lib/mastodon/cli/maintenance.rb
index 532fbc328a..32ee35c7c7 100644
--- a/lib/mastodon/cli/maintenance.rb
+++ b/lib/mastodon/cli/maintenance.rb
@@ -192,6 +192,7 @@ module Mastodon::CLI
verify_schema_version!
verify_sidekiq_not_active!
verify_backup_warning!
+ disable_timeout!
end
def process_deduplications
@@ -251,6 +252,13 @@ module Mastodon::CLI
fail_with_message 'Maintenance process stopped.' unless yes?('Continue? (Yes/No)')
end
+ def disable_timeout!
+ # Remove server-configured timeout if present
+ database_connection.execute(<<~SQL.squish)
+ SET statement_timeout = 0
+ SQL
+ end
+
def deduplicate_accounts!
remove_index_if_exists!(:accounts, 'index_accounts_on_username_and_domain_lower')
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index a16b3d550f..1827714122 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -21,11 +21,11 @@ module Mastodon
end
def prerelease
- ENV['MASTODON_VERSION_PRERELEASE'].presence || default_prerelease
+ version_configuration[:prerelease].presence || default_prerelease
end
def build_metadata
- ['glitch', ENV.fetch('MASTODON_VERSION_METADATA', nil)].compact_blank.join('.')
+ version_configuration[:metadata]
end
def to_a
@@ -77,5 +77,9 @@ module Mastodon
def user_agent
@user_agent ||= "Mastodon/#{Version} (#{HTTP::Request::USER_AGENT}; +http#{Rails.configuration.x.use_https ? 's' : ''}://#{Rails.configuration.x.web_domain}/)"
end
+
+ def version_configuration
+ Rails.configuration.x.mastodon.version
+ end
end
end
diff --git a/package.json b/package.json
index 7da0cc9908..51ecc8a317 100644
--- a/package.json
+++ b/package.json
@@ -102,7 +102,7 @@
"react-hotkeys": "^1.1.4",
"react-immutable-proptypes": "^2.2.0",
"react-immutable-pure-component": "^2.2.2",
- "react-intl": "^6.4.2",
+ "react-intl": "^7.0.0",
"react-motion": "^0.5.2",
"react-notification": "^6.8.5",
"react-overlays": "^5.2.1",
@@ -201,6 +201,8 @@
"webpack-dev-server": "^3.11.3"
},
"resolutions": {
+ "@types/react": "^18.2.7",
+ "@types/react-dom": "^18.2.4",
"kind-of": "^6.0.3",
"webpack/terser-webpack-plugin": "^4.2.3"
},
diff --git a/spec/controllers/admin/follow_recommendations_controller_spec.rb b/spec/controllers/admin/follow_recommendations_controller_spec.rb
deleted file mode 100644
index 82446cd467..0000000000
--- a/spec/controllers/admin/follow_recommendations_controller_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Admin::FollowRecommendationsController do
- render_views
-
- let(:user) { Fabricate(:admin_user) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show
-
- expect(response).to have_http_status(:success)
- end
- end
-end
diff --git a/spec/controllers/admin/terms_of_service/histories_controller_spec.rb b/spec/controllers/admin/terms_of_service/histories_controller_spec.rb
deleted file mode 100644
index 8c2c3a3de3..0000000000
--- a/spec/controllers/admin/terms_of_service/histories_controller_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Admin::TermsOfService::HistoriesController do
- render_views
-
- let(:user) { Fabricate(:admin_user) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show
-
- expect(response).to have_http_status(:success)
- end
- end
-end
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 52d92a2b6c..1678005871 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -3,6 +3,8 @@
require 'rails_helper'
RSpec.describe ApplicationController do
+ render_views
+
controller do
def success
head 200
@@ -23,9 +25,22 @@ RSpec.describe ApplicationController do
shared_examples 'respond_with_error' do |code|
it "returns http #{code} for http and renders template" do
- expect(subject).to render_template("errors/#{code}", layout: 'error')
+ subject
- expect(response).to have_http_status(code)
+ expect(response)
+ .to have_http_status(code)
+ expect(response.parsed_body)
+ .to have_css('body[class=error]')
+ expect(response.parsed_body.css('h1').to_s)
+ .to include(error_content(code))
+ end
+
+ def error_content(code)
+ if code == 422
+ I18n.t('errors.422.content')
+ else
+ I18n.t("errors.#{code}")
+ end
end
end
diff --git a/spec/controllers/settings/migrations_controller_spec.rb b/spec/controllers/settings/migrations_controller_spec.rb
deleted file mode 100644
index dca4c925fd..0000000000
--- a/spec/controllers/settings/migrations_controller_spec.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Settings::MigrationsController do
- render_views
-
- describe 'GET #show' do
- context 'when user is not sign in' do
- subject { get :show }
-
- it { is_expected.to redirect_to new_user_session_path }
- end
-
- context 'when user is sign in' do
- subject { get :show }
-
- let(:user) { Fabricate(:account, moved_to_account: moved_to_account).user }
-
- before { sign_in user, scope: :user }
-
- context 'when user does not have moved to account' do
- let(:moved_to_account) { nil }
-
- it 'renders show page' do
- expect(subject).to have_http_status 200
- expect(subject).to render_template :show
- end
- end
-
- context 'when user has a moved to account' do
- let(:moved_to_account) { Fabricate(:account) }
-
- it 'renders show page' do
- expect(subject).to have_http_status 200
- expect(subject).to render_template :show
- end
- end
- end
- end
-
- describe 'POST #create' do
- context 'when user is not sign in' do
- subject { post :create }
-
- it { is_expected.to redirect_to new_user_session_path }
- end
-
- context 'when user is signed in' do
- subject { post :create, params: { account_migration: { acct: acct, current_password: '12345678' } } }
-
- let(:user) { Fabricate(:user, password: '12345678') }
-
- before { sign_in user, scope: :user }
-
- context 'when migration account is changed' do
- let(:acct) { Fabricate(:account, also_known_as: [ActivityPub::TagManager.instance.uri_for(user.account)]) }
-
- it 'updates moved to account' do
- expect(subject).to redirect_to settings_migration_path
- expect(user.account.reload.moved_to_account_id).to eq acct.id
- end
- end
-
- context 'when acct is the current account' do
- let(:acct) { user.account }
-
- it 'does not update the moved account', :aggregate_failures do
- subject
-
- expect(user.account.reload.moved_to_account_id).to be_nil
- expect(response).to render_template :show
- end
- end
-
- context 'when target account does not reference the account being moved from' do
- let(:acct) { Fabricate(:account, also_known_as: []) }
-
- it 'does not update the moved account', :aggregate_failures do
- subject
-
- expect(user.account.reload.moved_to_account_id).to be_nil
- expect(response).to render_template :show
- end
- end
-
- context 'when a recent migration already exists' do
- let(:acct) { Fabricate(:account, also_known_as: [ActivityPub::TagManager.instance.uri_for(user.account)]) }
-
- before do
- moved_to = Fabricate(:account, also_known_as: [ActivityPub::TagManager.instance.uri_for(user.account)])
- user.account.migrations.create!(acct: moved_to.acct)
- end
-
- it 'does not update the moved account', :aggregate_failures do
- subject
-
- expect(user.account.reload.moved_to_account_id).to be_nil
- expect(response).to render_template :show
- end
- end
- end
- end
-end
diff --git a/spec/helpers/theme_helper_spec.rb b/spec/helpers/theme_helper_spec.rb
index 83a68f4739..f9dfd4d48e 100644
--- a/spec/helpers/theme_helper_spec.rb
+++ b/spec/helpers/theme_helper_spec.rb
@@ -79,6 +79,26 @@ RSpec.describe ThemeHelper do
end
end
+ describe '#custom_stylesheet' do
+ context 'when custom css setting value digest is present' do
+ before { Rails.cache.write(:setting_digest_custom_css, '1a2s3d4f1a2s3d4f') }
+
+ it 'returns value from settings' do
+ expect(custom_stylesheet)
+ .to match('/css/custom-1a2s3d4f.css')
+ end
+ end
+
+ context 'when custom css setting value digest is not present' do
+ before { Rails.cache.delete(:setting_digest_custom_css) }
+
+ it 'returns default value' do
+ expect(custom_stylesheet)
+ .to be_blank
+ end
+ end
+ end
+
private
def html_links
diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb
index a98e6896ca..ad4cb9997d 100644
--- a/spec/lib/activitypub/activity/create_spec.rb
+++ b/spec/lib/activitypub/activity/create_spec.rb
@@ -162,12 +162,9 @@ RSpec.describe ActivityPub::Activity::Create do
context 'when object publication date is below ISO8601 range' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- published: '-0977-11-03T08:31:22Z',
- }
+ build_object(
+ published: '-0977-11-03T08:31:22Z'
+ )
end
it 'creates status with a valid creation date', :aggregate_failures do
@@ -184,12 +181,9 @@ RSpec.describe ActivityPub::Activity::Create do
context 'when object publication date is above ISO8601 range' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- published: '10000-11-03T08:31:22Z',
- }
+ build_object(
+ published: '10000-11-03T08:31:22Z'
+ )
end
it 'creates status with a valid creation date', :aggregate_failures do
@@ -206,13 +200,10 @@ RSpec.describe ActivityPub::Activity::Create do
context 'when object has been edited' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
published: '2022-01-22T15:00:00Z',
- updated: '2022-01-22T16:00:00Z',
- }
+ updated: '2022-01-22T16:00:00Z'
+ )
end
it 'creates status with appropriate creation and edition dates', :aggregate_failures do
@@ -232,13 +223,10 @@ RSpec.describe ActivityPub::Activity::Create do
context 'when object has update date equal to creation date' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
published: '2022-01-22T15:00:00Z',
- updated: '2022-01-22T15:00:00Z',
- }
+ updated: '2022-01-22T15:00:00Z'
+ )
end
it 'creates status and does not mark it as edited' do
@@ -254,11 +242,9 @@ RSpec.describe ActivityPub::Activity::Create do
context 'with an unknown object type' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Banana',
- content: 'Lorem ipsum',
- }
+ build_object(
+ type: 'Banana'
+ )
end
it 'does not create a status' do
@@ -267,13 +253,7 @@ RSpec.describe ActivityPub::Activity::Create do
end
context 'with a standalone' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- }
- end
+ let(:object_json) { build_object }
it 'creates status' do
expect { subject.perform }.to change(sender.statuses, :count).by(1)
@@ -296,12 +276,9 @@ RSpec.describe ActivityPub::Activity::Create do
context 'when public with explicit public address' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- to: 'https://www.w3.org/ns/activitystreams#Public',
- }
+ build_object(
+ to: 'https://www.w3.org/ns/activitystreams#Public'
+ )
end
it 'creates status' do
@@ -316,12 +293,9 @@ RSpec.describe ActivityPub::Activity::Create do
context 'when public with as:Public' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- to: 'as:Public',
- }
+ build_object(
+ to: 'as:Public'
+ )
end
it 'creates status' do
@@ -336,12 +310,9 @@ RSpec.describe ActivityPub::Activity::Create do
context 'when public with Public' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- to: 'Public',
- }
+ build_object(
+ to: 'Public'
+ )
end
it 'creates status' do
@@ -356,12 +327,9 @@ RSpec.describe ActivityPub::Activity::Create do
context 'when unlisted with explicit public address' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- cc: 'https://www.w3.org/ns/activitystreams#Public',
- }
+ build_object(
+ cc: 'https://www.w3.org/ns/activitystreams#Public'
+ )
end
it 'creates status' do
@@ -376,12 +344,9 @@ RSpec.describe ActivityPub::Activity::Create do
context 'when unlisted with as:Public' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- cc: 'as:Public',
- }
+ build_object(
+ cc: 'as:Public'
+ )
end
it 'creates status' do
@@ -396,12 +361,9 @@ RSpec.describe ActivityPub::Activity::Create do
context 'when unlisted with Public' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- cc: 'Public',
- }
+ build_object(
+ cc: 'Public'
+ )
end
it 'creates status' do
@@ -416,12 +378,9 @@ RSpec.describe ActivityPub::Activity::Create do
context 'when private' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- to: 'http://example.com/followers',
- }
+ build_object(
+ to: 'http://example.com/followers'
+ )
end
it 'creates status' do
@@ -436,16 +395,13 @@ RSpec.describe ActivityPub::Activity::Create do
context 'when private with inlined Collection in audience' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
to: {
type: 'OrderedCollection',
id: 'http://example.com/followers',
first: 'http://example.com/followers?page=true',
- },
- }
+ }
+ )
end
it 'creates status' do
@@ -462,12 +418,9 @@ RSpec.describe ActivityPub::Activity::Create do
let(:recipient) { Fabricate(:account) }
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- to: ActivityPub::TagManager.instance.uri_for(recipient),
- }
+ build_object(
+ to: ActivityPub::TagManager.instance.uri_for(recipient)
+ )
end
it 'creates status with a silent mention' do
@@ -512,16 +465,13 @@ RSpec.describe ActivityPub::Activity::Create do
let(:recipient) { Fabricate(:account) }
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
to: ActivityPub::TagManager.instance.uri_for(recipient),
tag: {
type: 'Mention',
href: ActivityPub::TagManager.instance.uri_for(recipient),
- },
- }
+ }
+ )
end
it 'creates status with direct visibility' do
@@ -561,12 +511,9 @@ RSpec.describe ActivityPub::Activity::Create do
let(:original_status) { Fabricate(:status) }
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- inReplyTo: ActivityPub::TagManager.instance.uri_for(original_status),
- }
+ build_object(
+ inReplyTo: ActivityPub::TagManager.instance.uri_for(original_status)
+ )
end
it 'creates status' do
@@ -586,17 +533,14 @@ RSpec.describe ActivityPub::Activity::Create do
let(:recipient) { Fabricate(:account) }
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
tag: [
{
type: 'Mention',
href: ActivityPub::TagManager.instance.uri_for(recipient),
},
- ],
- }
+ ]
+ )
end
it 'creates status' do
@@ -611,16 +555,13 @@ RSpec.describe ActivityPub::Activity::Create do
context 'with mentions missing href' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
tag: [
{
type: 'Mention',
},
- ],
- }
+ ]
+ )
end
it 'creates status' do
@@ -633,10 +574,7 @@ RSpec.describe ActivityPub::Activity::Create do
context 'with media attachments' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
attachment: [
{
type: 'Document',
@@ -648,8 +586,8 @@ RSpec.describe ActivityPub::Activity::Create do
mediaType: 'image/png',
url: 'http://example.com/emoji.png',
},
- ],
- }
+ ]
+ )
end
it 'creates status with correctly-ordered media attachments' do
@@ -665,19 +603,16 @@ RSpec.describe ActivityPub::Activity::Create do
context 'with media attachments with long description' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
attachment: [
{
type: 'Document',
mediaType: 'image/png',
url: 'http://example.com/attachment.png',
- name: '*' * 1500,
+ name: '*' * MediaAttachment::MAX_DESCRIPTION_LENGTH,
},
- ],
- }
+ ]
+ )
end
it 'creates status' do
@@ -686,25 +621,22 @@ RSpec.describe ActivityPub::Activity::Create do
status = sender.statuses.first
expect(status).to_not be_nil
- expect(status.media_attachments.map(&:description)).to include('*' * 1500)
+ expect(status.media_attachments.map(&:description)).to include('*' * MediaAttachment::MAX_DESCRIPTION_LENGTH)
end
end
context 'with media attachments with long description as summary' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
attachment: [
{
type: 'Document',
mediaType: 'image/png',
url: 'http://example.com/attachment.png',
- summary: '*' * 1500,
+ summary: '*' * MediaAttachment::MAX_DESCRIPTION_LENGTH,
},
- ],
- }
+ ]
+ )
end
it 'creates status' do
@@ -713,16 +645,13 @@ RSpec.describe ActivityPub::Activity::Create do
status = sender.statuses.first
expect(status).to_not be_nil
- expect(status.media_attachments.map(&:description)).to include('*' * 1500)
+ expect(status.media_attachments.map(&:description)).to include('*' * MediaAttachment::MAX_DESCRIPTION_LENGTH)
end
end
context 'with media attachments with focal points' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
attachment: [
{
type: 'Document',
@@ -730,8 +659,8 @@ RSpec.describe ActivityPub::Activity::Create do
url: 'http://example.com/attachment.png',
focalPoint: [0.5, -0.7],
},
- ],
- }
+ ]
+ )
end
it 'creates status' do
@@ -746,17 +675,14 @@ RSpec.describe ActivityPub::Activity::Create do
context 'with media attachments missing url' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
attachment: [
{
type: 'Document',
mediaType: 'image/png',
},
- ],
- }
+ ]
+ )
end
it 'creates status' do
@@ -769,18 +695,15 @@ RSpec.describe ActivityPub::Activity::Create do
context 'with hashtags' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
tag: [
{
type: 'Hashtag',
href: 'http://example.com/blah',
name: '#test',
},
- ],
- }
+ ]
+ )
end
it 'creates status' do
@@ -795,10 +718,7 @@ RSpec.describe ActivityPub::Activity::Create do
context 'with featured hashtags' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
to: 'https://www.w3.org/ns/activitystreams#Public',
tag: [
{
@@ -806,8 +726,8 @@ RSpec.describe ActivityPub::Activity::Create do
href: 'http://example.com/blah',
name: '#test',
},
- ],
- }
+ ]
+ )
end
before do
@@ -829,17 +749,14 @@ RSpec.describe ActivityPub::Activity::Create do
context 'with hashtags missing name' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
tag: [
{
type: 'Hashtag',
href: 'http://example.com/blah',
},
- ],
- }
+ ]
+ )
end
it 'creates status' do
@@ -852,18 +769,15 @@ RSpec.describe ActivityPub::Activity::Create do
context 'with hashtags invalid name' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
tag: [
{
type: 'Hashtag',
href: 'http://example.com/blah',
name: 'foo, #eh !',
},
- ],
- }
+ ]
+ )
end
it 'creates status' do
@@ -876,9 +790,7 @@ RSpec.describe ActivityPub::Activity::Create do
context 'with emojis' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
+ build_object(
content: 'Lorem ipsum :tinking:',
tag: [
{
@@ -888,8 +800,8 @@ RSpec.describe ActivityPub::Activity::Create do
},
name: 'tinking',
},
- ],
- }
+ ]
+ )
end
it 'creates status' do
@@ -904,9 +816,7 @@ RSpec.describe ActivityPub::Activity::Create do
context 'with emojis served with invalid content-type' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
+ build_object(
content: 'Lorem ipsum :tinkong:',
tag: [
{
@@ -916,8 +826,8 @@ RSpec.describe ActivityPub::Activity::Create do
},
name: 'tinkong',
},
- ],
- }
+ ]
+ )
end
it 'creates status' do
@@ -932,9 +842,7 @@ RSpec.describe ActivityPub::Activity::Create do
context 'with emojis missing name' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
+ build_object(
content: 'Lorem ipsum :tinking:',
tag: [
{
@@ -943,8 +851,8 @@ RSpec.describe ActivityPub::Activity::Create do
url: 'http://example.com/emoji.png',
},
},
- ],
- }
+ ]
+ )
end
it 'creates status' do
@@ -957,17 +865,15 @@ RSpec.describe ActivityPub::Activity::Create do
context 'with emojis missing icon' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
+ build_object(
content: 'Lorem ipsum :tinking:',
tag: [
{
type: 'Emoji',
name: 'tinking',
},
- ],
- }
+ ]
+ )
end
it 'creates status' do
@@ -980,8 +886,7 @@ RSpec.describe ActivityPub::Activity::Create do
context 'with poll' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
+ build_object(
type: 'Question',
content: 'Which color was the submarine?',
oneOf: [
@@ -999,8 +904,8 @@ RSpec.describe ActivityPub::Activity::Create do
totalItems: 3,
},
},
- ],
- }
+ ]
+ )
end
it 'creates status with a poll' do
@@ -1023,12 +928,10 @@ RSpec.describe ActivityPub::Activity::Create do
let!(:local_status) { Fabricate(:status, poll: poll) }
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
+ build_object(
name: 'Yellow',
- inReplyTo: ActivityPub::TagManager.instance.uri_for(local_status),
- }
+ inReplyTo: ActivityPub::TagManager.instance.uri_for(local_status)
+ ).except(:content)
end
it 'adds a vote to the poll with correct uri' do
@@ -1050,12 +953,10 @@ RSpec.describe ActivityPub::Activity::Create do
let!(:local_status) { Fabricate(:status, poll: poll) }
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
+ build_object(
name: 'Yellow',
- inReplyTo: ActivityPub::TagManager.instance.uri_for(local_status),
- }
+ inReplyTo: ActivityPub::TagManager.instance.uri_for(local_status)
+ ).except(:content)
end
it 'does not add a vote to the poll' do
@@ -1067,10 +968,7 @@ RSpec.describe ActivityPub::Activity::Create do
context 'with counts' do
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
+ build_object(
likes: {
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar', '/likes'].join,
type: 'Collection',
@@ -1080,8 +978,8 @@ RSpec.describe ActivityPub::Activity::Create do
id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar', '/shares'].join,
type: 'Collection',
totalItems: 100,
- },
- }
+ }
+ )
end
it 'uses the counts from the created object' do
@@ -1110,12 +1008,9 @@ RSpec.describe ActivityPub::Activity::Create do
end
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- to: 'https://www.w3.org/ns/activitystreams#Public',
- }
+ build_object(
+ to: 'https://www.w3.org/ns/activitystreams#Public'
+ )
end
before do
@@ -1145,13 +1040,7 @@ RSpec.describe ActivityPub::Activity::Create do
subject.perform
end
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- }
- end
+ let(:object_json) { build_object }
it 'creates status' do
status = sender.statuses.first
@@ -1166,12 +1055,9 @@ RSpec.describe ActivityPub::Activity::Create do
let!(:local_status) { Fabricate(:status) }
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- inReplyTo: ActivityPub::TagManager.instance.uri_for(local_status),
- }
+ build_object(
+ inReplyTo: ActivityPub::TagManager.instance.uri_for(local_status)
+ )
end
before do
@@ -1190,13 +1076,11 @@ RSpec.describe ActivityPub::Activity::Create do
subject { described_class.new(json, sender, delivery: true) }
let!(:local_account) { Fabricate(:account) }
+
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- to: ActivityPub::TagManager.instance.uri_for(local_account),
- }
+ build_object(
+ to: ActivityPub::TagManager.instance.uri_for(local_account)
+ )
end
before do
@@ -1216,12 +1100,9 @@ RSpec.describe ActivityPub::Activity::Create do
let!(:local_account) { Fabricate(:account) }
let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- cc: ActivityPub::TagManager.instance.uri_for(local_account),
- }
+ build_object(
+ cc: ActivityPub::TagManager.instance.uri_for(local_account)
+ )
end
before do
@@ -1243,17 +1124,19 @@ RSpec.describe ActivityPub::Activity::Create do
subject.perform
end
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- }
- end
+ let(:object_json) { build_object }
it 'does not create anything' do
expect(sender.statuses.count).to eq 0
end
end
+
+ def build_object(options = {})
+ {
+ id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
+ type: 'Note',
+ content: 'Lorem ipsum',
+ }.merge(options)
+ end
end
end
diff --git a/spec/lib/mastodon/cli/maintenance_spec.rb b/spec/lib/mastodon/cli/maintenance_spec.rb
index 6a15677f43..3e8eb9c360 100644
--- a/spec/lib/mastodon/cli/maintenance_spec.rb
+++ b/spec/lib/mastodon/cli/maintenance_spec.rb
@@ -89,10 +89,8 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :accounts, name: :index_accounts_on_username_and_domain_lower
- _remote_account = Fabricate(:account, username: duplicate_account_username, domain: duplicate_account_domain)
- _remote_account_dupe = Fabricate.build(:account, username: duplicate_account_username, domain: duplicate_account_domain).save(validate: false)
- _local_account = Fabricate(:account, username: duplicate_account_username, domain: nil)
- _local_account_dupe = Fabricate.build(:account, username: duplicate_account_username, domain: nil).save(validate: false)
+ duplicate_record(:account, username: duplicate_account_username, domain: duplicate_account_domain)
+ duplicate_record(:account, username: duplicate_account_username, domain: nil)
end
def choose_local_account_to_keep
@@ -127,8 +125,7 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :users, :email
- Fabricate(:user, email: duplicate_email)
- Fabricate.build(:user, email: duplicate_email).save(validate: false)
+ duplicate_record(:user, email: duplicate_email)
end
end
@@ -156,8 +153,7 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :users, :confirmation_token
- Fabricate(:user, confirmation_token: duplicate_confirmation_token)
- Fabricate.build(:user, confirmation_token: duplicate_confirmation_token).save(validate: false)
+ duplicate_record(:user, confirmation_token: duplicate_confirmation_token)
end
end
@@ -185,8 +181,7 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :users, :reset_password_token
- Fabricate(:user, reset_password_token: duplicate_reset_password_token)
- Fabricate.build(:user, reset_password_token: duplicate_reset_password_token).save(validate: false)
+ duplicate_record(:user, reset_password_token: duplicate_reset_password_token)
end
end
@@ -214,8 +209,7 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :account_domain_blocks, [:account_id, :domain]
- Fabricate(:account_domain_block, account: account, domain: duplicate_domain)
- Fabricate.build(:account_domain_block, account: account, domain: duplicate_domain).save(validate: false)
+ duplicate_record(:account_domain_block, account: account, domain: duplicate_domain)
end
end
@@ -244,8 +238,7 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :announcement_reactions, [:account_id, :announcement_id, :name]
- Fabricate(:announcement_reaction, account: account, announcement: announcement, name: name)
- Fabricate.build(:announcement_reaction, account: account, announcement: announcement, name: name).save(validate: false)
+ duplicate_record(:announcement_reaction, account: account, announcement: announcement, name: name)
end
end
@@ -272,8 +265,7 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :conversations, :uri
- Fabricate(:conversation, uri: uri)
- Fabricate.build(:conversation, uri: uri).save(validate: false)
+ duplicate_record(:conversation, uri: uri)
end
end
@@ -301,8 +293,7 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :custom_emojis, [:shortcode, :domain]
- Fabricate(:custom_emoji, shortcode: duplicate_shortcode, domain: duplicate_domain)
- Fabricate.build(:custom_emoji, shortcode: duplicate_shortcode, domain: duplicate_domain).save(validate: false)
+ duplicate_record(:custom_emoji, shortcode: duplicate_shortcode, domain: duplicate_domain)
end
end
@@ -329,8 +320,7 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :custom_emoji_categories, :name
- Fabricate(:custom_emoji_category, name: duplicate_name)
- Fabricate.build(:custom_emoji_category, name: duplicate_name).save(validate: false)
+ duplicate_record(:custom_emoji_category, name: duplicate_name)
end
end
@@ -357,8 +347,7 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :domain_allows, :domain
- Fabricate(:domain_allow, domain: domain)
- Fabricate.build(:domain_allow, domain: domain).save(validate: false)
+ duplicate_record(:domain_allow, domain: domain)
end
end
@@ -385,8 +374,7 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :domain_blocks, :domain
- Fabricate(:domain_block, domain: domain)
- Fabricate.build(:domain_block, domain: domain).save(validate: false)
+ duplicate_record(:domain_block, domain: domain)
end
end
@@ -413,8 +401,7 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :email_domain_blocks, :domain
- Fabricate(:email_domain_block, domain: domain)
- Fabricate.build(:email_domain_block, domain: domain).save(validate: false)
+ duplicate_record(:email_domain_block, domain: domain)
end
end
@@ -441,8 +428,7 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :media_attachments, :shortcode
- Fabricate(:media_attachment, shortcode: shortcode)
- Fabricate.build(:media_attachment, shortcode: shortcode).save(validate: false)
+ duplicate_record(:media_attachment, shortcode: shortcode)
end
end
@@ -469,8 +455,7 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :preview_cards, :url
- Fabricate(:preview_card, url: url)
- Fabricate.build(:preview_card, url: url).save(validate: false)
+ duplicate_record(:preview_card, url: url)
end
end
@@ -530,8 +515,7 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :tags, name: 'index_tags_on_name_lower_btree'
- Fabricate(:tag, name: name)
- Fabricate.build(:tag, name: name).save(validate: false)
+ duplicate_record(:tag, name: name)
end
end
@@ -558,8 +542,7 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :webauthn_credentials, :external_id
- Fabricate(:webauthn_credential, external_id: external_id)
- Fabricate.build(:webauthn_credential, external_id: external_id).save(validate: false)
+ duplicate_record(:webauthn_credential, external_id: external_id)
end
end
@@ -586,11 +569,15 @@ RSpec.describe Mastodon::CLI::Maintenance do
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :webhooks, :url
- Fabricate(:webhook, url: url)
- Fabricate.build(:webhook, url: url).save(validate: false)
+ duplicate_record(:webhook, url: url)
end
end
+ def duplicate_record(fabricator, options = {})
+ Fabricate(fabricator, options)
+ Fabricate.build(fabricator, options).save(validate: false)
+ end
+
def agree_to_backup_warning
allow(cli.shell)
.to receive(:yes?)
diff --git a/spec/lib/request_spec.rb b/spec/lib/request_spec.rb
index c600a48ee2..f17cf637b9 100644
--- a/spec/lib/request_spec.rb
+++ b/spec/lib/request_spec.rb
@@ -4,7 +4,9 @@ require 'rails_helper'
require 'securerandom'
RSpec.describe Request do
- subject { described_class.new(:get, 'http://example.com') }
+ subject { described_class.new(:get, 'http://example.com', **options) }
+
+ let(:options) { {} }
describe '#headers' do
it 'returns user agent' do
@@ -39,8 +41,8 @@ RSpec.describe Request do
end
describe '#perform' do
- context 'with valid host' do
- before { stub_request(:get, 'http://example.com') }
+ context 'with valid host and non-persistent connection' do
+ before { stub_request(:get, 'http://example.com').to_return(body: 'lorem ipsum') }
it 'executes a HTTP request' do
expect { |block| subject.perform(&block) }.to yield_control
@@ -71,9 +73,9 @@ RSpec.describe Request do
expect(subject.send(:http_client)).to have_received(:close)
end
- it 'returns response which implements body_with_limit' do
+ it 'yields response' do
subject.perform do |response|
- expect(response).to respond_to :body_with_limit
+ expect(response.body_with_limit).to eq 'lorem ipsum'
end
end
end
@@ -95,6 +97,43 @@ RSpec.describe Request do
expect { subject.perform }.to raise_error Mastodon::ValidationError
end
end
+
+ context 'with persistent connection' do
+ before { stub_request(:get, 'http://example.com').to_return(body: SecureRandom.random_bytes(2.megabytes)) }
+
+ let(:http_client) { described_class.http_client.persistent('http://example.com') }
+ let(:options) { { http_client: http_client } }
+
+ it 'leaves connection open after completely consumed response' do
+ allow(http_client).to receive(:close)
+
+ subject.perform { |response| response.truncated_body(3.megabytes) }
+
+ expect(http_client).to_not have_received(:close)
+ end
+
+ it 'leaves connection open after nearly consumed response' do
+ allow(http_client).to receive(:close)
+
+ subject.perform { |response| response.truncated_body(1.8.megabytes) }
+
+ expect(http_client).to_not have_received(:close)
+ end
+
+ it 'closes connection after unconsumed response' do
+ allow(http_client).to receive(:close)
+
+ subject.perform
+
+ expect(http_client).to have_received(:close)
+ end
+
+ it 'yields response' do
+ subject.perform do |response|
+ expect(response.body_with_limit(2.megabytes).size).to eq 2.megabytes
+ end
+ end
+ end
end
describe "response's body_with_limit method" do
diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb
index 967809b8e1..5b995b4af6 100644
--- a/spec/models/account_spec.rb
+++ b/spec/models/account_spec.rb
@@ -3,6 +3,7 @@
require 'rails_helper'
RSpec.describe Account do
+ include_examples 'Account::Search'
include_examples 'Reviewable'
context 'with an account record' do
@@ -48,14 +49,48 @@ RSpec.describe Account do
end
describe '#local?' do
- it 'returns true when the account is local' do
+ it 'returns true when domain is null' do
account = Fabricate(:account, domain: nil)
- expect(account.local?).to be true
+ expect(account).to be_local
end
- it 'returns false when the account is on a different domain' do
+ it 'returns false when domain is present' do
account = Fabricate(:account, domain: 'foreign.tld')
- expect(account.local?).to be false
+ expect(account).to_not be_local
+ end
+ end
+
+ describe '#remote?' do
+ context 'when the domain is null' do
+ subject { Fabricate.build :account, domain: nil }
+
+ it { is_expected.to_not be_remote }
+ end
+
+ context 'when the domain is blank' do
+ subject { Fabricate.build :account, domain: '' }
+
+ it { is_expected.to_not be_remote }
+ end
+
+ context 'when the domain is present' do
+ subject { Fabricate.build :account, domain: 'host.example' }
+
+ it { is_expected.to be_remote }
+ end
+ end
+
+ describe '#actor_type_application?' do
+ context 'when the actor is not of type application' do
+ subject { Fabricate.build :account, actor_type: 'Person' }
+
+ it { is_expected.to_not be_actor_type_application }
+ end
+
+ context 'when the actor is of type application' do
+ subject { Fabricate.build :account, actor_type: 'Application' }
+
+ it { is_expected.to be_actor_type_application }
end
end
@@ -324,271 +359,6 @@ RSpec.describe Account do
end
end
- describe '.search_for' do
- before do
- _missing = Fabricate(
- :account,
- display_name: 'Missing',
- username: 'missing',
- domain: 'missing.com'
- )
- end
-
- it 'does not return suspended users' do
- Fabricate(
- :account,
- display_name: 'Display Name',
- username: 'username',
- domain: 'example.com',
- suspended: true
- )
-
- results = described_class.search_for('username')
- expect(results).to eq []
- end
-
- it 'does not return unapproved users' do
- match = Fabricate(
- :account,
- display_name: 'Display Name',
- username: 'username'
- )
-
- match.user.update(approved: false)
-
- results = described_class.search_for('username')
- expect(results).to eq []
- end
-
- it 'does not return unconfirmed users' do
- match = Fabricate(
- :account,
- display_name: 'Display Name',
- username: 'username'
- )
-
- match.user.update(confirmed_at: nil)
-
- results = described_class.search_for('username')
- expect(results).to eq []
- end
-
- it 'accepts ?, \, : and space as delimiter' do
- match = Fabricate(
- :account,
- display_name: 'A & l & i & c & e',
- username: 'username',
- domain: 'example.com'
- )
-
- results = described_class.search_for('A?l\i:c e')
- expect(results).to eq [match]
- end
-
- it 'finds accounts with matching display_name' do
- match = Fabricate(
- :account,
- display_name: 'Display Name',
- username: 'username',
- domain: 'example.com'
- )
-
- results = described_class.search_for('display')
- expect(results).to eq [match]
- end
-
- it 'finds accounts with matching username' do
- match = Fabricate(
- :account,
- display_name: 'Display Name',
- username: 'username',
- domain: 'example.com'
- )
-
- results = described_class.search_for('username')
- expect(results).to eq [match]
- end
-
- it 'finds accounts with matching domain' do
- match = Fabricate(
- :account,
- display_name: 'Display Name',
- username: 'username',
- domain: 'example.com'
- )
-
- results = described_class.search_for('example')
- expect(results).to eq [match]
- end
-
- it 'limits via constant by default' do
- stub_const('Account::Search::DEFAULT_LIMIT', 1)
- 2.times.each { Fabricate(:account, display_name: 'Display Name') }
- results = described_class.search_for('display')
- expect(results.size).to eq 1
- end
-
- it 'accepts arbitrary limits' do
- 2.times.each { Fabricate(:account, display_name: 'Display Name') }
- results = described_class.search_for('display', limit: 1)
- expect(results.size).to eq 1
- end
-
- it 'ranks multiple matches higher' do
- matches = [
- { username: 'username', display_name: 'username' },
- { display_name: 'Display Name', username: 'username', domain: 'example.com' },
- ].map(&method(:Fabricate).curry(2).call(:account))
-
- results = described_class.search_for('username')
- expect(results).to eq matches
- end
- end
-
- describe '.advanced_search_for' do
- let(:account) { Fabricate(:account) }
-
- context 'when limiting search to followed accounts' do
- it 'accepts ?, \, : and space as delimiter' do
- match = Fabricate(
- :account,
- display_name: 'A & l & i & c & e',
- username: 'username',
- domain: 'example.com'
- )
- account.follow!(match)
-
- results = described_class.advanced_search_for('A?l\i:c e', account, limit: 10, following: true)
- expect(results).to eq [match]
- end
-
- it 'does not return non-followed accounts' do
- Fabricate(
- :account,
- display_name: 'A & l & i & c & e',
- username: 'username',
- domain: 'example.com'
- )
-
- results = described_class.advanced_search_for('A?l\i:c e', account, limit: 10, following: true)
- expect(results).to eq []
- end
-
- it 'does not return suspended users' do
- Fabricate(
- :account,
- display_name: 'Display Name',
- username: 'username',
- domain: 'example.com',
- suspended: true
- )
-
- results = described_class.advanced_search_for('username', account, limit: 10, following: true)
- expect(results).to eq []
- end
-
- it 'does not return unapproved users' do
- match = Fabricate(
- :account,
- display_name: 'Display Name',
- username: 'username'
- )
-
- match.user.update(approved: false)
-
- results = described_class.advanced_search_for('username', account, limit: 10, following: true)
- expect(results).to eq []
- end
-
- it 'does not return unconfirmed users' do
- match = Fabricate(
- :account,
- display_name: 'Display Name',
- username: 'username'
- )
-
- match.user.update(confirmed_at: nil)
-
- results = described_class.advanced_search_for('username', account, limit: 10, following: true)
- expect(results).to eq []
- end
- end
-
- it 'does not return suspended users' do
- Fabricate(
- :account,
- display_name: 'Display Name',
- username: 'username',
- domain: 'example.com',
- suspended: true
- )
-
- results = described_class.advanced_search_for('username', account)
- expect(results).to eq []
- end
-
- it 'does not return unapproved users' do
- match = Fabricate(
- :account,
- display_name: 'Display Name',
- username: 'username'
- )
-
- match.user.update(approved: false)
-
- results = described_class.advanced_search_for('username', account)
- expect(results).to eq []
- end
-
- it 'does not return unconfirmed users' do
- match = Fabricate(
- :account,
- display_name: 'Display Name',
- username: 'username'
- )
-
- match.user.update(confirmed_at: nil)
-
- results = described_class.advanced_search_for('username', account)
- expect(results).to eq []
- end
-
- it 'accepts ?, \, : and space as delimiter' do
- match = Fabricate(
- :account,
- display_name: 'A & l & i & c & e',
- username: 'username',
- domain: 'example.com'
- )
-
- results = described_class.advanced_search_for('A?l\i:c e', account)
- expect(results).to eq [match]
- end
-
- it 'limits result count by default value' do
- stub_const('Account::Search::DEFAULT_LIMIT', 1)
- 2.times { Fabricate(:account, display_name: 'Display Name') }
- results = described_class.advanced_search_for('display', account)
- expect(results.size).to eq 1
- end
-
- it 'accepts arbitrary limits' do
- 2.times { Fabricate(:account, display_name: 'Display Name') }
- results = described_class.advanced_search_for('display', account, limit: 1)
- expect(results.size).to eq 1
- end
-
- it 'ranks followed accounts higher' do
- match = Fabricate(:account, username: 'Matching')
- followed_match = Fabricate(:account, username: 'Matcher')
- Fabricate(:follow, account: account, target_account: followed_match)
-
- results = described_class.advanced_search_for('match', account)
- expect(results).to eq [followed_match, match]
- expect(results.first.rank).to be > results.last.rank
- end
- end
-
describe '#statuses_count' do
subject { Fabricate(:account) }
@@ -824,8 +594,12 @@ RSpec.describe Account do
it { is_expected.to_not allow_values(account_note_over_limit).for(:note) }
it { is_expected.to allow_value(fields_empty_name_value).for(:fields) }
- it { is_expected.to_not allow_value(fields_over_limit).for(:fields) }
- it { is_expected.to_not allow_value(fields_empty_name).for(:fields) }
+ it { is_expected.to_not allow_values(fields_over_limit, fields_empty_name).for(:fields) }
+
+ it { is_expected.to validate_absence_of(:followers_url).on(:create) }
+ it { is_expected.to validate_absence_of(:inbox_url).on(:create) }
+ it { is_expected.to validate_absence_of(:shared_inbox_url).on(:create) }
+ it { is_expected.to validate_absence_of(:uri).on(:create) }
end
context 'when account is remote' do
diff --git a/spec/models/account_warning_spec.rb b/spec/models/account_warning_spec.rb
index 37866ce3da..9fe2b331eb 100644
--- a/spec/models/account_warning_spec.rb
+++ b/spec/models/account_warning_spec.rb
@@ -8,4 +8,18 @@ RSpec.describe AccountWarning do
it { is_expected.to normalize(:text).from(nil).to('') }
end
end
+
+ describe '#appeal_eligible?' do
+ context 'when created too long ago' do
+ subject { Fabricate.build :account_warning, created_at: (described_class::APPEAL_WINDOW * 2).ago }
+
+ it { is_expected.to_not be_appeal_eligible }
+ end
+
+ context 'when created recently' do
+ subject { Fabricate.build :account_warning, created_at: (described_class::APPEAL_WINDOW - 2.days).ago }
+
+ it { is_expected.to be_appeal_eligible }
+ end
+ end
end
diff --git a/spec/models/appeal_spec.rb b/spec/models/appeal_spec.rb
index e974ff9254..d624e14949 100644
--- a/spec/models/appeal_spec.rb
+++ b/spec/models/appeal_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Appeal do
it { is_expected.to validate_length_of(:text).is_at_most(described_class::TEXT_LENGTH_LIMIT) }
context 'with a strike created too long ago' do
- let(:strike) { Fabricate.build :account_warning, created_at: 100.days.ago }
+ let(:strike) { Fabricate.build :account_warning, created_at: (AccountWarning::APPEAL_WINDOW * 2).ago }
it { is_expected.to_not allow_values(strike).for(:strike).against(:base).on(:create) }
end
diff --git a/spec/models/doorkeeper/application_spec.rb b/spec/models/doorkeeper/application_spec.rb
new file mode 100644
index 0000000000..e026d90caa
--- /dev/null
+++ b/spec/models/doorkeeper/application_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe Doorkeeper::Application do
+ describe 'Associations' do
+ it { is_expected.to have_many(:created_users).class_name('User').inverse_of(:created_by_application).with_foreign_key(:created_by_application_id) }
+ end
+
+ describe 'Validations' do
+ it { is_expected.to validate_length_of(:name).is_at_most(described_class::APP_NAME_LIMIT) }
+ it { is_expected.to validate_length_of(:redirect_uri).is_at_most(described_class::APP_REDIRECT_URI_LIMIT) }
+ it { is_expected.to validate_length_of(:website).is_at_most(described_class::APP_WEBSITE_LIMIT) }
+ end
+end
diff --git a/spec/models/form/admin_settings_spec.rb b/spec/models/form/admin_settings_spec.rb
index 73106f2b69..899d56703a 100644
--- a/spec/models/form/admin_settings_spec.rb
+++ b/spec/models/form/admin_settings_spec.rb
@@ -17,4 +17,40 @@ RSpec.describe Form::AdminSettings do
end
end
end
+
+ describe '#save' do
+ describe 'updating digest values' do
+ context 'when updating custom css to real value' do
+ subject { described_class.new(custom_css: css) }
+
+ let(:css) { 'body { color: red; }' }
+ let(:digested) { Digest::SHA256.hexdigest(css) }
+
+ it 'changes relevant digest value' do
+ expect { subject.save }
+ .to(change { Rails.cache.read(:setting_digest_custom_css) }.to(digested))
+ end
+ end
+
+ context 'when updating custom css to empty value' do
+ subject { described_class.new(custom_css: '') }
+
+ before { Rails.cache.write(:setting_digest_custom_css, 'previous-value') }
+
+ it 'changes relevant digest value' do
+ expect { subject.save }
+ .to(change { Rails.cache.read(:setting_digest_custom_css) }.to(be_blank))
+ end
+ end
+
+ context 'when updating other fields' do
+ subject { described_class.new(site_contact_email: 'test@example.host') }
+
+ it 'does not update digests' do
+ expect { subject.save }
+ .to(not_change { Rails.cache.read(:setting_digest_custom_css) })
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/trends/links_spec.rb b/spec/models/trends/links_spec.rb
new file mode 100644
index 0000000000..b0d41d4613
--- /dev/null
+++ b/spec/models/trends/links_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe Trends::Links do
+ describe 'Trends::Links::Query' do
+ subject { described_class.new.query }
+
+ describe '#records' do
+ context 'with scored cards' do
+ let!(:higher_score) { Fabricate :preview_card_trend, score: 10, language: 'en' }
+ let!(:lower_score) { Fabricate :preview_card_trend, score: 1, language: 'es' }
+
+ it 'returns higher score first' do
+ expect(subject.records)
+ .to eq([higher_score.preview_card, lower_score.preview_card])
+ end
+
+ context 'with preferred locale' do
+ before { subject.in_locale!('es') }
+
+ it 'returns in language order' do
+ expect(subject.records)
+ .to eq([lower_score.preview_card, higher_score.preview_card])
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/trends/statuses_spec.rb b/spec/models/trends/statuses_spec.rb
index 7c30b5b997..abb1535d04 100644
--- a/spec/models/trends/statuses_spec.rb
+++ b/spec/models/trends/statuses_spec.rb
@@ -45,6 +45,31 @@ RSpec.describe Trends::Statuses do
end
end
+ describe 'Trends::Statuses::Query methods' do
+ subject { described_class.new.query }
+
+ describe '#records' do
+ context 'with scored cards' do
+ let!(:higher_score) { Fabricate :status_trend, score: 10, language: 'en' }
+ let!(:lower_score) { Fabricate :status_trend, score: 1, language: 'es' }
+
+ it 'returns higher score first' do
+ expect(subject.records)
+ .to eq([higher_score.status, lower_score.status])
+ end
+
+ context 'with preferred locale' do
+ before { subject.in_locale!('es') }
+
+ it 'returns in language order' do
+ expect(subject.records)
+ .to eq([lower_score.status, higher_score.status])
+ end
+ end
+ end
+ end
+ end
+
describe '#add' do
let(:status) { Fabricate(:status) }
diff --git a/spec/models/trends/tags_spec.rb b/spec/models/trends/tags_spec.rb
index 936b441d92..8f36b4a50d 100644
--- a/spec/models/trends/tags_spec.rb
+++ b/spec/models/trends/tags_spec.rb
@@ -29,6 +29,31 @@ RSpec.describe Trends::Tags do
end
end
+ describe 'Trends::Tags::Query' do
+ subject { described_class.new.query }
+
+ describe '#records' do
+ context 'with scored cards' do
+ let!(:higher_score) { Fabricate :tag_trend, score: 10, language: 'en' }
+ let!(:lower_score) { Fabricate :tag_trend, score: 1, language: 'es' }
+
+ it 'returns higher score first' do
+ expect(subject.records)
+ .to eq([higher_score.tag, lower_score.tag])
+ end
+
+ context 'with preferred locale' do
+ before { subject.in_locale!('es') }
+
+ it 'returns in language order' do
+ expect(subject.records)
+ .to eq([lower_score.tag, higher_score.tag])
+ end
+ end
+ end
+ end
+ end
+
describe '#refresh' do
let!(:today) { at_time }
let!(:yesterday) { today - 1.day }
diff --git a/spec/policies/account_warning_policy_spec.rb b/spec/policies/account_warning_policy_spec.rb
index 75142e2071..2603794886 100644
--- a/spec/policies/account_warning_policy_spec.rb
+++ b/spec/policies/account_warning_policy_spec.rb
@@ -31,11 +31,11 @@ RSpec.describe AccountWarningPolicy do
context 'when account is target' do
context 'when record is appealable' do
- it { is_expected.to permit(account, AccountWarning.new(target_account_id: account.id, created_at: Appeal::MAX_STRIKE_AGE.ago + 1.hour)) }
+ it { is_expected.to permit(account, AccountWarning.new(target_account_id: account.id, created_at: AccountWarning::APPEAL_WINDOW.ago + 1.hour)) }
end
context 'when record is not appealable' do
- it { is_expected.to_not permit(account, AccountWarning.new(target_account_id: account.id, created_at: Appeal::MAX_STRIKE_AGE.ago - 1.hour)) }
+ it { is_expected.to_not permit(account, AccountWarning.new(target_account_id: account.id, created_at: AccountWarning::APPEAL_WINDOW.ago - 1.hour)) }
end
end
end
diff --git a/spec/policies/backup_policy_spec.rb b/spec/policies/backup_policy_spec.rb
index 031021d91d..28995d195b 100644
--- a/spec/policies/backup_policy_spec.rb
+++ b/spec/policies/backup_policy_spec.rb
@@ -23,22 +23,30 @@ RSpec.describe BackupPolicy do
context 'when backups are too old' do
it 'permits' do
- travel(-8.days) do
+ travel(-before_time) do
Fabricate(:backup, user: john.user)
end
expect(subject).to permit(john, Backup)
end
+
+ def before_time
+ described_class::MIN_AGE + 2.days
+ end
end
context 'when backups are newer' do
it 'denies' do
- travel(-3.days) do
+ travel(-within_time) do
Fabricate(:backup, user: john.user)
end
expect(subject).to_not permit(john, Backup)
end
+
+ def within_time
+ described_class::MIN_AGE - 2.days
+ end
end
end
end
diff --git a/spec/requests/accounts_spec.rb b/spec/requests/accounts_spec.rb
index afd9ac80e2..72913ebf22 100644
--- a/spec/requests/accounts_spec.rb
+++ b/spec/requests/accounts_spec.rb
@@ -53,8 +53,9 @@ RSpec.describe 'Accounts show response' do
it 'returns a standard HTML response', :aggregate_failures do
expect(response)
.to have_http_status(200)
- .and render_template(:show)
.and have_http_link_header(ActivityPub::TagManager.instance.uri_for(account)).for(rel: 'alternate')
+ expect(response.parsed_body.at('title').content)
+ .to include(account.username)
end
end
diff --git a/spec/requests/api/v1/accounts/credentials_spec.rb b/spec/requests/api/v1/accounts/credentials_spec.rb
index 966d1f598e..0badc17e1b 100644
--- a/spec/requests/api/v1/accounts/credentials_spec.rb
+++ b/spec/requests/api/v1/accounts/credentials_spec.rb
@@ -85,7 +85,7 @@ RSpec.describe 'credentials API' do
end
describe 'with invalid data' do
- let(:params) { { note: "This is too long. #{'a' * Account::NOTE_LENGTH_LIMIT}" } }
+ let(:params) { { note: 'a' * 2 * Account::NOTE_LENGTH_LIMIT } }
it 'returns http unprocessable entity' do
subject
diff --git a/spec/requests/api/v1/accounts/notes_spec.rb b/spec/requests/api/v1/accounts/notes_spec.rb
index 1677ec07e3..e616df1e6f 100644
--- a/spec/requests/api/v1/accounts/notes_spec.rb
+++ b/spec/requests/api/v1/accounts/notes_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe 'Accounts Notes API' do
end
context 'when account note exceeds allowed length', :aggregate_failures do
- let(:comment) { 'a' * 2_001 }
+ let(:comment) { 'a' * AccountNote::COMMENT_SIZE_LIMIT * 2 }
it 'does not create account note' do
subject
diff --git a/spec/requests/api/v1/apps_spec.rb b/spec/requests/api/v1/apps_spec.rb
index 4e9147ba32..3120ab9c64 100644
--- a/spec/requests/api/v1/apps_spec.rb
+++ b/spec/requests/api/v1/apps_spec.rb
@@ -122,7 +122,7 @@ RSpec.describe 'Apps' do
end
context 'with a too-long name' do
- let(:client_name) { 'hoge' * 20 }
+ let(:client_name) { 'a' * Doorkeeper::Application::APP_NAME_LIMIT * 2 }
it 'returns http unprocessable entity' do
subject
@@ -134,7 +134,7 @@ RSpec.describe 'Apps' do
end
context 'with a too-long website' do
- let(:website) { "https://foo.bar/#{'hoge' * 2_000}" }
+ let(:website) { "https://foo.bar/#{'a' * Doorkeeper::Application::APP_WEBSITE_LIMIT * 2}" }
it 'returns http unprocessable entity' do
subject
@@ -146,7 +146,7 @@ RSpec.describe 'Apps' do
end
context 'with a too-long redirect_uri' do
- let(:redirect_uris) { "https://app.example/#{'hoge' * 2_000}" }
+ let(:redirect_uris) { "https://app.example/#{'a' * Doorkeeper::Application::APP_REDIRECT_URI_LIMIT * 2}" }
it 'returns http unprocessable entity' do
subject
diff --git a/spec/requests/api/v2/media_spec.rb b/spec/requests/api/v2/media_spec.rb
index 807e427d3f..18ebb9cdda 100644
--- a/spec/requests/api/v2/media_spec.rb
+++ b/spec/requests/api/v2/media_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe 'Media API', :attachment_processing do
let(:params) do
{
file: fixture_file_upload('attachment-jpg.123456_abcd', 'image/jpeg'),
- description: 'aa' * MediaAttachment::MAX_DESCRIPTION_LENGTH,
+ description: 'a' * MediaAttachment::MAX_DESCRIPTION_LENGTH * 2,
}
end
diff --git a/spec/requests/api/v2/notifications_spec.rb b/spec/requests/api/v2/notifications_spec.rb
index ffa0a71c77..aa4a861557 100644
--- a/spec/requests/api/v2/notifications_spec.rb
+++ b/spec/requests/api/v2/notifications_spec.rb
@@ -143,6 +143,55 @@ RSpec.describe 'Notifications' do
end
end
+ context 'when there are numerous notifications for the same final group' do
+ before do
+ user.account.notifications.destroy_all
+ 5.times.each { FavouriteService.new.call(Fabricate(:account), user.account.statuses.first) }
+ end
+
+ context 'with no options' do
+ it 'returns a notification group covering all notifications' do
+ subject
+
+ notification_ids = user.account.notifications.reload.pluck(:id)
+
+ expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:notification_groups]).to contain_exactly(
+ a_hash_including(
+ type: 'favourite',
+ sample_account_ids: have_attributes(size: 5),
+ page_min_id: notification_ids.first.to_s,
+ page_max_id: notification_ids.last.to_s
+ )
+ )
+ end
+ end
+
+ context 'with min_id param' do
+ let(:params) { { min_id: user.account.notifications.reload.first.id - 1 } }
+
+ it 'returns a notification group covering all notifications' do
+ subject
+
+ notification_ids = user.account.notifications.reload.pluck(:id)
+
+ expect(response).to have_http_status(200)
+ expect(response.content_type)
+ .to start_with('application/json')
+ expect(response.parsed_body[:notification_groups]).to contain_exactly(
+ a_hash_including(
+ type: 'favourite',
+ sample_account_ids: have_attributes(size: 5),
+ page_min_id: notification_ids.first.to_s,
+ page_max_id: notification_ids.last.to_s
+ )
+ )
+ end
+ end
+ end
+
context 'with no options' do
it 'returns expected notification types', :aggregate_failures do
subject
diff --git a/spec/controllers/auth/challenges_controller_spec.rb b/spec/requests/auth/challenges_spec.rb
similarity index 64%
rename from spec/controllers/auth/challenges_controller_spec.rb
rename to spec/requests/auth/challenges_spec.rb
index 3c9d2a5964..628bfe499b 100644
--- a/spec/controllers/auth/challenges_controller_spec.rb
+++ b/spec/requests/auth/challenges_spec.rb
@@ -2,9 +2,7 @@
require 'rails_helper'
-RSpec.describe Auth::ChallengesController do
- render_views
-
+RSpec.describe 'Auth Challenges' do
let(:password) { 'foobar12345' }
let(:user) { Fabricate(:user, password: password) }
@@ -14,9 +12,9 @@ RSpec.describe Auth::ChallengesController do
let(:return_to) { edit_user_registration_path }
context 'with correct password' do
- before { post :create, params: { form_challenge: { return_to: return_to, current_password: password } } }
-
it 'redirects back and sets challenge passed at in session' do
+ post '/auth/challenge', params: { form_challenge: { return_to: return_to, current_password: password } }
+
expect(response)
.to redirect_to(return_to)
expect(session[:challenge_passed_at])
@@ -25,13 +23,12 @@ RSpec.describe Auth::ChallengesController do
end
context 'with incorrect password' do
- before { post :create, params: { form_challenge: { return_to: return_to, current_password: 'hhfggjjd562' } } }
-
it 'renders challenge, displays error, does not set session' do
- expect(response)
- .to render_template('auth/challenges/new')
+ post '/auth/challenge', params: { form_challenge: { return_to: return_to, current_password: 'hhfggjjd562' } }
+
expect(response.body)
- .to include 'Invalid password'
+ .to include(I18n.t('challenge.prompt'))
+ .and include('Invalid password')
expect(session[:challenge_passed_at])
.to be_nil
end
diff --git a/spec/requests/cache_spec.rb b/spec/requests/cache_spec.rb
index 2a52e4dea9..8ca2817263 100644
--- a/spec/requests/cache_spec.rb
+++ b/spec/requests/cache_spec.rb
@@ -10,6 +10,7 @@ module TestEndpoints
/.well-known/nodeinfo
/nodeinfo/2.0
/manifest
+ /css/custom-1a2s3d4f.css
/custom.css
/actor
/api/v1/instance/extended_description
diff --git a/spec/requests/custom_css_spec.rb b/spec/requests/custom_css_spec.rb
index d97da00187..66ff5c4b13 100644
--- a/spec/requests/custom_css_spec.rb
+++ b/spec/requests/custom_css_spec.rb
@@ -5,10 +5,10 @@ require 'rails_helper'
RSpec.describe 'Custom CSS' do
include RoutingHelper
- describe 'GET /custom.css' do
+ describe 'GET /css/:id.css' do
context 'without any CSS or User Roles' do
it 'returns empty stylesheet' do
- get '/custom.css'
+ get '/css/custom-123.css'
expect(response)
.to have_http_status(200)
@@ -27,7 +27,7 @@ RSpec.describe 'Custom CSS' do
end
it 'returns stylesheet from settings' do
- get '/custom.css'
+ get '/css/custom-456.css'
expect(response)
.to have_http_status(200)
@@ -45,34 +45,5 @@ RSpec.describe 'Custom CSS' do
CSS
end
end
-
- context 'with highlighted colored UserRole records' do
- before do
- _highlighted_colored = Fabricate :user_role, highlighted: true, color: '#336699', id: '123_123_123'
- _highlighted_no_color = Fabricate :user_role, highlighted: true, color: ''
- _no_highlight_with_color = Fabricate :user_role, highlighted: false, color: ''
- end
-
- it 'returns stylesheet from settings' do
- get '/custom.css'
-
- expect(response)
- .to have_http_status(200)
- .and have_cacheable_headers
- .and have_attributes(
- content_type: match('text/css')
- )
- expect(response.body.strip)
- .to eq(expected_css)
- end
-
- def expected_css
- <<~CSS.strip
- .user-role-123123123 {
- --user-role-accent: #336699;
- }
- CSS
- end
- end
end
end
diff --git a/spec/requests/remote_interaction_helper_spec.rb b/spec/requests/remote_interaction_helper_spec.rb
index 942f70b9a4..b89060b5b2 100644
--- a/spec/requests/remote_interaction_helper_spec.rb
+++ b/spec/requests/remote_interaction_helper_spec.rb
@@ -9,7 +9,6 @@ RSpec.describe 'Remote Interaction Helper' do
expect(response)
.to have_http_status(200)
- .and render_template(:index, layout: 'helper_frame')
.and have_attributes(
headers: include(
'X-Frame-Options' => 'SAMEORIGIN',
@@ -17,6 +16,8 @@ RSpec.describe 'Remote Interaction Helper' do
'Content-Security-Policy' => expected_csp_headers
)
)
+ expect(response.body)
+ .to match(/remote_interaction_helper/)
end
end
diff --git a/spec/requests/settings/migrations_spec.rb b/spec/requests/settings/migrations_spec.rb
new file mode 100644
index 0000000000..4103d6b320
--- /dev/null
+++ b/spec/requests/settings/migrations_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Settings Migrations' do
+ describe 'GET #show' do
+ context 'when user is not signed in' do
+ subject { get '/settings/migration' }
+
+ it { is_expected.to redirect_to new_user_session_path }
+ end
+ end
+
+ describe 'POST #create' do
+ context 'when user is not signed in' do
+ subject { post '/settings/migration' }
+
+ it { is_expected.to redirect_to new_user_session_path }
+ end
+ end
+end
diff --git a/spec/routing/custom_css_routing_spec.rb b/spec/routing/custom_css_routing_spec.rb
new file mode 100644
index 0000000000..26139b4744
--- /dev/null
+++ b/spec/routing/custom_css_routing_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Custom CSS routes' do
+ describe 'the legacy route' do
+ it 'routes to correct place' do
+ expect(get('/custom.css'))
+ .to route_to('custom_css#show')
+ end
+ end
+
+ describe 'the custom digest route' do
+ it 'routes to correct place' do
+ expect(get('/css/custom-1a2s3d4f.css'))
+ .to route_to('custom_css#show', id: 'custom-1a2s3d4f', format: 'css')
+ end
+ end
+end
diff --git a/spec/serializers/rest/scheduled_status_serializer_spec.rb b/spec/serializers/rest/scheduled_status_serializer_spec.rb
index 08ad8a6f8a..2cf0098654 100644
--- a/spec/serializers/rest/scheduled_status_serializer_spec.rb
+++ b/spec/serializers/rest/scheduled_status_serializer_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe REST::ScheduledStatusSerializer do
expect(subject.deep_symbolize_keys)
.to include(
scheduled_at: be_a(String).and(match_api_datetime_format),
- params: not_include(:application_id)
+ params: include(:application_id)
)
end
end
diff --git a/spec/support/examples/models/concerns/account/search.rb b/spec/support/examples/models/concerns/account/search.rb
new file mode 100644
index 0000000000..9d9b499732
--- /dev/null
+++ b/spec/support/examples/models/concerns/account/search.rb
@@ -0,0 +1,268 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'Account::Search' do
+ describe '.search_for' do
+ before do
+ _missing = Fabricate(
+ :account,
+ display_name: 'Missing',
+ username: 'missing',
+ domain: 'missing.com'
+ )
+ end
+
+ it 'does not return suspended users' do
+ Fabricate(
+ :account,
+ display_name: 'Display Name',
+ username: 'username',
+ domain: 'example.com',
+ suspended: true
+ )
+
+ results = described_class.search_for('username')
+ expect(results).to eq []
+ end
+
+ it 'does not return unapproved users' do
+ match = Fabricate(
+ :account,
+ display_name: 'Display Name',
+ username: 'username'
+ )
+
+ match.user.update(approved: false)
+
+ results = described_class.search_for('username')
+ expect(results).to eq []
+ end
+
+ it 'does not return unconfirmed users' do
+ match = Fabricate(
+ :account,
+ display_name: 'Display Name',
+ username: 'username'
+ )
+
+ match.user.update(confirmed_at: nil)
+
+ results = described_class.search_for('username')
+ expect(results).to eq []
+ end
+
+ it 'accepts ?, \, : and space as delimiter' do
+ match = Fabricate(
+ :account,
+ display_name: 'A & l & i & c & e',
+ username: 'username',
+ domain: 'example.com'
+ )
+
+ results = described_class.search_for('A?l\i:c e')
+ expect(results).to eq [match]
+ end
+
+ it 'finds accounts with matching display_name' do
+ match = Fabricate(
+ :account,
+ display_name: 'Display Name',
+ username: 'username',
+ domain: 'example.com'
+ )
+
+ results = described_class.search_for('display')
+ expect(results).to eq [match]
+ end
+
+ it 'finds accounts with matching username' do
+ match = Fabricate(
+ :account,
+ display_name: 'Display Name',
+ username: 'username',
+ domain: 'example.com'
+ )
+
+ results = described_class.search_for('username')
+ expect(results).to eq [match]
+ end
+
+ it 'finds accounts with matching domain' do
+ match = Fabricate(
+ :account,
+ display_name: 'Display Name',
+ username: 'username',
+ domain: 'example.com'
+ )
+
+ results = described_class.search_for('example')
+ expect(results).to eq [match]
+ end
+
+ it 'limits via constant by default' do
+ stub_const('Account::Search::DEFAULT_LIMIT', 1)
+ 2.times.each { Fabricate(:account, display_name: 'Display Name') }
+ results = described_class.search_for('display')
+ expect(results.size).to eq 1
+ end
+
+ it 'accepts arbitrary limits' do
+ 2.times.each { Fabricate(:account, display_name: 'Display Name') }
+ results = described_class.search_for('display', limit: 1)
+ expect(results.size).to eq 1
+ end
+
+ it 'ranks multiple matches higher' do
+ matches = [
+ { username: 'username', display_name: 'username' },
+ { display_name: 'Display Name', username: 'username', domain: 'example.com' },
+ ].map(&method(:Fabricate).curry(2).call(:account))
+
+ results = described_class.search_for('username')
+ expect(results).to eq matches
+ end
+ end
+
+ describe '.advanced_search_for' do
+ let(:account) { Fabricate(:account) }
+
+ context 'when limiting search to followed accounts' do
+ it 'accepts ?, \, : and space as delimiter' do
+ match = Fabricate(
+ :account,
+ display_name: 'A & l & i & c & e',
+ username: 'username',
+ domain: 'example.com'
+ )
+ account.follow!(match)
+
+ results = described_class.advanced_search_for('A?l\i:c e', account, limit: 10, following: true)
+ expect(results).to eq [match]
+ end
+
+ it 'does not return non-followed accounts' do
+ Fabricate(
+ :account,
+ display_name: 'A & l & i & c & e',
+ username: 'username',
+ domain: 'example.com'
+ )
+
+ results = described_class.advanced_search_for('A?l\i:c e', account, limit: 10, following: true)
+ expect(results).to eq []
+ end
+
+ it 'does not return suspended users' do
+ Fabricate(
+ :account,
+ display_name: 'Display Name',
+ username: 'username',
+ domain: 'example.com',
+ suspended: true
+ )
+
+ results = described_class.advanced_search_for('username', account, limit: 10, following: true)
+ expect(results).to eq []
+ end
+
+ it 'does not return unapproved users' do
+ match = Fabricate(
+ :account,
+ display_name: 'Display Name',
+ username: 'username'
+ )
+
+ match.user.update(approved: false)
+
+ results = described_class.advanced_search_for('username', account, limit: 10, following: true)
+ expect(results).to eq []
+ end
+
+ it 'does not return unconfirmed users' do
+ match = Fabricate(
+ :account,
+ display_name: 'Display Name',
+ username: 'username'
+ )
+
+ match.user.update(confirmed_at: nil)
+
+ results = described_class.advanced_search_for('username', account, limit: 10, following: true)
+ expect(results).to eq []
+ end
+ end
+
+ it 'does not return suspended users' do
+ Fabricate(
+ :account,
+ display_name: 'Display Name',
+ username: 'username',
+ domain: 'example.com',
+ suspended: true
+ )
+
+ results = described_class.advanced_search_for('username', account)
+ expect(results).to eq []
+ end
+
+ it 'does not return unapproved users' do
+ match = Fabricate(
+ :account,
+ display_name: 'Display Name',
+ username: 'username'
+ )
+
+ match.user.update(approved: false)
+
+ results = described_class.advanced_search_for('username', account)
+ expect(results).to eq []
+ end
+
+ it 'does not return unconfirmed users' do
+ match = Fabricate(
+ :account,
+ display_name: 'Display Name',
+ username: 'username'
+ )
+
+ match.user.update(confirmed_at: nil)
+
+ results = described_class.advanced_search_for('username', account)
+ expect(results).to eq []
+ end
+
+ it 'accepts ?, \, : and space as delimiter' do
+ match = Fabricate(
+ :account,
+ display_name: 'A & l & i & c & e',
+ username: 'username',
+ domain: 'example.com'
+ )
+
+ results = described_class.advanced_search_for('A?l\i:c e', account)
+ expect(results).to eq [match]
+ end
+
+ it 'limits result count by default value' do
+ stub_const('Account::Search::DEFAULT_LIMIT', 1)
+ 2.times { Fabricate(:account, display_name: 'Display Name') }
+ results = described_class.advanced_search_for('display', account)
+ expect(results.size).to eq 1
+ end
+
+ it 'accepts arbitrary limits' do
+ 2.times { Fabricate(:account, display_name: 'Display Name') }
+ results = described_class.advanced_search_for('display', account, limit: 1)
+ expect(results.size).to eq 1
+ end
+
+ it 'ranks followed accounts higher' do
+ match = Fabricate(:account, username: 'Matching')
+ followed_match = Fabricate(:account, username: 'Matcher')
+ Fabricate(:follow, account: account, target_account: followed_match)
+
+ results = described_class.advanced_search_for('match', account)
+ expect(results).to eq [followed_match, match]
+ expect(results.first.rank).to be > results.last.rank
+ end
+ end
+end
diff --git a/spec/system/admin/follow_recommendations_spec.rb b/spec/system/admin/follow_recommendations_spec.rb
new file mode 100644
index 0000000000..141a0f8152
--- /dev/null
+++ b/spec/system/admin/follow_recommendations_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Admin Follow Recommendations' do
+ let(:user) { Fabricate(:admin_user) }
+
+ before { sign_in(user) }
+
+ describe 'Viewing follow recommendations details' do
+ it 'shows a list of accounts' do
+ visit admin_follow_recommendations_path
+
+ expect(page)
+ .to have_content(I18n.t('admin.follow_recommendations.title'))
+ end
+ end
+end
diff --git a/spec/system/admin/terms_of_service/histories_spec.rb b/spec/system/admin/terms_of_service/histories_spec.rb
new file mode 100644
index 0000000000..aa59550d09
--- /dev/null
+++ b/spec/system/admin/terms_of_service/histories_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Admin Terms of Service Histories' do
+ let(:current_user) { Fabricate(:admin_user) }
+
+ before { sign_in(current_user) }
+
+ describe 'Viewing TOS histories' do
+ before { Fabricate :terms_of_service, changelog: 'The changelog notes from v1 are here' }
+
+ it 'shows previous terms versions' do
+ visit admin_terms_of_service_history_path
+
+ expect(page)
+ .to have_content(I18n.t('admin.terms_of_service.history'))
+ .and have_content(/changelog notes from v1/)
+ end
+ end
+end
diff --git a/spec/system/settings/migrations_spec.rb b/spec/system/settings/migrations_spec.rb
new file mode 100644
index 0000000000..fecde36f35
--- /dev/null
+++ b/spec/system/settings/migrations_spec.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe 'Settings Migrations' do
+ describe 'Viewing settings migrations' do
+ let(:user) { Fabricate(:account, moved_to_account: moved_to_account).user }
+
+ before { sign_in(user) }
+
+ context 'when user does not have moved to account' do
+ let(:moved_to_account) { nil }
+
+ it 'renders show page' do
+ visit settings_migration_path
+
+ expect(page)
+ .to have_content(I18n.t('settings.migrate'))
+ end
+ end
+
+ context 'when user has a moved to account' do
+ let(:moved_to_account) { Fabricate(:account) }
+
+ it 'renders show page and account details' do
+ visit settings_migration_path
+
+ expect(page)
+ .to have_content(I18n.t('settings.migrate'))
+ .and have_content(moved_to_account.pretty_acct)
+ end
+ end
+ end
+
+ describe 'Creating migrations' do
+ let(:user) { Fabricate(:user, password: '12345678') }
+
+ before { sign_in(user) }
+
+ context 'when migration account is changed' do
+ let(:acct) { Fabricate(:account, also_known_as: [ActivityPub::TagManager.instance.uri_for(user.account)]) }
+
+ it 'updates moved to account' do
+ visit settings_migration_path
+
+ expect { fill_in_and_submit }
+ .to(change { user.account.reload.moved_to_account_id }.to(acct.id))
+ expect(page)
+ .to have_content(I18n.t('settings.migrate'))
+ end
+ end
+
+ context 'when acct is the current account' do
+ let(:acct) { user.account }
+
+ it 'does not update the moved account', :aggregate_failures do
+ visit settings_migration_path
+
+ expect { fill_in_and_submit }
+ .to_not(change { user.account.reload.moved_to_account_id }.from(nil))
+ expect(page)
+ .to have_content(I18n.t('settings.migrate'))
+ end
+ end
+
+ context 'when target account does not reference the account being moved from' do
+ let(:acct) { Fabricate(:account, also_known_as: []) }
+
+ it 'does not update the moved account', :aggregate_failures do
+ visit settings_migration_path
+
+ expect { fill_in_and_submit }
+ .to_not(change { user.account.reload.moved_to_account_id }.from(nil))
+ expect(page)
+ .to have_content(I18n.t('settings.migrate'))
+ end
+ end
+
+ context 'when a recent migration already exists' do
+ let(:acct) { Fabricate(:account, also_known_as: [ActivityPub::TagManager.instance.uri_for(user.account)]) }
+ let(:moved_to) { Fabricate(:account, also_known_as: [ActivityPub::TagManager.instance.uri_for(user.account)]) }
+
+ before { user.account.migrations.create!(acct: moved_to.acct) }
+
+ it 'can not update the moved account', :aggregate_failures do
+ visit settings_migration_path
+
+ expect(find_by_id('account_migration_acct'))
+ .to be_disabled
+ end
+ end
+
+ def fill_in_and_submit
+ fill_in 'account_migration_acct', with: acct.username
+ fill_in 'account_migration_current_password', with: '12345678'
+ click_on I18n.t('migrations.proceed_with_move')
+ end
+ end
+end
diff --git a/streaming/package.json b/streaming/package.json
index 2419ffd273..b98608edd5 100644
--- a/streaming/package.json
+++ b/streaming/package.json
@@ -21,7 +21,7 @@
"dotenv": "^16.0.3",
"express": "^4.18.2",
"ioredis": "^5.3.2",
- "jsdom": "^25.0.0",
+ "jsdom": "^26.0.0",
"pg": "^8.5.0",
"pg-connection-string": "^2.6.0",
"pino": "^9.0.0",
diff --git a/yarn.lock b/yarn.lock
index 5aa4814237..8335f8b992 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -42,6 +42,19 @@ __metadata:
languageName: node
linkType: hard
+"@asamuzakjp/css-color@npm:^2.8.2":
+ version: 2.8.2
+ resolution: "@asamuzakjp/css-color@npm:2.8.2"
+ dependencies:
+ "@csstools/css-calc": "npm:^2.1.1"
+ "@csstools/css-color-parser": "npm:^3.0.7"
+ "@csstools/css-parser-algorithms": "npm:^3.0.4"
+ "@csstools/css-tokenizer": "npm:^3.0.3"
+ lru-cache: "npm:^11.0.2"
+ checksum: 10c0/352b91ca7741876e459cd3cb350a969e842da1e532577157d38365a6da89b7d6e6944249489366ee61b8a225ede1b521e7ab305b70ad4c688b01404061eecca8
+ 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.25.9, @babel/code-frame@npm:^7.26.0":
version: 7.26.0
resolution: "@babel/code-frame@npm:7.26.0"
@@ -2267,14 +2280,15 @@ __metadata:
languageName: node
linkType: hard
-"@formatjs/ecma402-abstract@npm:2.2.3":
- version: 2.2.3
- resolution: "@formatjs/ecma402-abstract@npm:2.2.3"
+"@formatjs/ecma402-abstract@npm:2.3.2":
+ version: 2.3.2
+ resolution: "@formatjs/ecma402-abstract@npm:2.3.2"
dependencies:
- "@formatjs/fast-memoize": "npm:2.2.3"
- "@formatjs/intl-localematcher": "npm:0.5.7"
+ "@formatjs/fast-memoize": "npm:2.2.6"
+ "@formatjs/intl-localematcher": "npm:0.5.10"
+ decimal.js: "npm:10"
tslib: "npm:2"
- checksum: 10c0/611d12bf320fc5c5b85cb2b57e3dcebe8490a51c6a0459c857c7a3560656cd2bdba5b117e9dd7cf174f5aa120c11eaad7a65a6783637b816caa59a1bc5c727f6
+ checksum: 10c0/364e9e7de974fed976e0e8142a0f888ee0af4a11a61899115e5761ed933e7c1f16379b7b54a01524fd3c5d58bf08b71308237ea969cd54889eaf7bb2d30ec776
languageName: node
linkType: hard
@@ -2287,12 +2301,12 @@ __metadata:
languageName: node
linkType: hard
-"@formatjs/fast-memoize@npm:2.2.3":
- version: 2.2.3
- resolution: "@formatjs/fast-memoize@npm:2.2.3"
+"@formatjs/fast-memoize@npm:2.2.6":
+ version: 2.2.6
+ resolution: "@formatjs/fast-memoize@npm:2.2.6"
dependencies:
tslib: "npm:2"
- checksum: 10c0/f1004c3b280de7e362bd37c5f48ff34c2ba1d6271d4a7b695fed561d1201a3379397824d8bffbf15fecee344d1e70398393bbb04297f242692310a305f12e75b
+ checksum: 10c0/dccdc21105af673e58ec7b04eb17cd6fde1fb1a7e7a446273ca43f7ab97c26d5c0fcc2b9e80d5b54bf9b80354f9e1e681273c0ed26633ec72f0adc2d116dfd7f
languageName: node
linkType: hard
@@ -2307,14 +2321,24 @@ __metadata:
languageName: node
linkType: hard
-"@formatjs/icu-messageformat-parser@npm:2.9.3":
- version: 2.9.3
- resolution: "@formatjs/icu-messageformat-parser@npm:2.9.3"
+"@formatjs/icu-messageformat-parser@npm:2.9.8":
+ version: 2.9.8
+ resolution: "@formatjs/icu-messageformat-parser@npm:2.9.8"
dependencies:
- "@formatjs/ecma402-abstract": "npm:2.2.3"
- "@formatjs/icu-skeleton-parser": "npm:1.8.7"
+ "@formatjs/ecma402-abstract": "npm:2.3.2"
+ "@formatjs/icu-skeleton-parser": "npm:1.8.12"
tslib: "npm:2"
- checksum: 10c0/519b59f7b4cf90681315c5382f7fcd105eb1974486f0d62d9227b6d0498895114ccc818792c208baae1ef79571d93b0edb9914c676e5ab76924dddb7fd6c28a0
+ checksum: 10c0/df97c7f24fbeb8ef49ae1371f9498ad90f231f88211bf1effb7b2e8ac3531bec67c5d9147ddcb1add0ba697e8d089729add44a9a9c5015e0e8d61e7a43f062d9
+ languageName: node
+ linkType: hard
+
+"@formatjs/icu-skeleton-parser@npm:1.8.12":
+ version: 1.8.12
+ resolution: "@formatjs/icu-skeleton-parser@npm:1.8.12"
+ dependencies:
+ "@formatjs/ecma402-abstract": "npm:2.3.2"
+ tslib: "npm:2"
+ checksum: 10c0/03e743aa09acb2137e37d03b98578fcbbc949d056b8c151763778e885d04d621e69c82f7656547f0532351d2a987bffac0a8c4c3d81186f47a28047ba64385e2
languageName: node
linkType: hard
@@ -2328,35 +2352,12 @@ __metadata:
languageName: node
linkType: hard
-"@formatjs/icu-skeleton-parser@npm:1.8.7":
- version: 1.8.7
- resolution: "@formatjs/icu-skeleton-parser@npm:1.8.7"
+"@formatjs/intl-localematcher@npm:0.5.10":
+ version: 0.5.10
+ resolution: "@formatjs/intl-localematcher@npm:0.5.10"
dependencies:
- "@formatjs/ecma402-abstract": "npm:2.2.3"
tslib: "npm:2"
- checksum: 10c0/e29eb4151580f2d324e6591509dc4543e2326266fc209a08580c94d502acab14acc3560d98b3aaf9ffbd5ff8e2683601ff08c65b32886f22da015c31ca35c5d0
- languageName: node
- linkType: hard
-
-"@formatjs/intl-displaynames@npm:6.8.3":
- version: 6.8.3
- resolution: "@formatjs/intl-displaynames@npm:6.8.3"
- dependencies:
- "@formatjs/ecma402-abstract": "npm:2.2.3"
- "@formatjs/intl-localematcher": "npm:0.5.7"
- tslib: "npm:2"
- checksum: 10c0/54d3ecaabc45dc8494be4cd9633bbf5eb0bc40c5f62ed5e5073aa5b214c4a9a9620d61d1c8a6f0074618474fd9c2ccc42904605078d2f6341c242bf43627bb3a
- languageName: node
- linkType: hard
-
-"@formatjs/intl-listformat@npm:7.7.3":
- version: 7.7.3
- resolution: "@formatjs/intl-listformat@npm:7.7.3"
- dependencies:
- "@formatjs/ecma402-abstract": "npm:2.2.3"
- "@formatjs/intl-localematcher": "npm:0.5.7"
- tslib: "npm:2"
- checksum: 10c0/2683513e86cc7885528f23237079e3ab9e3a8bc7111aa10d4c685dcbe368ef07039573115df240112fb20f2ec0b70c8ea189ea3b79cbfed7e3dc46024a4667ff
+ checksum: 10c0/362ec83aca9382165be575f1cefa477478339e6fead8ca8866185ce6e58427ea1487a811b12c73d1bcfa99fd4db0c24543b35c823451839f585576bfccb8c9cc
languageName: node
linkType: hard
@@ -2369,43 +2370,33 @@ __metadata:
languageName: node
linkType: hard
-"@formatjs/intl-localematcher@npm:0.5.7":
- version: 0.5.7
- resolution: "@formatjs/intl-localematcher@npm:0.5.7"
- dependencies:
- tslib: "npm:2"
- checksum: 10c0/1ae374ca146a0d7457794926eed808c99971628e594f704a42ae2540b1f38928b26cbf942a7bbcc2796cc9fe8d9d7a603ac422bd9b89b714d2f91b506da40792
- languageName: node
- linkType: hard
-
"@formatjs/intl-pluralrules@npm:^5.2.2":
- version: 5.3.3
- resolution: "@formatjs/intl-pluralrules@npm:5.3.3"
+ version: 5.4.2
+ resolution: "@formatjs/intl-pluralrules@npm:5.4.2"
dependencies:
- "@formatjs/ecma402-abstract": "npm:2.2.3"
- "@formatjs/intl-localematcher": "npm:0.5.7"
+ "@formatjs/ecma402-abstract": "npm:2.3.2"
+ "@formatjs/intl-localematcher": "npm:0.5.10"
+ decimal.js: "npm:10"
tslib: "npm:2"
- checksum: 10c0/003d33af6f5d902517f230b7038e39b8336da3a84500fe5f4278fa5cac0c9a1b746de484f1c2bb2315026fd771491eafdc0aa59a809bb25189b63093efb8400d
+ checksum: 10c0/0ecb9da19084d7a15e636362c206c7ee14297ad365e3e63ea53c82c8442d02cd4dcf8a0da65af9b0f835b32f0e8c3d43407d6ee0a0d7974c3044c92574b49686
languageName: node
linkType: hard
-"@formatjs/intl@npm:2.10.13":
- version: 2.10.13
- resolution: "@formatjs/intl@npm:2.10.13"
+"@formatjs/intl@npm:3.1.0":
+ version: 3.1.0
+ resolution: "@formatjs/intl@npm:3.1.0"
dependencies:
- "@formatjs/ecma402-abstract": "npm:2.2.3"
- "@formatjs/fast-memoize": "npm:2.2.3"
- "@formatjs/icu-messageformat-parser": "npm:2.9.3"
- "@formatjs/intl-displaynames": "npm:6.8.3"
- "@formatjs/intl-listformat": "npm:7.7.3"
- intl-messageformat: "npm:10.7.5"
+ "@formatjs/ecma402-abstract": "npm:2.3.2"
+ "@formatjs/fast-memoize": "npm:2.2.6"
+ "@formatjs/icu-messageformat-parser": "npm:2.9.8"
+ intl-messageformat: "npm:10.7.11"
tslib: "npm:2"
peerDependencies:
- typescript: ^4.7 || 5
+ typescript: 5
peerDependenciesMeta:
typescript:
optional: true
- checksum: 10c0/14edcc45addc181c7a45845bc34cec5c73bb5544dcf8ed455eca916bbd3a5023c7204a8e8e289060545b85006933c6f297c33c4f04a8a4cb3890aa7baae5bfbf
+ checksum: 10c0/a073768fffc51696eb7bd25fe1f0afdda1a0e38db3e2dd9b2fc3138ea799f00ef522f3d3083626ad3acbf913593254cfd728a6c6b08ef4f167dd132626a7e9fc
languageName: node
linkType: hard
@@ -2429,11 +2420,11 @@ __metadata:
languageName: node
linkType: hard
-"@formatjs/ts-transformer@npm:3.13.22":
- version: 3.13.22
- resolution: "@formatjs/ts-transformer@npm:3.13.22"
+"@formatjs/ts-transformer@npm:3.13.27":
+ version: 3.13.27
+ resolution: "@formatjs/ts-transformer@npm:3.13.27"
dependencies:
- "@formatjs/icu-messageformat-parser": "npm:2.9.3"
+ "@formatjs/icu-messageformat-parser": "npm:2.9.8"
"@types/json-stable-stringify": "npm:1"
"@types/node": "npm:14 || 16 || 17 || 18 || 20 || 22"
chalk: "npm:4"
@@ -2445,7 +2436,7 @@ __metadata:
peerDependenciesMeta:
ts-jest:
optional: true
- checksum: 10c0/42503292248bcae728181fdf68e79eac4169c18064953beb9245097d2c58e5434ae7a7978e6ce2829dfd6eb4b4155f78fecef70ac6820626a338f231c66f60cb
+ checksum: 10c0/ab26ce081835ce2a1384172a6e24db42d48bc9f8b9b941c646fba2f01ce8370123480623d1fbc1e75f6ec90a232f8ff67b5243c5e9ad18311dc03d7061a4892b
languageName: node
linkType: hard
@@ -2942,7 +2933,7 @@ __metadata:
react-hotkeys: "npm:^1.1.4"
react-immutable-proptypes: "npm:^2.2.0"
react-immutable-pure-component: "npm:^2.2.2"
- react-intl: "npm:^6.4.2"
+ react-intl: "npm:^7.0.0"
react-motion: "npm:^0.5.2"
react-notification: "npm:^6.8.5"
react-overlays: "npm:^5.2.1"
@@ -3012,7 +3003,7 @@ __metadata:
eslint-define-config: "npm:^2.0.0"
express: "npm:^4.18.2"
ioredis: "npm:^5.3.2"
- jsdom: "npm:^25.0.0"
+ jsdom: "npm:^26.0.0"
pg: "npm:^8.5.0"
pg-connection-string: "npm:^2.6.0"
pino: "npm:^9.0.0"
@@ -3294,22 +3285,22 @@ __metadata:
linkType: hard
"@reduxjs/toolkit@npm:^2.0.1":
- version: 2.3.0
- resolution: "@reduxjs/toolkit@npm:2.3.0"
+ version: 2.5.0
+ resolution: "@reduxjs/toolkit@npm:2.5.0"
dependencies:
immer: "npm:^10.0.3"
redux: "npm:^5.0.1"
redux-thunk: "npm:^3.1.0"
reselect: "npm:^5.1.0"
peerDependencies:
- react: ^16.9.0 || ^17.0.0 || ^18
+ react: ^16.9.0 || ^17.0.0 || ^18 || ^19
react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0
peerDependenciesMeta:
react:
optional: true
react-redux:
optional: true
- checksum: 10c0/414e90b706331385a2122fc79e33f90c59a9caf9a59419f1bfd7f5e594bc8e4987902fd1bccbc53eb96d22c65ec2981ff5581f3d2df3ecd381a630f391edfc3e
+ checksum: 10c0/81748a5a6d2f52a14769b6ed25aea1e77cda81b1db6599c7c3a1d1605696c65c4469f55146c2b2a7a2f8ebafa5ecd4996aa8deecb37aebb5307217ec2fe384ac
languageName: node
linkType: hard
@@ -3833,12 +3824,12 @@ __metadata:
linkType: hard
"@types/hoist-non-react-statics@npm:3, @types/hoist-non-react-statics@npm:^3.3.1":
- version: 3.3.5
- resolution: "@types/hoist-non-react-statics@npm:3.3.5"
+ version: 3.3.6
+ resolution: "@types/hoist-non-react-statics@npm:3.3.6"
dependencies:
"@types/react": "npm:*"
hoist-non-react-statics: "npm:^3.3.0"
- checksum: 10c0/2a3b64bf3d9817d7830afa60ee314493c475fb09570a64e7737084cd482d2177ebdddf888ce837350bac51741278b077683facc9541f052d4bbe8487b4e3e618
+ checksum: 10c0/149a4c217d81f21f8a1e152160a59d5b99b6a9aa6d354385d5f5bc02760cbf1e170a8442ba92eb653befff44b0c5bc2234bb77ce33e0d11a65f779e8bab5c321
languageName: node
linkType: hard
@@ -4018,9 +4009,9 @@ __metadata:
linkType: hard
"@types/prop-types@npm:*, @types/prop-types@npm:^15.7.5":
- version: 15.7.13
- resolution: "@types/prop-types@npm:15.7.13"
- checksum: 10c0/1b20fc67281902c6743379960247bc161f3f0406ffc0df8e7058745a85ea1538612109db0406290512947f9632fe9e10e7337bf0ce6338a91d6c948df16a7c61
+ version: 15.7.14
+ resolution: "@types/prop-types@npm:15.7.14"
+ checksum: 10c0/1ec775160bfab90b67a782d735952158c7e702ca4502968aa82565bd8e452c2de8601c8dfe349733073c31179116cf7340710160d3836aa8a1ef76d1532893b1
languageName: node
linkType: hard
@@ -4060,11 +4051,11 @@ __metadata:
linkType: hard
"@types/react-dom@npm:^18.2.4":
- version: 18.3.1
- resolution: "@types/react-dom@npm:18.3.1"
- dependencies:
- "@types/react": "npm:*"
- checksum: 10c0/8b416551c60bb6bd8ec10e198c957910cfb271bc3922463040b0d57cf4739cdcd24b13224f8d68f10318926e1ec3cd69af0af79f0291b599a992f8c80d47f1eb
+ version: 18.3.5
+ resolution: "@types/react-dom@npm:18.3.5"
+ peerDependencies:
+ "@types/react": ^18.0.0
+ checksum: 10c0/b163d35a6b32a79f5782574a7aeb12a31a647e248792bf437e6d596e2676961c394c5e3c6e91d1ce44ae90441dbaf93158efb4f051c0d61e2612f1cb04ce4faa
languageName: node
linkType: hard
@@ -4127,20 +4118,20 @@ __metadata:
linkType: hard
"@types/react-swipeable-views@npm:^0.13.1":
- version: 0.13.5
- resolution: "@types/react-swipeable-views@npm:0.13.5"
+ version: 0.13.6
+ resolution: "@types/react-swipeable-views@npm:0.13.6"
dependencies:
"@types/react": "npm:*"
- checksum: 10c0/d1dcc78d862f37d30a43d79d915fdb388e05dce0b2ac07462ca4f1b00e0eef37cb41d75997f5685dec79bcce1ffee0dfbc744f20d5266dd3090658def5b4e193
+ checksum: 10c0/a26879146748417234bb7f44c5a71e6bab2b76c0b34c72f0493c18403487a5d77021510e8665bd8bd22786904fbbd90d6db55c8dd2bf983c32421139de851c94
languageName: node
linkType: hard
"@types/react-test-renderer@npm:^18.0.0":
- version: 18.3.0
- resolution: "@types/react-test-renderer@npm:18.3.0"
+ version: 18.3.1
+ resolution: "@types/react-test-renderer@npm:18.3.1"
dependencies:
- "@types/react": "npm:*"
- checksum: 10c0/3c9748be52e8e659e7adf91dea6939486463264e6f633bf21c4cb116de18af7bef0595568a1e588160420b2f65289473075dda1cb417c2875df8cf7a09f5d913
+ "@types/react": "npm:^18"
+ checksum: 10c0/9fc8467ff1a3f14be6cc3498a75fc788d2c92c0fffa7bf21269ed5d9d82db9195bf2178ddc42ea16a0836995c1b77601c6be8abb27bd1864668c418c6d0e5a3b
languageName: node
linkType: hard
@@ -4162,13 +4153,13 @@ __metadata:
languageName: node
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.3.12
- resolution: "@types/react@npm:18.3.12"
+"@types/react@npm:^18.2.7":
+ version: 18.3.18
+ resolution: "@types/react@npm:18.3.18"
dependencies:
"@types/prop-types": "npm:*"
csstype: "npm:^3.0.2"
- checksum: 10c0/8bae8d9a41619804561574792e29112b413044eb0d53746dde2b9720c1f9a59f71c895bbd7987cd8ce9500b00786e53bc032dced38cddf42910458e145675290
+ checksum: 10c0/8fb2b00672072135d0858dc9db07873ea107cc238b6228aaa2a9afd1ef7a64a7074078250db38afbeb19064be8ea6af5eac32d404efdd5f45e093cc4829d87f8
languageName: node
linkType: hard
@@ -4743,12 +4734,10 @@ __metadata:
languageName: node
linkType: hard
-"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0":
- version: 7.1.0
- resolution: "agent-base@npm:7.1.0"
- dependencies:
- debug: "npm:^4.3.4"
- checksum: 10c0/fc974ab57ffdd8421a2bc339644d312a9cca320c20c3393c9d8b1fd91731b9bbabdb985df5fc860f5b79d81c3e350daa3fcb31c5c07c0bb385aafc817df004ce
+"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.2":
+ version: 7.1.3
+ resolution: "agent-base@npm:7.1.3"
+ checksum: 10c0/6192b580c5b1d8fb399b9c62bf8343d76654c2dd62afcb9a52b2cf44a8b6ace1e3b704d3fe3547d91555c857d3df02603341ff2cb961b9cfe2b12f9f3c38ee11
languageName: node
linkType: hard
@@ -5351,21 +5340,21 @@ __metadata:
linkType: hard
"babel-plugin-formatjs@npm:^10.5.1":
- version: 10.5.24
- resolution: "babel-plugin-formatjs@npm:10.5.24"
+ version: 10.5.30
+ resolution: "babel-plugin-formatjs@npm:10.5.30"
dependencies:
"@babel/core": "npm:^7.25.0"
"@babel/helper-plugin-utils": "npm:^7.25.0"
"@babel/plugin-syntax-jsx": "npm:^7.25.0"
"@babel/traverse": "npm:^7.25.0"
"@babel/types": "npm:^7.25.0"
- "@formatjs/icu-messageformat-parser": "npm:2.9.3"
- "@formatjs/ts-transformer": "npm:3.13.22"
+ "@formatjs/icu-messageformat-parser": "npm:2.9.8"
+ "@formatjs/ts-transformer": "npm:3.13.27"
"@types/babel__core": "npm:^7.20.5"
"@types/babel__helper-plugin-utils": "npm:^7.10.3"
"@types/babel__traverse": "npm:^7.20.6"
tslib: "npm:2"
- checksum: 10c0/a99c92e62edb30e0b6a5bf1115811eb18336b851109f8c096b5a9aa2be3eb72299eea3a8cb706e03705eb79edfa5a62d69bb52d80a375c1d5a1c963e3d00c40e
+ checksum: 10c0/cf9f17b71da9e95a402e0722cfbf4a549c984a8bb536f6b46dc187fa4b69dd2e248e6a825ea95d5ddfa2a9b09b3eb399cefa2dce1dcf52fd6e661adb99a9d3fa
languageName: node
linkType: hard
@@ -6544,9 +6533,9 @@ __metadata:
linkType: hard
"core-js@npm:^3.30.2":
- version: 3.39.0
- resolution: "core-js@npm:3.39.0"
- checksum: 10c0/f7602069b6afb2e3298eec612a5c1e0c3e6a458930fbfc7a4c5f9ac03426507f49ce395eecdd2d9bae9024f820e44582b67ffe16f2272395af26964f174eeb6b
+ version: 3.40.0
+ resolution: "core-js@npm:3.40.0"
+ checksum: 10c0/db7946ada881e845d8b157061945b1187618fa45cf162f392a151e8a497962aed2da688c982eaa1d444c864be97a70f8be4d73385294b515d224dd164d19f1d4
languageName: node
linkType: hard
@@ -7003,12 +6992,13 @@ __metadata:
languageName: node
linkType: hard
-"cssstyle@npm:^4.1.0":
- version: 4.1.0
- resolution: "cssstyle@npm:4.1.0"
+"cssstyle@npm:^4.2.1":
+ version: 4.2.1
+ resolution: "cssstyle@npm:4.2.1"
dependencies:
- rrweb-cssom: "npm:^0.7.1"
- checksum: 10c0/05c6597e5d3e0ec6b15221f2c0ce9a0443a46cc50a6089a3ba9ee1ac27f83ff86a445a8f95435137dadd859f091fc61b6d342abaf396d3c910471b5b33cfcbfa
+ "@asamuzakjp/css-color": "npm:^2.8.2"
+ rrweb-cssom: "npm:^0.8.0"
+ checksum: 10c0/02ba8c47c0caaab57acadacb3eb6c0f5f009000f55d61f6563670e07d389b26edefeed497e6c1847fcd2e6bbe0b6974c2d4291f97fa0c6ec6add13a7fa926d84
languageName: node
linkType: hard
@@ -7131,7 +7121,7 @@ __metadata:
languageName: node
linkType: hard
-"decimal.js@npm:^10.4.2, decimal.js@npm:^10.4.3":
+"decimal.js@npm:10, decimal.js@npm:^10.4.2, decimal.js@npm:^10.4.3":
version: 10.4.3
resolution: "decimal.js@npm:10.4.3"
checksum: 10c0/6d60206689ff0911f0ce968d40f163304a6c1bc739927758e6efc7921cfa630130388966f16bf6ef6b838cb33679fbe8e7a78a2f3c478afce841fd55ac8fb8ee
@@ -7719,7 +7709,7 @@ __metadata:
languageName: node
linkType: hard
-"entities@npm:^4.2.0, entities@npm:^4.4.0":
+"entities@npm:^4.2.0, entities@npm:^4.5.0":
version: 4.5.0
resolution: "entities@npm:4.5.0"
checksum: 10c0/5b039739f7621f5d1ad996715e53d964035f75ad3b9a4d38c6b3804bb226e282ffeae2443624d8fdd9c47d8e926ae9ac009c54671243f0c3294c26af7cc85250
@@ -8890,14 +8880,14 @@ __metadata:
languageName: node
linkType: hard
-"form-data@npm:^4.0.0":
- version: 4.0.0
- resolution: "form-data@npm:4.0.0"
+"form-data@npm:^4.0.0, form-data@npm:^4.0.1":
+ version: 4.0.1
+ resolution: "form-data@npm:4.0.1"
dependencies:
asynckit: "npm:^0.4.0"
combined-stream: "npm:^1.0.8"
mime-types: "npm:^2.1.12"
- checksum: 10c0/cb6f3ac49180be03ff07ba3ff125f9eba2ff0b277fb33c7fc47569fc5e616882c5b1c69b9904c4c4187e97dd0419dd03b134174756f296dec62041e6527e2c6e
+ checksum: 10c0/bb102d570be8592c23f4ea72d7df9daa50c7792eb0cf1c5d7e506c1706e7426a4e4ae48a35b109e91c85f1c0ec63774a21ae252b66f4eb981cb8efef7d0463c8
languageName: node
linkType: hard
@@ -9677,13 +9667,13 @@ __metadata:
languageName: node
linkType: hard
-"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.5":
- version: 7.0.5
- resolution: "https-proxy-agent@npm:7.0.5"
+"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.6":
+ version: 7.0.6
+ resolution: "https-proxy-agent@npm:7.0.6"
dependencies:
- agent-base: "npm:^7.0.2"
+ agent-base: "npm:^7.1.2"
debug: "npm:4"
- checksum: 10c0/2490e3acec397abeb88807db52cac59102d5ed758feee6df6112ab3ccd8325e8a1ce8bce6f4b66e5470eca102d31e425ace904242e4fa28dbe0c59c4bafa7b2c
+ checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac
languageName: node
linkType: hard
@@ -9942,15 +9932,15 @@ __metadata:
languageName: node
linkType: hard
-"intl-messageformat@npm:10.7.5, intl-messageformat@npm:^10.3.5":
- version: 10.7.5
- resolution: "intl-messageformat@npm:10.7.5"
+"intl-messageformat@npm:10.7.11, intl-messageformat@npm:^10.3.5":
+ version: 10.7.11
+ resolution: "intl-messageformat@npm:10.7.11"
dependencies:
- "@formatjs/ecma402-abstract": "npm:2.2.3"
- "@formatjs/fast-memoize": "npm:2.2.3"
- "@formatjs/icu-messageformat-parser": "npm:2.9.3"
+ "@formatjs/ecma402-abstract": "npm:2.3.2"
+ "@formatjs/fast-memoize": "npm:2.2.6"
+ "@formatjs/icu-messageformat-parser": "npm:2.9.8"
tslib: "npm:2"
- checksum: 10c0/1aa173a8c16ace50520af3de7d3f0ce9bafda90d47b6d674eb88cc47c12c3460d4d53c97ca412fae1141b00abb8ff2ba313250997a040837f01a25379165c949
+ checksum: 10c0/7ccd972277cc6798038af876c830203084db6552becfa99c3706541fd67838552013f57f8ed0ed3aed03d4fba436591a83a25f913365d66ad04ee9332eee7b73
languageName: node
linkType: hard
@@ -11276,21 +11266,21 @@ __metadata:
languageName: node
linkType: hard
-"jsdom@npm:^25.0.0":
- version: 25.0.1
- resolution: "jsdom@npm:25.0.1"
+"jsdom@npm:^26.0.0":
+ version: 26.0.0
+ resolution: "jsdom@npm:26.0.0"
dependencies:
- cssstyle: "npm:^4.1.0"
+ cssstyle: "npm:^4.2.1"
data-urls: "npm:^5.0.0"
decimal.js: "npm:^10.4.3"
- form-data: "npm:^4.0.0"
+ form-data: "npm:^4.0.1"
html-encoding-sniffer: "npm:^4.0.0"
http-proxy-agent: "npm:^7.0.2"
- https-proxy-agent: "npm:^7.0.5"
+ https-proxy-agent: "npm:^7.0.6"
is-potential-custom-element-name: "npm:^1.0.1"
- nwsapi: "npm:^2.2.12"
- parse5: "npm:^7.1.2"
- rrweb-cssom: "npm:^0.7.1"
+ nwsapi: "npm:^2.2.16"
+ parse5: "npm:^7.2.1"
+ rrweb-cssom: "npm:^0.8.0"
saxes: "npm:^6.0.0"
symbol-tree: "npm:^3.2.4"
tough-cookie: "npm:^5.0.0"
@@ -11298,15 +11288,15 @@ __metadata:
webidl-conversions: "npm:^7.0.0"
whatwg-encoding: "npm:^3.1.1"
whatwg-mimetype: "npm:^4.0.0"
- whatwg-url: "npm:^14.0.0"
+ whatwg-url: "npm:^14.1.0"
ws: "npm:^8.18.0"
xml-name-validator: "npm:^5.0.0"
peerDependencies:
- canvas: ^2.11.2
+ canvas: ^3.0.0
peerDependenciesMeta:
canvas:
optional: true
- checksum: 10c0/6bda32a6dfe4e37a30568bf51136bdb3ba9c0b72aadd6356280404275a34c9e097c8c25b5eb3c742e602623741e172da977ff456684befd77c9042ed9bf8c2b4
+ checksum: 10c0/e48725ba4027edcfc9bca5799eaec72c6561ecffe3675a8ff87fe9c3541ca4ff9f82b4eff5b3d9c527302da0d859b2f60e9364347a5d42b77f5c76c436c569dc
languageName: node
linkType: hard
@@ -11773,6 +11763,13 @@ __metadata:
languageName: node
linkType: hard
+"lru-cache@npm:^11.0.2":
+ version: 11.0.2
+ resolution: "lru-cache@npm:11.0.2"
+ checksum: 10c0/c993b8e06ead0b24b969c1dbb5b301716aed66e320e9014a80012f5febe280b438f28ff50046b2c55ff404e889351ccb332ff91f8dd175a21f5eae80e3fb155f
+ languageName: node
+ linkType: hard
+
"lru-cache@npm:^5.1.1":
version: 5.1.1
resolution: "lru-cache@npm:5.1.1"
@@ -12600,10 +12597,10 @@ __metadata:
languageName: node
linkType: hard
-"nwsapi@npm:^2.2.12, nwsapi@npm:^2.2.2":
- version: 2.2.12
- resolution: "nwsapi@npm:2.2.12"
- checksum: 10c0/95e9623d63df111405503df8c5d800e26f71675d319e2c9c70cddfa31e5ace1d3f8b6d98d354544fc156a1506d920ec291e303fab761e4f99296868e199a466e
+"nwsapi@npm:^2.2.16, nwsapi@npm:^2.2.2":
+ version: 2.2.16
+ resolution: "nwsapi@npm:2.2.16"
+ checksum: 10c0/0aa0637f4d51043d0183d994e08336bae996b03b42984381bf09ebdf3ff4909c018eda6b2a8aba0a08f3ea8303db8a0dad0608b38dc0bff15fd87017286ae21a
languageName: node
linkType: hard
@@ -13000,12 +12997,12 @@ __metadata:
languageName: node
linkType: hard
-"parse5@npm:^7.0.0, parse5@npm:^7.1.1, parse5@npm:^7.1.2":
- version: 7.1.2
- resolution: "parse5@npm:7.1.2"
+"parse5@npm:^7.0.0, parse5@npm:^7.1.1, parse5@npm:^7.2.1":
+ version: 7.2.1
+ resolution: "parse5@npm:7.2.1"
dependencies:
- entities: "npm:^4.4.0"
- checksum: 10c0/297d7af8224f4b5cb7f6617ecdae98eeaed7f8cbd78956c42785e230505d5a4f07cef352af10d3006fa5c1544b76b57784d3a22d861ae071bbc460c649482bf4
+ entities: "npm:^4.5.0"
+ checksum: 10c0/829d37a0c709215a887e410a7118d754f8e1afd7edb529db95bc7bbf8045fb0266a7b67801331d8e8d9d073ea75793624ec27ce9ff3b96862c3b9008f4d68e80
languageName: node
linkType: hard
@@ -14685,27 +14682,25 @@ __metadata:
languageName: node
linkType: hard
-"react-intl@npm:^6.4.2":
- version: 6.8.6
- resolution: "react-intl@npm:6.8.6"
+"react-intl@npm:^7.0.0":
+ version: 7.1.0
+ resolution: "react-intl@npm:7.1.0"
dependencies:
- "@formatjs/ecma402-abstract": "npm:2.2.3"
- "@formatjs/icu-messageformat-parser": "npm:2.9.3"
- "@formatjs/intl": "npm:2.10.13"
- "@formatjs/intl-displaynames": "npm:6.8.3"
- "@formatjs/intl-listformat": "npm:7.7.3"
+ "@formatjs/ecma402-abstract": "npm:2.3.2"
+ "@formatjs/icu-messageformat-parser": "npm:2.9.8"
+ "@formatjs/intl": "npm:3.1.0"
"@types/hoist-non-react-statics": "npm:3"
"@types/react": "npm:16 || 17 || 18"
hoist-non-react-statics: "npm:3"
- intl-messageformat: "npm:10.7.5"
+ intl-messageformat: "npm:10.7.11"
tslib: "npm:2"
peerDependencies:
react: ^16.6.0 || 17 || 18
- typescript: ^4.7 || 5
+ typescript: 5
peerDependenciesMeta:
typescript:
optional: true
- checksum: 10c0/ec88cc2b1d0edf089f04c8061ffda730840fb3317177d0dc1a6df208245ec278f52b4ca8546ff9511b0b28ff2d89863c5837a274d33731d4c8f75a3b3baafbe2
+ checksum: 10c0/9d69e316a5f5c6d31fa77f136b595079db2f75f63398cf8253d407878246dd5bcf0cc2eb4d7d4aa0646530ee58b16ce9a8c3876a5c2f0dc38fdda7e4f8c07615
languageName: node
linkType: hard
@@ -14971,15 +14966,15 @@ __metadata:
linkType: hard
"react-textarea-autosize@npm:^8.4.1":
- version: 8.5.6
- resolution: "react-textarea-autosize@npm:8.5.6"
+ version: 8.5.7
+ resolution: "react-textarea-autosize@npm:8.5.7"
dependencies:
"@babel/runtime": "npm:^7.20.13"
use-composed-ref: "npm:^1.3.0"
use-latest: "npm:^1.2.1"
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
- checksum: 10c0/652d290d316c55a253507ecf65ca27f2162801dace10c715f2241203e81d82e9de6d282095b758b26c6bc9e1af9ca552cab5c3a361b230e5fcf25bec31e1bd25
+ checksum: 10c0/ff004797ea28faca442460c42b30042d4c34a140f324eeeddee74508688dbc0f98966d21282c945630655006ad28a87edbcb59e6da7f9e762f4f3042c72f9f24
languageName: node
linkType: hard
@@ -15550,10 +15545,10 @@ __metadata:
languageName: node
linkType: hard
-"rrweb-cssom@npm:^0.7.1":
- version: 0.7.1
- resolution: "rrweb-cssom@npm:0.7.1"
- checksum: 10c0/127b8ca6c8aac45e2755abbae6138d4a813b1bedc2caabf79466ae83ab3cfc84b5bfab513b7033f0aa4561c7753edf787d0dd01163ceacdee2e8eb1b6bf7237e
+"rrweb-cssom@npm:^0.8.0":
+ version: 0.8.0
+ resolution: "rrweb-cssom@npm:0.8.0"
+ checksum: 10c0/56f2bfd56733adb92c0b56e274c43f864b8dd48784d6fe946ef5ff8d438234015e59ad837fc2ad54714b6421384141c1add4eb569e72054e350d1f8a50b8ac7b
languageName: node
linkType: hard
@@ -17872,11 +17867,11 @@ __metadata:
linkType: hard
"uuid@npm:^11.0.0":
- version: 11.0.4
- resolution: "uuid@npm:11.0.4"
+ version: 11.0.5
+ resolution: "uuid@npm:11.0.5"
bin:
uuid: dist/esm/bin/uuid
- checksum: 10c0/3c13591c4dedaa3741f925e284df5974e3d6e0b1cb0f6f75f98c36f9c01d2a414350364fd067613ef600a21c6973dab0506530d4f499ff878f32a06f84569ead
+ checksum: 10c0/6f59f0c605e02c14515401084ca124b9cb462b4dcac866916a49862bcf831874508a308588c23a7718269226ad11a92da29b39d761ad2b86e736623e3a33b6e7
languageName: node
linkType: hard
@@ -18294,13 +18289,13 @@ __metadata:
languageName: node
linkType: hard
-"whatwg-url@npm:^14.0.0":
- version: 14.0.0
- resolution: "whatwg-url@npm:14.0.0"
+"whatwg-url@npm:^14.0.0, whatwg-url@npm:^14.1.0":
+ version: 14.1.0
+ resolution: "whatwg-url@npm:14.1.0"
dependencies:
tr46: "npm:^5.0.0"
webidl-conversions: "npm:^7.0.0"
- checksum: 10c0/ac32e9ba9d08744605519bbe9e1371174d36229689ecc099157b6ba102d4251a95e81d81f3d80271eb8da182eccfa65653f07f0ab43ea66a6934e643fd091ba9
+ checksum: 10c0/f00104f1c67ce086ba8ffedab529cbbd9aefd8c0a6555320026de7aeff31f91c38680f95818b140a7c9cc657cde3781e567835dda552ddb1e2b8faaba0ac3cb6
languageName: node
linkType: hard