mirror of
https://github.com/funamitech/mastodon
synced 2024-11-27 06:18:53 +09:00
Merge commit '4a7395d989e40c3bd4ef18173aa5ea850c8ddcdd' into glitch-soc/merge-upstream
Conflicts: - `README.md`: Upstream modified its README, we have a completely different one. Kept our README file.
This commit is contained in:
commit
6e56f95285
@ -50,6 +50,10 @@ You can contribute in the following ways:
|
||||
|
||||
If your contributions are accepted into Mastodon, you can request to be paid through [our OpenCollective](https://opencollective.com/mastodon).
|
||||
|
||||
## API Changes and Additions
|
||||
|
||||
Please note that any changes or additions made to the API should have an accompanying pull request on [our documentation repository](https://github.com/mastodon/documentation).
|
||||
|
||||
## Bug reports
|
||||
|
||||
Bug reports and feature suggestions must use descriptive and concise titles and be submitted to [GitHub Issues](https://github.com/mastodon/mastodon/issues). Please use the search function to make sure that you are not submitting duplicates, and that a similar report or request has not already been resolved or rejected.
|
||||
|
12
Gemfile.lock
12
Gemfile.lock
@ -118,7 +118,7 @@ GEM
|
||||
minitest (>= 5.1)
|
||||
mutex_m
|
||||
tzinfo (~> 2.0)
|
||||
addressable (2.8.5)
|
||||
addressable (2.8.6)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
aes_key_wrap (1.1.0)
|
||||
android_key_attestation (0.3.0)
|
||||
@ -220,9 +220,9 @@ GEM
|
||||
database_cleaner-core (~> 2.0.0)
|
||||
database_cleaner-core (2.0.1)
|
||||
date (3.3.4)
|
||||
debug (1.8.0)
|
||||
irb (>= 1.5.0)
|
||||
reline (>= 0.3.1)
|
||||
debug (1.9.0)
|
||||
irb (~> 1.10)
|
||||
reline (>= 0.3.8)
|
||||
debug_inspector (1.1.0)
|
||||
devise (4.9.3)
|
||||
bcrypt (~> 3.0)
|
||||
@ -484,8 +484,8 @@ GEM
|
||||
nokogiri (1.15.5)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
oj (3.16.2)
|
||||
bigdecimal (~> 3.1)
|
||||
oj (3.16.3)
|
||||
bigdecimal (>= 3.0)
|
||||
omniauth (2.1.1)
|
||||
hashie (>= 3.4.6)
|
||||
rack (>= 2.2.3)
|
||||
|
@ -114,7 +114,7 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
def fa_icon(icon, attributes = {})
|
||||
class_names = attributes[:class]&.split(' ') || []
|
||||
class_names = attributes[:class]&.split || []
|
||||
class_names << 'fa'
|
||||
class_names += icon.split.map { |cl| "fa-#{cl}" }
|
||||
|
||||
|
@ -18,6 +18,6 @@ export const notificationsUpdate = createAction(
|
||||
playSound: boolean;
|
||||
}) => ({
|
||||
payload: args,
|
||||
meta: { playSound: playSound ? { sound: 'boop' } : undefined },
|
||||
meta: { sound: playSound ? 'boop' : undefined },
|
||||
}),
|
||||
);
|
||||
|
@ -21,6 +21,7 @@
|
||||
"account.blocked": "Blocked",
|
||||
"account.browse_more_on_origin_server": "Browse more on the original profile",
|
||||
"account.cancel_follow_request": "Cancel follow",
|
||||
"account.copy": "Copy link to profile",
|
||||
"account.direct": "Privately mention @{name}",
|
||||
"account.disable_notifications": "Stop notifying me when @{name} posts",
|
||||
"account.domain_blocked": "Domain blocked",
|
||||
@ -191,6 +192,7 @@
|
||||
"conversation.mark_as_read": "Mark as read",
|
||||
"conversation.open": "View conversation",
|
||||
"conversation.with": "With {names}",
|
||||
"copy_icon_button.copied": "Copied to clipboard",
|
||||
"copypaste.copied": "Copied",
|
||||
"copypaste.copy_to_clipboard": "Copy to clipboard",
|
||||
"directory.federated": "From known fediverse",
|
||||
@ -222,6 +224,7 @@
|
||||
"emoji_button.search_results": "Search results",
|
||||
"emoji_button.symbols": "Symbols",
|
||||
"emoji_button.travel": "Travel & Places",
|
||||
"empty_column.account_hides_collections": "This user has chosen to not make this information available",
|
||||
"empty_column.account_suspended": "Account suspended",
|
||||
"empty_column.account_timeline": "No posts here!",
|
||||
"empty_column.account_unavailable": "Profile unavailable",
|
||||
@ -478,6 +481,8 @@
|
||||
"onboarding.follows.empty": "Unfortunately, no results can be shown right now. You can try using search or browsing the explore page to find people to follow, or try again later.",
|
||||
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
|
||||
"onboarding.follows.title": "Personalize your home feed",
|
||||
"onboarding.profile.discoverable": "Make my profile discoverable",
|
||||
"onboarding.profile.discoverable_hint": "When you opt in to discoverability on Mastodon, your posts may appear in search results and trending, and your profile may be suggested to people with similar interests to you.",
|
||||
"onboarding.profile.display_name": "Display name",
|
||||
"onboarding.profile.display_name_hint": "Your full name or your fun name…",
|
||||
"onboarding.profile.lead": "You can always complete this later in the settings, where even more customisation options are available.",
|
||||
@ -530,6 +535,7 @@
|
||||
"privacy.unlisted.short": "Unlisted",
|
||||
"privacy_policy.last_updated": "Last updated {date}",
|
||||
"privacy_policy.title": "Privacy Policy",
|
||||
"recommended": "Recommended",
|
||||
"refresh": "Refresh",
|
||||
"regeneration_indicator.label": "Loading…",
|
||||
"regeneration_indicator.sublabel": "Your home feed is being prepared!",
|
||||
@ -600,6 +606,7 @@
|
||||
"search.quick_action.status_search": "Posts matching {x}",
|
||||
"search.search_or_paste": "Search or paste URL",
|
||||
"search_popout.full_text_search_disabled_message": "Unavailable on {domain}.",
|
||||
"search_popout.full_text_search_logged_out_message": "Only available when logged in.",
|
||||
"search_popout.language_code": "ISO language code",
|
||||
"search_popout.options": "Search options",
|
||||
"search_popout.quick_actions": "Quick actions",
|
||||
|
@ -21,6 +21,7 @@
|
||||
"account.blocked": "Blokita",
|
||||
"account.browse_more_on_origin_server": "Foliumi pli ĉe la originala profilo",
|
||||
"account.cancel_follow_request": "Nuligi peton por sekvado",
|
||||
"account.copy": "Kopii ligilon al profilo",
|
||||
"account.direct": "Private mencii @{name}",
|
||||
"account.disable_notifications": "Ne plu sciigi min, kiam @{name} mesaĝas",
|
||||
"account.domain_blocked": "Domajno blokita",
|
||||
@ -191,6 +192,7 @@
|
||||
"conversation.mark_as_read": "Marki legita",
|
||||
"conversation.open": "Vidi konversacion",
|
||||
"conversation.with": "Kun {names}",
|
||||
"copy_icon_button.copied": "Kopiis al kliptabulo",
|
||||
"copypaste.copied": "Kopiita",
|
||||
"copypaste.copy_to_clipboard": "Kopii al dosierujo",
|
||||
"directory.federated": "El konata fediverso",
|
||||
@ -202,7 +204,9 @@
|
||||
"dismissable_banner.community_timeline": "Jen la plej novaj publikaj afiŝoj de uzantoj, kies kontojn gastigas {domain}.",
|
||||
"dismissable_banner.dismiss": "Eksigi",
|
||||
"dismissable_banner.explore_links": "Tiuj novaĵoj estas aktuale priparolataj de uzantoj en tiu ĉi kaj aliaj serviloj, sur la malcentrigita reto.",
|
||||
"dismissable_banner.explore_statuses": "Ĉi tioj estas afiŝoj de socia reto kiu populariĝas hodiau.",
|
||||
"dismissable_banner.explore_tags": "Ĉi tiuj kradvostoj populariĝas en ĉi tiu kaj aliaj serviloj en la malcentraliza reto nun.",
|
||||
"dismissable_banner.public_timeline": "Ĉi tioj estas plej lastaj publikaj afiŝoj de personoj ĉe socia reto kiu personoj ĉe {domain} sekvas.",
|
||||
"embed.instructions": "Enkorpigu ĉi tiun afiŝon en vian retejon per kopio de la suba kodo.",
|
||||
"embed.preview": "Ĝi aperos tiel:",
|
||||
"emoji_button.activity": "Agadoj",
|
||||
@ -220,6 +224,7 @@
|
||||
"emoji_button.search_results": "Serĉaj rezultoj",
|
||||
"emoji_button.symbols": "Simboloj",
|
||||
"emoji_button.travel": "Vojaĝoj kaj lokoj",
|
||||
"empty_column.account_hides_collections": "Ĉi tiu uzanto elektis ne disponebligi ĉi tiu informon",
|
||||
"empty_column.account_suspended": "Konto suspendita",
|
||||
"empty_column.account_timeline": "Neniu afiŝo ĉi tie!",
|
||||
"empty_column.account_unavailable": "Profilo ne disponebla",
|
||||
@ -229,6 +234,8 @@
|
||||
"empty_column.direct": "Vi ankoraŭ ne havas privatan mencion. Kiam vi sendos aŭ ricevos iun, tiu aperos ĉi tie.",
|
||||
"empty_column.domain_blocks": "Ankoraŭ neniu domajno estas blokita.",
|
||||
"empty_column.explore_statuses": "Nenio tendencas nun. Rekontrolu poste!",
|
||||
"empty_column.favourited_statuses": "Vi ankoraŭ ne havas stelumitan afiŝon.",
|
||||
"empty_column.favourites": "Ankoraŭ neniu stelumis tiun afiŝon.",
|
||||
"empty_column.follow_requests": "Vi ne ankoraŭ havas iun peton de sekvado. Kiam vi ricevos unu, ĝi aperos ĉi tie.",
|
||||
"empty_column.followed_tags": "Vi ankoraŭ ne sekvas iujn kradvortojn. Kiam vi faras, ili aperos ĉi tie.",
|
||||
"empty_column.hashtag": "Ankoraŭ estas nenio per ĉi tiu kradvorto.",
|
||||
@ -292,19 +299,36 @@
|
||||
"hashtag.column_settings.tag_mode.any": "Iu ajn",
|
||||
"hashtag.column_settings.tag_mode.none": "Neniu",
|
||||
"hashtag.column_settings.tag_toggle": "Aldoni pliajn etikedojn por ĉi tiu kolumno",
|
||||
"hashtag.counter_by_accounts": "{count, plural,one {{counter} partoprenanto} other {{counter} partoprenantoj}}",
|
||||
"hashtag.counter_by_uses": "{count, plural,one {{counter} afiŝo} other {{counter} afiŝoj}}",
|
||||
"hashtag.counter_by_uses_today": "{count, plural,one {{counter} afiŝo} other {{counter} afiŝoj}} hodiau",
|
||||
"hashtag.follow": "Sekvi la kradvorton",
|
||||
"hashtag.unfollow": "Ne plu sekvi la kradvorton",
|
||||
"hashtags.and_other": "…kaj {count, plural,other {# pli}}",
|
||||
"home.actions.go_to_explore": "Vidi kio populariĝas",
|
||||
"home.actions.go_to_suggestions": "Trovi homojn por sekvi",
|
||||
"home.column_settings.basic": "Bazaj agordoj",
|
||||
"home.column_settings.show_reblogs": "Montri diskonigojn",
|
||||
"home.column_settings.show_replies": "Montri respondojn",
|
||||
"home.explore_prompt.body": "Via hejmafiŝaro havos miksitajn afiŝojn de kradvortoj kiujn vi elektis sekvi, personoj kiujn vi elektis sekvi, kaj afiŝoj kiujn ili suprenigis.",
|
||||
"home.explore_prompt.title": "Ĉi tio estas via hejma paĝo en Mastodon.",
|
||||
"home.hide_announcements": "Kaŝi la anoncojn",
|
||||
"home.pending_critical_update.body": "Ĝisdatigu vian servilon de Mastodon kiel eble plej baldau!",
|
||||
"home.pending_critical_update.link": "Vidi ĝisdatigojn",
|
||||
"home.pending_critical_update.title": "Kritika sekurĝisdatigo estas disponebla!",
|
||||
"home.show_announcements": "Montri anoncojn",
|
||||
"interaction_modal.description.favourite": "Per konto ĉe Mastodon, vi povas stelumiti ĉi tiun afiŝon por sciigi la afiŝanton ke vi aprezigas ŝin kaj konservas por la estonteco.",
|
||||
"interaction_modal.description.follow": "Kun konto ĉe Mastodon, vi povos sekvi {name} por vidi ties mesaĝojn en via hejmo.",
|
||||
"interaction_modal.description.reblog": "Kun konto ĉe Mastodon, vi povas diskonigi ĉi tiun afiŝon, por ke viaj propraj sekvantoj vidu ĝin.",
|
||||
"interaction_modal.description.reply": "Kun konto ĉe Mastodon, vi povos respondi al ĉi tiu mesaĝo.",
|
||||
"interaction_modal.login.action": "Prenu min hejmen",
|
||||
"interaction_modal.login.prompt": "Domajno de via hejma servilo, ekz. mastodon.social",
|
||||
"interaction_modal.no_account_yet": "Ĉu ne estas ĉe Mastodon?",
|
||||
"interaction_modal.on_another_server": "En alia servilo",
|
||||
"interaction_modal.on_this_server": "En ĉi tiu servilo",
|
||||
"interaction_modal.sign_in": "Vi ne estas ensalutita al ĉi tiu servilo.",
|
||||
"interaction_modal.sign_in_hint": "Gvideto: Tio estas la retejo kie vi registris. Vi ankau povas tajpi vian plenan uzantonomon!",
|
||||
"interaction_modal.title.favourite": "Stelumi la afiŝon de {name}",
|
||||
"interaction_modal.title.follow": "Sekvi {name}",
|
||||
"interaction_modal.title.reblog": "Akceli la afiŝon de {name}",
|
||||
"interaction_modal.title.reply": "Respondi al la afiŝo de {name}",
|
||||
@ -320,6 +344,8 @@
|
||||
"keyboard_shortcuts.direct": "por malfermi la kolumnon pri privataj mencioj",
|
||||
"keyboard_shortcuts.down": "iri suben en la listo",
|
||||
"keyboard_shortcuts.enter": "malfermi mesaĝon",
|
||||
"keyboard_shortcuts.favourite": "Stelumi afiŝon",
|
||||
"keyboard_shortcuts.favourites": "Malfermi la liston de la stelumoj",
|
||||
"keyboard_shortcuts.federated": "Malfermi la frataran templinion",
|
||||
"keyboard_shortcuts.heading": "Klavaraj mallongigoj",
|
||||
"keyboard_shortcuts.home": "Malfermi la hejman templinion",
|
||||
@ -366,6 +392,7 @@
|
||||
"lists.search": "Serĉi inter la homoj, kiujn vi sekvas",
|
||||
"lists.subheading": "Viaj listoj",
|
||||
"load_pending": "{count,plural, one {# nova elemento} other {# novaj elementoj}}",
|
||||
"loading_indicator.label": "Ŝargado…",
|
||||
"media_gallery.toggle_visible": "{number, plural, one {Kaŝi la bildon} other {Kaŝi la bildojn}}",
|
||||
"moved_to_account_banner.text": "Via konto {disabledAccount} estas malvalidigita ĉar vi movis ĝin al {movedToAccount}.",
|
||||
"mute_modal.duration": "Daŭro",
|
||||
@ -382,6 +409,7 @@
|
||||
"navigation_bar.domain_blocks": "Blokitaj domajnoj",
|
||||
"navigation_bar.edit_profile": "Redakti profilon",
|
||||
"navigation_bar.explore": "Esplori",
|
||||
"navigation_bar.favourites": "Stelumoj",
|
||||
"navigation_bar.filters": "Silentigitaj vortoj",
|
||||
"navigation_bar.follow_requests": "Petoj de sekvado",
|
||||
"navigation_bar.followed_tags": "Sekvataj kradvortoj",
|
||||
@ -389,6 +417,7 @@
|
||||
"navigation_bar.lists": "Listoj",
|
||||
"navigation_bar.logout": "Adiaŭi",
|
||||
"navigation_bar.mutes": "Silentigitaj uzantoj",
|
||||
"navigation_bar.opened_in_classic_interface": "Afiŝoj, kontoj, kaj aliaj specifaj paĝoj kiuj estas malfermititaj defaulta en la klasika reta interfaco.",
|
||||
"navigation_bar.personal": "Persone",
|
||||
"navigation_bar.pins": "Alpinglitaj mesaĝoj",
|
||||
"navigation_bar.preferences": "Preferoj",
|
||||
@ -398,6 +427,7 @@
|
||||
"not_signed_in_indicator.not_signed_in": "Necesas saluti por aliri tiun rimedon.",
|
||||
"notification.admin.report": "{name} raportis {target}",
|
||||
"notification.admin.sign_up": "{name} kreis konton",
|
||||
"notification.favourite": "{name} stelumis vian afiŝon",
|
||||
"notification.follow": "{name} eksekvis vin",
|
||||
"notification.follow_request": "{name} petis sekvi vin",
|
||||
"notification.mention": "{name} menciis vin",
|
||||
@ -411,6 +441,7 @@
|
||||
"notifications.column_settings.admin.report": "Novaj raportoj:",
|
||||
"notifications.column_settings.admin.sign_up": "Novaj registriĝoj:",
|
||||
"notifications.column_settings.alert": "Sciigoj de la retumilo",
|
||||
"notifications.column_settings.favourite": "Stelumoj:",
|
||||
"notifications.column_settings.filter_bar.advanced": "Montri ĉiujn kategoriojn",
|
||||
"notifications.column_settings.filter_bar.category": "Rapida filtra breto",
|
||||
"notifications.column_settings.filter_bar.show_bar": "Montri la breton de filtrilo",
|
||||
@ -428,6 +459,7 @@
|
||||
"notifications.column_settings.update": "Redaktoj:",
|
||||
"notifications.filter.all": "Ĉiuj",
|
||||
"notifications.filter.boosts": "Diskonigoj",
|
||||
"notifications.filter.favourites": "Stelumoj",
|
||||
"notifications.filter.follows": "Sekvoj",
|
||||
"notifications.filter.mentions": "Mencioj",
|
||||
"notifications.filter.polls": "Balotenketaj rezultoj",
|
||||
@ -441,14 +473,29 @@
|
||||
"notifications_permission_banner.enable": "Ŝalti retumilajn sciigojn",
|
||||
"notifications_permission_banner.how_to_control": "Por ricevi sciigojn kiam Mastodon ne estas malfermita, ebligu labortablajn sciigojn. Vi povas regi precize kiuj specoj de interagoj generas labortablajn sciigojn per la supra butono {icon} post kiam ili estas ebligitaj.",
|
||||
"notifications_permission_banner.title": "Neniam preterlasas iun ajn",
|
||||
"onboarding.action.back": "Prenu min reen",
|
||||
"onboarding.actions.back": "Prenu min reen",
|
||||
"onboarding.actions.go_to_explore": "See what's trending",
|
||||
"onboarding.actions.go_to_home": "Go to your home feed",
|
||||
"onboarding.compose.template": "Saluton #Mastodon!",
|
||||
"onboarding.follows.empty": "Bedaŭrinde, neniu rezulto estas montrebla nuntempe. Vi povas provi serĉi aŭ foliumi la esploran paĝon por trovi kontojn por sekvi, aŭ retrovi baldaŭ.",
|
||||
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
|
||||
"onboarding.follows.title": "Popular on Mastodon",
|
||||
"onboarding.profile.discoverable": "Trovebligi mian profilon",
|
||||
"onboarding.profile.discoverable_hint": "Kiam vi aliĝi al trovebleco ĉe Mastodon, viaj afiŝoj eble aperos en serĉaj rezultoj kaj populariĝoj, kaj via profilo eble estas sugestota al personoj kun similaj intereseoj al vi.",
|
||||
"onboarding.profile.display_name": "Publika nomo",
|
||||
"onboarding.profile.display_name_hint": "Via plena nomo aŭ via kromnomo…",
|
||||
"onboarding.profile.lead": "Vi ĉiam povas plenigi ĉi tion poste en la agordoj, kie eĉ pli da personecigagordoj estas disponeblaj.",
|
||||
"onboarding.profile.note": "Sinprezento",
|
||||
"onboarding.profile.note_hint": "Vi povas @mencii aliajn homojn aŭ #kradvortojn…",
|
||||
"onboarding.profile.save_and_continue": "Konservi kaj daŭrigi",
|
||||
"onboarding.profile.title": "Profila fikso",
|
||||
"onboarding.profile.upload_avatar": "Alŝuti profilbildon",
|
||||
"onboarding.profile.upload_header": "Alŝuti profilkapbildon",
|
||||
"onboarding.share.lead": "Sciigi personojn pri kiel ili povas trovi vin ĉe Mastodon!",
|
||||
"onboarding.share.message": "Mi estas {username} en #Mastodon! Sekvu min ĉe {url}",
|
||||
"onboarding.share.next_steps": "Eblaj malantauaj paŝoj:",
|
||||
"onboarding.share.title": "Disvastigi vian profilon",
|
||||
"onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:",
|
||||
"onboarding.start.skip": "Want to skip right ahead?",
|
||||
"onboarding.start.title": "Vi atingas ĝin!",
|
||||
@ -460,6 +507,9 @@
|
||||
"onboarding.steps.setup_profile.title": "Customize your profile",
|
||||
"onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!",
|
||||
"onboarding.steps.share_profile.title": "Share your profile",
|
||||
"onboarding.tips.2fa": "<strong>Ĉu vi scias?</strong> Vi povas sekurigi vian konton per efektivigi dufaktora autentigo en via kontoagordoj.",
|
||||
"onboarding.tips.accounts_from_other_servers": "<strong>Ĉu vi scias?</strong> Ĉar Mastodon estas sencentra, kelkaj profiloj kiujn vi trovi estas gastigitaj ĉe aliaj serviloj kiuj ne estas via.",
|
||||
"onboarding.tips.migration": "<strong>Ĉu vi scias?</strong> Se vi sentas ke {domain} ne estas bona servilelekto por vi en la estonteco, vi povas translokiĝi al alia servilo de Mastodon sen malgajni viajn sekvantojn.",
|
||||
"password_confirmation.mismatching": "Pasvorto konfirmo ne kongruas",
|
||||
"picture_in_picture.restore": "Remetu ĝin",
|
||||
"poll.closed": "Finita",
|
||||
|
@ -702,7 +702,7 @@
|
||||
"timeline_hint.resources.followers": "Les abonnés",
|
||||
"timeline_hint.resources.follows": "Les abonnements",
|
||||
"timeline_hint.resources.statuses": "Messages plus anciens",
|
||||
"trends.counter_by_accounts": "{count, plural, one {{counter} personne} other {{counter} personnes}} au cours {days, plural, one {des dernières 24h} other {des {days} derniers jours}}",
|
||||
"trends.counter_by_accounts": "{count, plural, one {{counter} pers.} other {{counter} pers.}} sur {days, plural, one {les dernières 24h} other {les {days} derniers jours}}",
|
||||
"trends.trending_now": "Tendance en ce moment",
|
||||
"ui.beforeunload": "Votre brouillon sera perdu si vous quittez Mastodon.",
|
||||
"units.short.billion": "{count}Md",
|
||||
|
@ -479,7 +479,7 @@
|
||||
"onboarding.actions.go_to_home": "Ugrás a saját hírfolyamra",
|
||||
"onboarding.compose.template": "Üdvözlet, #Mastodon!",
|
||||
"onboarding.follows.empty": "Sajnos jelenleg nem jeleníthető meg eredmény. Kipróbálhatod a keresést vagy böngészheted a felfedező oldalon a követni kívánt személyeket, vagy próbáld meg később.",
|
||||
"onboarding.follows.lead": "A saját hírfolyamod az elsődleges tapasztalás a Mastodonon. Minél több embert követsz, annál aktívabb és érdekesebb a dolog. Az induláshoz itt van néhány javaslat:",
|
||||
"onboarding.follows.lead": "A kezdőlapod a Mastodon használatának elsődleges módja. Minél több embert követsz, annál aktívabbak és érdekesebbek lesznek a dolgok. Az induláshoz itt van néhány javaslat:",
|
||||
"onboarding.follows.title": "Szabd személyre a kezdőlapodat",
|
||||
"onboarding.profile.discoverable": "Saját profil beállítása felfedezhetőként",
|
||||
"onboarding.profile.discoverable_hint": "A Mastodonon a felfedezhetőség választása esetén a saját bejegyzéseid megjelenhetnek a keresési eredmények és a felkapott tartalmak között, valamint a profilod a hozzád hasonló érdeklődési körrel rendelkező embereknél is ajánlásra kerülhet.",
|
||||
@ -720,7 +720,7 @@
|
||||
"upload_form.undo": "Törlés",
|
||||
"upload_form.video_description": "Leírás siket, hallássérült, vak vagy gyengénlátó emberek számára",
|
||||
"upload_modal.analyzing_picture": "Kép elemzése…",
|
||||
"upload_modal.apply": "Alkalmazás",
|
||||
"upload_modal.apply": "Alkalmaz",
|
||||
"upload_modal.applying": "Alkalmazás…",
|
||||
"upload_modal.choose_image": "Kép kiválasztása",
|
||||
"upload_modal.description_placeholder": "A gyors, barna róka átugrik a lusta kutya fölött",
|
||||
|
@ -239,7 +239,7 @@
|
||||
"empty_column.follow_requests": "아직 팔로우 요청이 없습니다. 요청을 받았을 때 여기에 나타납니다.",
|
||||
"empty_column.followed_tags": "아직 아무 해시태그도 팔로우하고 있지 않습니다. 해시태그를 팔로우하면, 여기에 표시됩니다.",
|
||||
"empty_column.hashtag": "이 해시태그는 아직 사용되지 않았습니다.",
|
||||
"empty_column.home": "당신의 홈 타임라인은 비어있습니다! 더 많은 사람들을 팔로우 하여 채워보세요. {suggestions}",
|
||||
"empty_column.home": "당신의 홈 타임라인은 비어있습니다! 더 많은 사람을 팔로우하여 채워보세요. {suggestions}",
|
||||
"empty_column.list": "리스트에 아직 아무것도 없습니다. 리스트의 누군가가 게시물을 올리면 여기에 나타납니다.",
|
||||
"empty_column.lists": "아직 리스트가 없습니다. 리스트를 만들면 여기에 나타납니다.",
|
||||
"empty_column.mutes": "아직 아무도 뮤트하지 않았습니다.",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"about.contact": "Ratio:",
|
||||
"about.domain_blocks.no_reason_available": "ratio abdere est",
|
||||
"about.domain_blocks.no_reason_available": "Ratio abdere est",
|
||||
"account.account_note_header": "Annotatio",
|
||||
"account.badges.bot": "Robotum",
|
||||
"account.badges.group": "Congregatio",
|
||||
@ -49,7 +49,7 @@
|
||||
"dismissable_banner.explore_links": "These news stories are being talked about by people on this and other servers of the decentralized network right now.",
|
||||
"dismissable_banner.explore_tags": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.",
|
||||
"embed.instructions": "Embed this status on your website by copying the code below.",
|
||||
"emoji_button.food": "cibus et potus",
|
||||
"emoji_button.food": "Cibus et potus",
|
||||
"emoji_button.people": "Homines",
|
||||
"emoji_button.search": "Quaerere...",
|
||||
"empty_column.account_timeline": "Hic nulla contributa!",
|
||||
@ -57,13 +57,13 @@
|
||||
"empty_column.home": "Your home timeline is empty! Follow more people to fill it up. {suggestions}",
|
||||
"empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.",
|
||||
"explore.trending_statuses": "Contributa",
|
||||
"generic.saved": "servavit",
|
||||
"generic.saved": "Servavit",
|
||||
"hashtag.column_settings.tag_toggle": "Include additional tags in this column",
|
||||
"keyboard_shortcuts.back": "to navigate back",
|
||||
"keyboard_shortcuts.blocked": "to open blocked users list",
|
||||
"keyboard_shortcuts.boost": "to boost",
|
||||
"keyboard_shortcuts.column": "to focus a status in one of the columns",
|
||||
"keyboard_shortcuts.compose": "to focus the compose textarea",
|
||||
"keyboard_shortcuts.back": "Re navigare",
|
||||
"keyboard_shortcuts.blocked": "Aperire listam usorum obstructorum",
|
||||
"keyboard_shortcuts.boost": "Inlustrare publicatio",
|
||||
"keyboard_shortcuts.column": "Columnam dirigere",
|
||||
"keyboard_shortcuts.compose": "TextArea Compositi Attendere",
|
||||
"keyboard_shortcuts.description": "Descriptio",
|
||||
"keyboard_shortcuts.direct": "to open direct messages column",
|
||||
"keyboard_shortcuts.down": "to move down in the list",
|
||||
|
@ -21,6 +21,7 @@
|
||||
"account.blocked": "ဘလော့ထားသည်",
|
||||
"account.browse_more_on_origin_server": "မူရင်းပရိုဖိုင်တွင် ပိုမိုကြည့်ရှုပါ။",
|
||||
"account.cancel_follow_request": "စောင့်ကြည့်မှု ပယ်ဖျက်ခြင်း",
|
||||
"account.copy": "လင့်ခ်ကို ပရိုဖိုင်သို့ ကူးယူပါ",
|
||||
"account.direct": "@{name} သီးသန့် သိရှိနိုင်အောင် မန်းရှင်းခေါ်မည်",
|
||||
"account.disable_notifications": "@{name} ပို့စ်တင်သည့်အခါ ကျွန်ုပ်ထံ အသိပေးခြင်း မပြုလုပ်ရန်။",
|
||||
"account.domain_blocked": "ဒိုမိန်း ပိတ်ပင်ထားခဲ့သည်",
|
||||
@ -191,6 +192,7 @@
|
||||
"conversation.mark_as_read": "ဖတ်ပြီးသားအဖြစ်မှတ်ထားပါ",
|
||||
"conversation.open": "Conversation ကိုကြည့်မည်",
|
||||
"conversation.with": "{အမည်များ} ဖြင့်",
|
||||
"copy_icon_button.copied": "ကလစ်ဘုတ်သို့ ကူးပါ",
|
||||
"copypaste.copied": "ကူယူပြီးပါပြီ",
|
||||
"copypaste.copy_to_clipboard": "ကလစ်ဘုတ်သို့ ကူးပါ",
|
||||
"directory.federated": "သင် သိသော ဖက်ဒီမှ",
|
||||
@ -389,6 +391,7 @@
|
||||
"lists.search": "မိမိဖောလိုးထားသူများမှရှာဖွေမည်",
|
||||
"lists.subheading": "သင့်၏စာရင်းများ",
|
||||
"load_pending": "{count, plural, one {# new item} other {# new items}}",
|
||||
"loading_indicator.label": "လုပ်ဆောင်နေသည်…",
|
||||
"media_gallery.toggle_visible": "{number, plural, one {Hide image} other {Hide images}}",
|
||||
"moved_to_account_banner.text": "{movedToAccount} အကောင့်သို့ပြောင်းလဲထားသဖြင့် {disabledAccount} အကောင့်မှာပိတ်ထားသည်",
|
||||
"mute_modal.duration": "ကြာချိန်",
|
||||
@ -477,6 +480,13 @@
|
||||
"onboarding.follows.empty": "ယခုအချိန် မည်သည့်ရလဒ်ကိုမျှ မပြသနိုင်ပါ။ လူများကိုစောင့်ကြည့်ရန်အတွက် Explore စာမျက်နှာကို အသုံးပြု၍ စမ်းကြည့်နိုင်သည် သို့မဟုတ် နောက်မှ ထပ်စမ်းကြည့်ပါ။",
|
||||
"onboarding.follows.lead": "သင့်ကိုယ်ပိုင်ပို့စ်များ တင်နိုင်သည်။ သင်စောင့်ကြည့်သူ များလေလေ၊ စိတ်ဝင်စားစရာကောင်းသောပို့စ်များ တွေ့ရလေဖြစ်သည်။ ဤပရိုဖိုင်များမှာ ကောင်းမွန်သောအစပြုမှုတစ်ခုဖြစ်ပြီး ၎င်းတို့ကိုစောင့်ကြည့်ခြင်းမှလည်း အချိန်မရွေး ပယ်ဖျက်နိုင်ပါသည်။",
|
||||
"onboarding.follows.title": "Mastodon တွင် ရေပန်းစားခြင်း",
|
||||
"onboarding.profile.discoverable": "ပရိုဖိုင် ရှာဖွေနိုင်ပါမည်",
|
||||
"onboarding.profile.display_name": "ဖော်ပြမည့်အမည်",
|
||||
"onboarding.profile.display_name_hint": "သင့်အမည်အပြည့်အစုံ သို့မဟုတ် သင့်အမည်ပြောင်။",
|
||||
"onboarding.profile.note": "ကိုယ်ရေးအကျဉ်း",
|
||||
"onboarding.profile.save_and_continue": "သိမ်းပြီး ဆက်လုပ်ပါ",
|
||||
"onboarding.profile.title": "ပရိုဖိုင်စနစ် ထည့်သွင်းခြင်း",
|
||||
"onboarding.profile.upload_avatar": "ပရိုဖိုင်ပုံ အပ်လုဒ်လုပ်ပါ",
|
||||
"onboarding.share.lead": "Mastodon တွင် သင့်အား မည်သို့ရှာတွေ့နိုင်သည်ကို အသိပေးပါ။",
|
||||
"onboarding.share.message": "Mastodon ရှိ ကျွန်ုပ်၏အမည်မှာ {username} ဖြစ်သည်။ ကျွန်ုပ်ကို {url} တွင် စောင့်ကြည့်နိုင်ပါသည်",
|
||||
"onboarding.share.next_steps": "ဖြစ်နိုင်ချေရှိသော နောက်အဆင့်များ -",
|
||||
@ -520,6 +530,7 @@
|
||||
"privacy.unlisted.short": "စာရင်းမသွင်းထားပါ",
|
||||
"privacy_policy.last_updated": "နောက်ဆုံး ပြင်ဆင်ခဲ့သည့်ရက်စွဲ {date}",
|
||||
"privacy_policy.title": "ကိုယ်ရေးအချက်အလက်မူဝါဒ",
|
||||
"recommended": "အကြံပြုသည်",
|
||||
"refresh": "ပြန်လည်စတင်ပါ",
|
||||
"regeneration_indicator.label": "လုပ်ဆောင်နေသည်…",
|
||||
"regeneration_indicator.sublabel": "သင့်ပင်မစာမျက်နှာကို ပြင်ဆင်နေပါသည်။",
|
||||
@ -590,6 +601,7 @@
|
||||
"search.quick_action.status_search": "{x} နှင့် ကိုက်ညီသော ပို့စ်များ",
|
||||
"search.search_or_paste": "URL ရိုက်ထည့်ပါ သို့မဟုတ် ရှာဖွေပါ",
|
||||
"search_popout.full_text_search_disabled_message": "{domain} တွင် မရနိုင်ပါ။",
|
||||
"search_popout.full_text_search_logged_out_message": "အကောင့်ဝင်ထားမှသာ ရနိုင်သည်။",
|
||||
"search_popout.language_code": "ISO ဘာသာစကားကုဒ်",
|
||||
"search_popout.options": "ရွေးချယ်ထားသည်များ ရှာဖွေရန်",
|
||||
"search_popout.quick_actions": "အမြန်လုပ်ဆောင်မှုများ",
|
||||
|
@ -1 +1,53 @@
|
||||
{}
|
||||
{
|
||||
"about.contact": "सम्पर्क:",
|
||||
"about.disclaimer": "Mastodon नि:शुल्क, खुला स्रोत सफ्टवेयर, र Mastodon gGmbH को ट्रेडमार्क हो।",
|
||||
"about.domain_blocks.no_reason_available": "कारण उपलब्ध छैन",
|
||||
"about.domain_blocks.preamble": "Mastodon ले तपाइँलाई सामान्यतया फेडिभर्समा कुनै पनि अन्य सर्भरका सामग्री हेर्न र प्रयोगकर्ताहरूसँग अन्तरक्रिया गर्न दिन्छ। यी अपवादहरू हुन् जुन यस विशेष सर्भरमा बनाइएका छन्।",
|
||||
"about.domain_blocks.silenced.title": "सीमित",
|
||||
"about.domain_blocks.suspended.explanation": "यस सर्भरबाट कुनै पनि डेटा प्रशोधन, भण्डारण वा आदानप्रदान गरिने छैन, जसले यस सर्भरका प्रयोगकर्ताहरूसँग कुनै पनि अन्तरक्रिया वा सञ्चारलाई असम्भव बनाउँछ।",
|
||||
"about.domain_blocks.suspended.title": "निलम्बित",
|
||||
"about.not_available": "यो जानकारी यस सर्भरमा उपलब्ध गराइएको छैन।",
|
||||
"about.powered_by": "{mastodon} द्वारा संचालित विकेन्द्रीकृत सामाजिक मिडिया",
|
||||
"about.rules": "सर्भर नियमहरू",
|
||||
"account.add_or_remove_from_list": "सूचीबाट थप्नुहोस् वा हटाउनुहोस्",
|
||||
"account.badges.group": "समूह",
|
||||
"account.block": "@{name} लाई ब्लक गर्नुहोस्",
|
||||
"account.block_domain": "{domain} डोमेनलाई ब्लक गर्नुहोस्",
|
||||
"account.block_short": "ब्लक",
|
||||
"account.blocked": "ब्लक गरिएको",
|
||||
"account.browse_more_on_origin_server": "मूल प्रोफाइलमा थप ब्राउज गर्नुहोस्",
|
||||
"account.cancel_follow_request": "फलो अनुरोध रद्द गर्नुहोस",
|
||||
"account.copy": "प्रोफाइलको लिङ्क प्रतिलिपि गर्नुहोस्",
|
||||
"account.direct": "@{name} लाई निजी रूपमा उल्लेख गर्नुहोस्",
|
||||
"account.disable_notifications": "@{name} ले पोस्ट गर्दा मलाई सूचित नगर्नुहोस्",
|
||||
"account.domain_blocked": "डोमेन ब्लक गरिएको छ",
|
||||
"account.edit_profile": "प्रोफाइल सम्पादन गर्नुहोस्",
|
||||
"account.enable_notifications": "@{name} ले पोस्ट गर्दा मलाई सूचित गर्नुहोस्",
|
||||
"account.endorse": "प्रोफाइलमा फिचर गर्नुहोस्",
|
||||
"account.featured_tags.last_status_never": "कुनै पोस्ट छैन",
|
||||
"account.follow": "फलो गर्नुहोस",
|
||||
"account.followers.empty": "यस प्रयोगकर्तालाई अहिलेसम्म कसैले फलो गर्दैन।",
|
||||
"account.follows.empty": "यो प्रयोगकर्ताले अहिलेसम्म कसैलाई फलो गरेको छैन।",
|
||||
"account.go_to_profile": "प्रोफाइलमा जानुहोस्",
|
||||
"account.hide_reblogs": "@{name} को बूस्टहरू लुकाउनुहोस्",
|
||||
"account.link_verified_on": "यस लिङ्कको स्वामित्व {date} मा जाँच गरिएको थियो",
|
||||
"account.media": "मिडिया",
|
||||
"account.mention": "@{name} लाई उल्लेख गर्नुहोस्",
|
||||
"account.no_bio": "कुनै विवरण प्रदान गरिएको छैन।",
|
||||
"account.posts": "पोस्टहरू",
|
||||
"account.requested": "स्वीकृतिको पर्खाइमा। फलो अनुरोध रद्द गर्न क्लिक गर्नुहोस्",
|
||||
"account.requested_follow": "{name} ले तपाईंलाई फलो गर्न अनुरोध गर्नुभएको छ",
|
||||
"account.share": "@{name} को प्रोफाइल सेयर गर्नुहोस्",
|
||||
"account.show_reblogs": "@{name} को बूस्टहरू देखाउनुहोस्",
|
||||
"account.statuses_counter": "{count, plural, one {{counter} पोस्ट} other {{counter} पोस्टहरू}}",
|
||||
"account.unblock": "@{name} लाई अनब्लक गर्नुहोस्",
|
||||
"account.unblock_domain": "{domain} डोमेनलाई अनब्लक गर्नुहोस्",
|
||||
"account.unblock_short": "अनब्लक गर्नुहोस्",
|
||||
"account.unendorse": "प्रोफाइलमा फिचर नगर्नुहोस्",
|
||||
"account.unfollow": "अनफलो गर्नुहोस्",
|
||||
"account_note.placeholder": "नोट लेख्न क्लिक गर्नुहोस्",
|
||||
"admin.dashboard.retention.average": "औसत",
|
||||
"admin.dashboard.retention.cohort_size": "नयाँ प्रयोगकर्ताहरू",
|
||||
"alert.rate_limited.message": "कृपया {retry_time, time, medium} पछि पुन: प्रयास गर्नुहोस्।",
|
||||
"alert.unexpected.message": "एउटा अनपेक्षित त्रुटि भयो।"
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
"about.domain_blocks.silenced.explanation": "Normalmente não verá perfis e conteúdo deste servidor, a menos que os procure explicitamente ou opte por os seguir.",
|
||||
"about.domain_blocks.silenced.title": "Limitados",
|
||||
"about.domain_blocks.suspended.explanation": "Nenhum dado deste servidor será processado, armazenado ou trocado, impossibilitando qualquer interação ou comunicação com os utilizadores dessas instâncias.",
|
||||
"about.domain_blocks.suspended.title": "Supensos",
|
||||
"about.domain_blocks.suspended.title": "Suspensos",
|
||||
"about.not_available": "Esta informação não foi disponibilizada neste servidor.",
|
||||
"about.powered_by": "Rede social descentralizada baseada no {mastodon}",
|
||||
"about.rules": "Regras do servidor",
|
||||
|
@ -224,6 +224,7 @@
|
||||
"emoji_button.search_results": "Výsledky hľadania",
|
||||
"emoji_button.symbols": "Symboly",
|
||||
"emoji_button.travel": "Cestovanie a miesta",
|
||||
"empty_column.account_hides_collections": "Tento užívateľ si zvolil nesprístupniť túto informáciu",
|
||||
"empty_column.account_suspended": "Účet bol pozastavený",
|
||||
"empty_column.account_timeline": "Nie sú tu žiadne príspevky!",
|
||||
"empty_column.account_unavailable": "Profil nedostupný",
|
||||
|
@ -8,7 +8,7 @@
|
||||
"about.domain_blocks.silenced.title": "已受限",
|
||||
"about.domain_blocks.suspended.explanation": "來自此伺服器的資料都不會被處理、儲存或交換,也無法與此伺服器上的使用者互動或交流。",
|
||||
"about.domain_blocks.suspended.title": "已停權",
|
||||
"about.not_available": "無法於本伺服器上使用此資訊。",
|
||||
"about.not_available": "無法於此伺服器上使用此資訊。",
|
||||
"about.powered_by": "由 {mastodon} 提供的去中心化社群媒體",
|
||||
"about.rules": "伺服器規則",
|
||||
"account.account_note_header": "備註",
|
||||
@ -34,9 +34,9 @@
|
||||
"account.follow": "跟隨",
|
||||
"account.followers": "跟隨者",
|
||||
"account.followers.empty": "尚未有人跟隨這位使用者。",
|
||||
"account.followers_counter": "被 {count, plural,one {{counter} 人}other {{counter} 人}}跟隨",
|
||||
"account.followers_counter": "被 {count, plural, other {{counter} 人}}跟隨",
|
||||
"account.following": "跟隨中",
|
||||
"account.following_counter": "正在跟隨 {count, plural, one {{counter} 人} other {{counter} 人}}",
|
||||
"account.following_counter": "正在跟隨 {count,plural,other {{counter} 人}}",
|
||||
"account.follows.empty": "這位使用者尚未跟隨任何人。",
|
||||
"account.follows_you": "跟隨了您",
|
||||
"account.go_to_profile": "前往個人檔案",
|
||||
@ -72,8 +72,8 @@
|
||||
"account.unmute_notifications_short": "取消靜音推播通知",
|
||||
"account.unmute_short": "解除靜音",
|
||||
"account_note.placeholder": "按此新增備註",
|
||||
"admin.dashboard.daily_retention": "註冊後使用者存留率(日)",
|
||||
"admin.dashboard.monthly_retention": "註冊後使用者存留率(月)",
|
||||
"admin.dashboard.daily_retention": "註冊後使用者存留率(日)",
|
||||
"admin.dashboard.monthly_retention": "註冊後使用者存留率(月)",
|
||||
"admin.dashboard.retention.average": "平均",
|
||||
"admin.dashboard.retention.cohort": "註冊月份",
|
||||
"admin.dashboard.retention.cohort_size": "新使用者",
|
||||
@ -103,9 +103,9 @@
|
||||
"bundle_modal_error.message": "載入此元件時發生錯誤。",
|
||||
"bundle_modal_error.retry": "重試",
|
||||
"closed_registrations.other_server_instructions": "因為 Mastodon 是去中心化的,所以您也能於其他伺服器上建立帳號,並仍然與這個伺服器互動。",
|
||||
"closed_registrations_modal.description": "目前無法於 {domain} 建立新帳號,但也請別忘了,您並不一定需要有 {domain} 伺服器的帳號,也能使用 Mastodon 。",
|
||||
"closed_registrations_modal.description": "目前無法於 {domain} 建立新帳號,但也請別忘了,您並不一定需要有 {domain} 伺服器的帳號,也能使用 Mastodon。",
|
||||
"closed_registrations_modal.find_another_server": "尋找另一個伺服器",
|
||||
"closed_registrations_modal.preamble": "Mastodon 是去中心化的,所以無論您於哪個伺服器新增帳號,都可以與此伺服器上的任何人跟隨及互動。您甚至能自行架一個自己的伺服器!",
|
||||
"closed_registrations_modal.preamble": "Mastodon 是去中心化的,所以無論您於哪個伺服器新增帳號,都可以與此伺服器上的任何人跟隨及互動。您甚至能自行架設一個自己的伺服器!",
|
||||
"closed_registrations_modal.title": "註冊 Mastodon",
|
||||
"column.about": "關於",
|
||||
"column.blocks": "已封鎖的使用者",
|
||||
@ -155,7 +155,7 @@
|
||||
"compose_form.publish_form": "嘟出去",
|
||||
"compose_form.publish_loud": "{publish}!",
|
||||
"compose_form.save_changes": "儲存變更",
|
||||
"compose_form.sensitive.hide": "標記媒體為敏感內容",
|
||||
"compose_form.sensitive.hide": "{count, plural, other {將媒體標記為敏感內容}}",
|
||||
"compose_form.sensitive.marked": "此媒體被標記為敏感內容",
|
||||
"compose_form.sensitive.unmarked": "此媒體未被標記為敏感內容",
|
||||
"compose_form.spoiler.marked": "移除內容警告",
|
||||
@ -207,14 +207,14 @@
|
||||
"dismissable_banner.explore_statuses": "這些於此伺服器以及去中心化網路中其他伺服器發出的嘟文正在被此伺服器上的人們熱烈討論著。越多不同人轉嘟及最愛排名更高。",
|
||||
"dismissable_banner.explore_tags": "這些主題標籤正在被此伺服器以及去中心化網路上的人們熱烈討論著。越多不同人所嘟出的主題標籤排名更高。",
|
||||
"dismissable_banner.public_timeline": "這些是來自 {domain} 使用者們跟隨中帳號所發表之最新公開嘟文。",
|
||||
"embed.instructions": "若您欲於您的網站嵌入此嘟文,請複製以下程式碼。",
|
||||
"embed.instructions": "如要將此嘟文嵌入您的網站,請複製以下程式碼。",
|
||||
"embed.preview": "它將顯示成這樣:",
|
||||
"emoji_button.activity": "活動",
|
||||
"emoji_button.clear": "清除",
|
||||
"emoji_button.custom": "自訂",
|
||||
"emoji_button.flags": "旗幟",
|
||||
"emoji_button.food": "食物 & 飲料",
|
||||
"emoji_button.label": "插入表情符號",
|
||||
"emoji_button.label": "插入表情圖案",
|
||||
"emoji_button.nature": "自然",
|
||||
"emoji_button.not_found": "啊就沒這表情符號吼!! (╯°□°)╯︵ ┻━┻",
|
||||
"emoji_button.objects": "物件",
|
||||
@ -353,11 +353,11 @@
|
||||
"keyboard_shortcuts.legend": "顯示此說明選單",
|
||||
"keyboard_shortcuts.local": "開啟本站時間軸",
|
||||
"keyboard_shortcuts.mention": "提及作者",
|
||||
"keyboard_shortcuts.muted": "開啟靜音使用者列表",
|
||||
"keyboard_shortcuts.muted": "開啟靜音使用者清單",
|
||||
"keyboard_shortcuts.my_profile": "開啟個人檔案頁面",
|
||||
"keyboard_shortcuts.notifications": "開啟通知欄",
|
||||
"keyboard_shortcuts.open_media": "開啟媒體",
|
||||
"keyboard_shortcuts.pinned": "開啟釘選的嘟文列表",
|
||||
"keyboard_shortcuts.pinned": "開啟釘選的嘟文清單",
|
||||
"keyboard_shortcuts.profile": "開啟作者的個人檔案頁面",
|
||||
"keyboard_shortcuts.reply": "回應嘟文",
|
||||
"keyboard_shortcuts.requests": "開啟跟隨請求列表",
|
||||
@ -386,7 +386,7 @@
|
||||
"lists.new.create": "新增列表",
|
||||
"lists.new.title_placeholder": "新列表標題",
|
||||
"lists.replies_policy.followed": "任何跟隨的使用者",
|
||||
"lists.replies_policy.list": "列表成員",
|
||||
"lists.replies_policy.list": "成員清單",
|
||||
"lists.replies_policy.none": "沒有人",
|
||||
"lists.replies_policy.title": "顯示回覆:",
|
||||
"lists.search": "搜尋您跟隨的使用者",
|
||||
@ -452,7 +452,7 @@
|
||||
"notifications.column_settings.push": "推播通知",
|
||||
"notifications.column_settings.reblog": "轉嘟:",
|
||||
"notifications.column_settings.show": "於欄位中顯示",
|
||||
"notifications.column_settings.sound": "播放聲音",
|
||||
"notifications.column_settings.sound": "播放音效",
|
||||
"notifications.column_settings.status": "新嘟文:",
|
||||
"notifications.column_settings.unread_notifications.category": "未讀通知",
|
||||
"notifications.column_settings.unread_notifications.highlight": "突顯未讀通知",
|
||||
@ -477,7 +477,7 @@
|
||||
"onboarding.actions.back": "返回",
|
||||
"onboarding.actions.go_to_explore": "看看發生什麼新鮮事",
|
||||
"onboarding.actions.go_to_home": "前往您的首頁時間軸",
|
||||
"onboarding.compose.template": "哈囉 #Mastodon!",
|
||||
"onboarding.compose.template": "你好 #Mastodon!",
|
||||
"onboarding.follows.empty": "很遺憾,目前未能顯示任何結果。您可以嘗試使用搜尋、瀏覽探索頁面以找尋人們跟隨、或稍候再試。",
|
||||
"onboarding.follows.lead": "您的首頁時間軸是 Mastodon 的核心體驗。若您跟隨更多人的話,它將會變得更活躍有趣。這些個人檔案也許是個好起點,您可以隨時取消跟隨他們!",
|
||||
"onboarding.follows.title": "客製化您的首頁時間軸",
|
||||
@ -540,7 +540,7 @@
|
||||
"regeneration_indicator.label": "載入中…",
|
||||
"regeneration_indicator.sublabel": "您的首頁時間軸正在準備中!",
|
||||
"relative_time.days": "{number} 天",
|
||||
"relative_time.full.days": "{number, plural, one {# 天} other {# 天}}前",
|
||||
"relative_time.full.days": "{number, plural, other {# 天}}前",
|
||||
"relative_time.full.hours": "{number, plural, one {# 小時} other {# 小時}}前",
|
||||
"relative_time.full.just_now": "剛剛",
|
||||
"relative_time.full.minutes": "{number, plural, one {# 分鐘} other {# 分鐘}}前",
|
||||
@ -620,7 +620,7 @@
|
||||
"search_results.see_all": "檢視全部",
|
||||
"search_results.statuses": "嘟文",
|
||||
"search_results.title": "搜尋:{q}",
|
||||
"server_banner.about_active_users": "最近三十日內使用此伺服器的人 (月活躍使用者)",
|
||||
"server_banner.about_active_users": "最近三十日內使用此伺服器的人(月活躍使用者)",
|
||||
"server_banner.active_users": "活躍使用者",
|
||||
"server_banner.administered_by": "管理者:",
|
||||
"server_banner.introduction": "{domain} 是由 {mastodon} 提供之去中心化社群網路一部分。",
|
||||
@ -687,7 +687,7 @@
|
||||
"status.translated_from_with": "透過 {provider} 翻譯 {lang}",
|
||||
"status.uncached_media_warning": "無法預覽",
|
||||
"status.unmute_conversation": "解除此對話的靜音",
|
||||
"status.unpin": "自個人檔案頁面取消釘選",
|
||||
"status.unpin": "從個人檔案頁面取消釘選",
|
||||
"subscribed_languages.lead": "僅選定語言的嘟文才會出現於您的首頁上,並於變更後列出時間軸。選取「無」以接收所有語言的嘟文。",
|
||||
"subscribed_languages.save": "儲存變更",
|
||||
"subscribed_languages.target": "變更 {target} 的訂閱語言",
|
||||
|
@ -4,7 +4,8 @@ class AttachmentBatch
|
||||
# Maximum amount of objects you can delete in an S3 API call. It's
|
||||
# important to remember that this does not correspond to the number
|
||||
# of records in the batch, since records can have multiple attachments
|
||||
LIMIT = 1_000
|
||||
LIMIT = ENV.fetch('S3_BATCH_DELETE_LIMIT', 1000).to_i
|
||||
MAX_RETRY = ENV.fetch('S3_BATCH_DELETE_RETRY', 3).to_i
|
||||
|
||||
# Attributes generated and maintained by Paperclip (not all of them
|
||||
# are always used on every class, however)
|
||||
@ -95,6 +96,7 @@ class AttachmentBatch
|
||||
# objects can be processed at once, so we have to potentially
|
||||
# separate them into multiple calls.
|
||||
|
||||
retries = 0
|
||||
keys.each_slice(LIMIT) do |keys_slice|
|
||||
logger.debug { "Deleting #{keys_slice.size} objects" }
|
||||
|
||||
@ -102,6 +104,17 @@ class AttachmentBatch
|
||||
objects: keys_slice.map { |key| { key: key } },
|
||||
quiet: true,
|
||||
})
|
||||
rescue => e
|
||||
retries += 1
|
||||
|
||||
if retries < MAX_RETRY
|
||||
logger.debug "Retry #{retries}/#{MAX_RETRY} after #{e.message}"
|
||||
sleep 2**retries
|
||||
retry
|
||||
else
|
||||
logger.error "Batch deletion from S3 failed after #{e.message}"
|
||||
raise e
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -14,9 +14,8 @@ class Vacuum::PreviewCardsVacuum
|
||||
private
|
||||
|
||||
def vacuum_cached_images!
|
||||
preview_cards_past_retention_period.find_each do |preview_card|
|
||||
preview_card.image.destroy
|
||||
preview_card.save
|
||||
preview_cards_past_retention_period.find_in_batches do |preview_card|
|
||||
AttachmentBatch.new(PreviewCard, preview_card).clear
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -9,9 +9,7 @@
|
||||
# url :string
|
||||
#
|
||||
class PreviewCardsStatus < ApplicationRecord
|
||||
# Composite primary keys are not properly supported in Rails. However,
|
||||
# we shouldn't need this anyway...
|
||||
self.primary_key = nil
|
||||
self.primary_key = [:preview_card_id, :status_id]
|
||||
|
||||
belongs_to :preview_card
|
||||
belongs_to :status
|
||||
|
@ -84,8 +84,7 @@ class Status < ApplicationRecord
|
||||
|
||||
has_and_belongs_to_many :tags
|
||||
|
||||
# Because of a composite primary key, the `dependent` option cannot be used on this association
|
||||
has_one :preview_cards_status, inverse_of: :status # rubocop:disable Rails/HasManyOrHasOneDependent
|
||||
has_one :preview_cards_status, inverse_of: :status, dependent: :delete
|
||||
|
||||
has_one :notification, as: :activity, dependent: :destroy
|
||||
has_one :status_stat, inverse_of: :status, dependent: nil
|
||||
@ -153,7 +152,6 @@ class Status < ApplicationRecord
|
||||
# The `prepend: true` option below ensures this runs before
|
||||
# the `dependent: destroy` callbacks remove relevant records
|
||||
before_destroy :unlink_from_conversations!, prepend: true
|
||||
before_destroy :reset_preview_card!
|
||||
|
||||
cache_associated :application,
|
||||
:media_attachments,
|
||||
|
@ -76,6 +76,15 @@ class FanOutOnWriteService < BaseService
|
||||
LocalNotificationWorker.push_bulk(mentions) do |mention|
|
||||
[mention.account_id, mention.id, 'Mention', 'mention']
|
||||
end
|
||||
|
||||
next unless update?
|
||||
|
||||
# This may result in duplicate update payloads, but this ensures clients
|
||||
# are aware of edits to posts only appearing in mention notifications
|
||||
# (e.g. private mentions or mentions by people they do not follow)
|
||||
PushUpdateWorker.push_bulk(mentions.filter { |mention| subscribed_to_streaming_api?(mention.account_id) }) do |mention|
|
||||
[mention.account_id, @status.id, "timeline:#{mention.account_id}:notifications", { 'update' => true }]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -170,4 +179,8 @@ class FanOutOnWriteService < BaseService
|
||||
def broadcastable?
|
||||
@status.public_visibility? && !@account.silenced? && (!@status.reblog? || Setting.show_reblogs_in_public_timelines)
|
||||
end
|
||||
|
||||
def subscribed_to_streaming_api?(account_id)
|
||||
redis.exists?("subscribed:timeline:#{account_id}") || redis.exists?("subscribed:timeline:#{account_id}:notifications")
|
||||
end
|
||||
end
|
||||
|
@ -100,7 +100,7 @@ class FetchOEmbedService
|
||||
end
|
||||
|
||||
def validate(oembed)
|
||||
oembed if oembed[:version].to_s == '1.0' && oembed[:type].present?
|
||||
oembed if oembed.present? && oembed[:version].to_s == '1.0' && oembed[:type].present?
|
||||
end
|
||||
|
||||
def html
|
||||
|
@ -6,7 +6,9 @@ hr:
|
||||
expires_at: Krajnji rok
|
||||
options: Opcije
|
||||
user:
|
||||
agreement: Ugovor o uslugama
|
||||
email: E-mail adresa
|
||||
locale: Lokalitet
|
||||
password: Lozinka
|
||||
user/account:
|
||||
username: Korisničko ime
|
||||
@ -18,3 +20,16 @@ hr:
|
||||
attributes:
|
||||
username:
|
||||
invalid: mora sadržavati samo slova, brojeve i _
|
||||
reserved: je rezervisano
|
||||
admin/webhook:
|
||||
attributes:
|
||||
url:
|
||||
invalid: nije validan URL
|
||||
doorkeeper/application:
|
||||
attributes:
|
||||
website:
|
||||
invalid: nije validan URL
|
||||
import:
|
||||
attributes:
|
||||
data:
|
||||
malformed: je neispravan
|
||||
|
@ -36,7 +36,7 @@ ru:
|
||||
status:
|
||||
attributes:
|
||||
reblog:
|
||||
taken: поста уже существует
|
||||
taken: пост уже существует
|
||||
user:
|
||||
attributes:
|
||||
email:
|
||||
|
@ -28,7 +28,7 @@ zh-TW:
|
||||
doorkeeper/application:
|
||||
attributes:
|
||||
website:
|
||||
invalid: 不是有效的 URL
|
||||
invalid: 不是有效的網址
|
||||
import:
|
||||
attributes:
|
||||
data:
|
||||
|
@ -29,7 +29,7 @@ zh-TW:
|
||||
edit:
|
||||
title: 編輯應用程式
|
||||
form:
|
||||
error: 唉呦!請看看表單以排查錯誤
|
||||
error: 糟糕!請檢查表單以排查錯誤
|
||||
help:
|
||||
native_redirect_uri: 請使用 %{native_redirect_uri} 作本站測試
|
||||
redirect_uri: 每行輸入一個 URI
|
||||
|
@ -534,6 +534,7 @@ en-GB:
|
||||
total_reported: Reports about them
|
||||
total_storage: Media attachments
|
||||
totals_time_period_hint_html: The totals displayed below include data for all time.
|
||||
unknown_instance: There is currently no record of this domain on this server.
|
||||
invites:
|
||||
deactivate_all: Deactivate all
|
||||
filter:
|
||||
@ -610,6 +611,7 @@ en-GB:
|
||||
created_at: Reported
|
||||
delete_and_resolve: Delete posts
|
||||
forwarded: Forwarded
|
||||
forwarded_replies_explanation: This report is from a remote user and about remote content. It has been forwarded to you because the reported content is in reply to one of your users.
|
||||
forwarded_to: Forwarded to %{domain}
|
||||
mark_as_resolved: Mark as resolved
|
||||
mark_as_sensitive: Mark as sensitive
|
||||
@ -1038,6 +1040,14 @@ en-GB:
|
||||
hint_html: Just one more thing! We need to confirm you're a human (this is so we can keep the spam out!). Solve the CAPTCHA below and click "Continue".
|
||||
title: Security check
|
||||
confirmations:
|
||||
awaiting_review: Your e-mail address is confirmed! The %{domain} staff is now reviewing your registration. You will receive an e-mail if they approve your account!
|
||||
awaiting_review_title: Your registration is being reviewed
|
||||
clicking_this_link: clicking this link
|
||||
login_link: log in
|
||||
proceed_to_login_html: You can now proceed to %{login_link}.
|
||||
redirect_to_app_html: You should have been redirected to the <strong>%{app_name}</strong> app. If that did not happen, try %{clicking_this_link} or manually return to the app.
|
||||
registration_complete: Your registration on %{domain} is now complete!
|
||||
welcome_title: Welcome, %{name}!
|
||||
wrong_email_hint: If that e-mail address is not correct, you can change it in account settings.
|
||||
delete_account: Delete account
|
||||
delete_account_html: If you wish to delete your account, you can <a href="%{path}">proceed here</a>. You will be asked for confirmation.
|
||||
@ -1099,6 +1109,7 @@ en-GB:
|
||||
functional: Your account is fully operational.
|
||||
pending: Your application is pending review by our staff. This may take some time. You will receive an e-mail if your application is approved.
|
||||
redirecting_to: Your account is inactive because it is currently redirecting to %{acct}.
|
||||
self_destruct: As %{domain} is closing down, you will only get limited access to your account.
|
||||
view_strikes: View past strikes against your account
|
||||
too_fast: Form submitted too fast, try again.
|
||||
use_security_key: Use security key
|
||||
@ -1356,6 +1367,7 @@ en-GB:
|
||||
'86400': 1 day
|
||||
expires_in_prompt: Never
|
||||
generate: Generate invite link
|
||||
invalid: This invite is not valid
|
||||
invited_by: 'You were invited by:'
|
||||
max_uses:
|
||||
one: 1 use
|
||||
@ -1568,6 +1580,9 @@ en-GB:
|
||||
over_daily_limit: You have exceeded the limit of %{limit} scheduled posts for today
|
||||
over_total_limit: You have exceeded the limit of %{limit} scheduled posts
|
||||
too_soon: The scheduled date must be in the future
|
||||
self_destruct:
|
||||
lead_html: Unfortunately, <strong>%{domain}</strong> is permanently closing down. If you had an account there, you will not be able to continue using it, but you can still request a backup of your data.
|
||||
title: This server is closing down
|
||||
sessions:
|
||||
activity: Last activity
|
||||
browser: Browser
|
||||
@ -1736,6 +1751,7 @@ en-GB:
|
||||
default: "%b %d, %Y, %H:%M"
|
||||
month: "%b %Y"
|
||||
time: "%H:%M"
|
||||
with_time_zone: "%b %d, %Y, %H:%M %Z"
|
||||
translation:
|
||||
errors:
|
||||
quota_exceeded: The server-wide usage quota for the translation service has been exceeded.
|
||||
|
@ -1324,6 +1324,7 @@ my:
|
||||
'86400': ၁ ရက်
|
||||
expires_in_prompt: ဘယ်တော့မှ
|
||||
generate: ဖိတ်ကြားချက်လင့်ခ် ဖန်တီးပါ
|
||||
invalid: ဤဖိတ်ကြားချက်မှာ မမှန်ကန်ပါ
|
||||
invited_by: သင့်ကို ဖိတ်ခေါ်ထားသည် -
|
||||
max_uses:
|
||||
other: "%{count} အသုံးပြုမှုများ"
|
||||
|
@ -16,7 +16,7 @@ zh-TW:
|
||||
acct: 指定要移動至的帳號的「使用者名稱@網域名稱」
|
||||
account_warning_preset:
|
||||
text: 您可使用嘟文語法,例如網址、「#」標籤與提及功能
|
||||
title: 可選的。不會向收件者顯示
|
||||
title: 可選。不會向收件者顯示
|
||||
admin_account_action:
|
||||
include_statuses: 使用者可看到導致檢舉或警告的嘟文
|
||||
send_email_notification: 使用者將收到帳號發生之事情的解釋
|
||||
|
@ -656,6 +656,10 @@ sk:
|
||||
rules_check:
|
||||
action: Spravuj serverové pravidlá
|
||||
message_html: Neurčil/a si žiadne serverové pravidlá.
|
||||
software_version_critical_check:
|
||||
action: Pozri dostupné aktualizácie
|
||||
software_version_patch_check:
|
||||
action: Pozri dostupné aktualizácie
|
||||
upload_check_privacy_error:
|
||||
action: Pozri tu pre viac informácií
|
||||
upload_check_privacy_error_object_storage:
|
||||
|
@ -467,7 +467,7 @@ zh-TW:
|
||||
other: 錯誤嘗試於 %{count} 天。
|
||||
no_failures_recorded: 報告中沒有錯誤。
|
||||
title: 可用狀態
|
||||
warning: 上一次嘗試連線至本伺服器失敗
|
||||
warning: 上一次嘗試連線至此伺服器失敗
|
||||
back_to_all: 所有
|
||||
back_to_limited: 受限制的
|
||||
back_to_warning: 警告
|
||||
@ -876,7 +876,7 @@ zh-TW:
|
||||
publishers:
|
||||
no_publisher_selected: 因未選取任何發行者,所以什麼事都沒發生
|
||||
shared_by_over_week:
|
||||
other: 上週被 %{count} 名使用者分享
|
||||
other: 上週被 %{count} 位使用者分享
|
||||
title: 熱門連結
|
||||
usage_comparison: 於今日被 %{today} 人分享,相較於昨日 %{yesterday} 人
|
||||
not_allowed_to_trend: 不允許登上熱門
|
||||
@ -1273,7 +1273,7 @@ zh-TW:
|
||||
other: 選取 %{count} 個符合您搜尋的項目。
|
||||
today: 今天
|
||||
validation_errors:
|
||||
other: 恩...似乎不太對勁耶?請檢查以下 %{count} 項錯誤
|
||||
other: 恩...似乎發生了點錯誤?請檢查以下 %{count} 項錯誤
|
||||
imports:
|
||||
errors:
|
||||
empty: 空的 CSV 檔案
|
||||
@ -1796,7 +1796,7 @@ zh-TW:
|
||||
welcome:
|
||||
edit_profile_action: 設定個人檔案
|
||||
edit_profile_step: 您可以設定您的個人檔案,包括上傳大頭貼、變更顯示名稱等等。您也可以選擇於新的跟隨者跟隨前,先對他們進行審核。
|
||||
explanation: 下面是幾個小幫助,希望它們能幫到您
|
||||
explanation: 以下是幾個小技巧,希望它們能幫到您
|
||||
final_action: 開始嘟嘟
|
||||
final_step: '開始嘟嘟吧!即使您現在沒有跟隨者,其他人仍然能於本站時間軸、主題標籤等地方,看到您的公開嘟文。試著用 #introductions 這個主題標籤介紹一下自己吧。'
|
||||
full_handle: 您的完整帳號名稱
|
||||
@ -1805,7 +1805,7 @@ zh-TW:
|
||||
title: "%{name} 誠摯歡迎您的加入!"
|
||||
users:
|
||||
follow_limit_reached: 您無法跟隨多於 %{limit} 個人
|
||||
go_to_sso_account_settings: 前往您的身分提供商 (identity provider) 之帳號設定
|
||||
go_to_sso_account_settings: 前往您的身分識別提供者(IdP)之帳號設定
|
||||
invalid_otp_token: 兩階段認證碼不正確
|
||||
otp_lost_help_html: 如果您無法存取這兩者,您可以透過 %{email} 與我們聯繫
|
||||
seamless_external_login: 由於您是由外部系統登入,所以不能設定密碼與電子郵件。
|
||||
|
@ -97,6 +97,8 @@ module Mastodon::CLI
|
||||
say("Removed #{custom_emojis_count} custom emojis#{dry_run_mode_suffix}", :green)
|
||||
end
|
||||
|
||||
CRAWL_SLEEP_TIME = 20
|
||||
|
||||
option :concurrency, type: :numeric, default: 50, aliases: [:c]
|
||||
option :format, type: :string, default: 'summary', aliases: [:f]
|
||||
option :exclude_suspended, type: :boolean, default: false, aliases: [:x]
|
||||
@ -168,8 +170,8 @@ module Mastodon::CLI
|
||||
pool.post(domain, &work_unit)
|
||||
end
|
||||
|
||||
sleep 20
|
||||
sleep 20 until pool.queue_length.zero?
|
||||
sleep CRAWL_SLEEP_TIME
|
||||
sleep CRAWL_SLEEP_TIME until pool.queue_length.zero?
|
||||
|
||||
pool.shutdown
|
||||
pool.wait_for_termination(20)
|
||||
|
@ -185,15 +185,15 @@ module Mastodon::CLI
|
||||
end
|
||||
|
||||
def schema_has_instances_view?
|
||||
ActiveRecord::Migrator.current_version >= 2020_12_06_004238
|
||||
migrator_version >= 2020_12_06_004238
|
||||
end
|
||||
|
||||
def verify_schema_version!
|
||||
if ActiveRecord::Migrator.current_version < MIN_SUPPORTED_VERSION
|
||||
if migrator_version < MIN_SUPPORTED_VERSION
|
||||
say 'Your version of the database schema is too old and is not supported by this script.', :red
|
||||
say 'Please update to at least Mastodon 3.0.0 before running this script.', :red
|
||||
exit(1)
|
||||
elsif ActiveRecord::Migrator.current_version > MAX_SUPPORTED_VERSION
|
||||
elsif migrator_version > MAX_SUPPORTED_VERSION
|
||||
say 'Your version of the database schema is more recent than this script, this may cause unexpected errors.', :yellow
|
||||
exit(1) unless yes?('Continue anyway? (Yes/No)')
|
||||
end
|
||||
@ -228,7 +228,7 @@ module Mastodon::CLI
|
||||
end
|
||||
|
||||
say 'Restoring index_accounts_on_username_and_domain_lower…'
|
||||
if ActiveRecord::Migrator.current_version < 2020_06_20_164023
|
||||
if migrator_version < 2020_06_20_164023
|
||||
ActiveRecord::Base.connection.add_index :accounts, 'lower (username), lower(domain)', name: 'index_accounts_on_username_and_domain_lower', unique: true
|
||||
else
|
||||
ActiveRecord::Base.connection.add_index :accounts, "lower (username), COALESCE(lower(domain), '')", name: 'index_accounts_on_username_and_domain_lower', unique: true
|
||||
@ -238,7 +238,7 @@ module Mastodon::CLI
|
||||
ActiveRecord::Base.connection.execute('REINDEX INDEX search_index;')
|
||||
ActiveRecord::Base.connection.execute('REINDEX INDEX index_accounts_on_uri;')
|
||||
ActiveRecord::Base.connection.execute('REINDEX INDEX index_accounts_on_url;')
|
||||
ActiveRecord::Base.connection.execute('REINDEX INDEX index_accounts_on_domain_and_id;') if ActiveRecord::Migrator.current_version >= 2023_05_24_190515
|
||||
ActiveRecord::Base.connection.execute('REINDEX INDEX index_accounts_on_domain_and_id;') if migrator_version >= 2023_05_24_190515
|
||||
end
|
||||
|
||||
def deduplicate_users!
|
||||
@ -269,15 +269,15 @@ module Mastodon::CLI
|
||||
say 'Restoring users indexes…'
|
||||
ActiveRecord::Base.connection.add_index :users, ['confirmation_token'], name: 'index_users_on_confirmation_token', unique: true
|
||||
ActiveRecord::Base.connection.add_index :users, ['email'], name: 'index_users_on_email', unique: true
|
||||
ActiveRecord::Base.connection.add_index :users, ['remember_token'], name: 'index_users_on_remember_token', unique: true if ActiveRecord::Migrator.current_version < 2022_01_18_183010
|
||||
ActiveRecord::Base.connection.add_index :users, ['remember_token'], name: 'index_users_on_remember_token', unique: true if migrator_version < 2022_01_18_183010
|
||||
|
||||
if ActiveRecord::Migrator.current_version < 2022_03_10_060641
|
||||
if migrator_version < 2022_03_10_060641
|
||||
ActiveRecord::Base.connection.add_index :users, ['reset_password_token'], name: 'index_users_on_reset_password_token', unique: true
|
||||
else
|
||||
ActiveRecord::Base.connection.add_index :users, ['reset_password_token'], name: 'index_users_on_reset_password_token', unique: true, where: 'reset_password_token IS NOT NULL', opclass: :text_pattern_ops
|
||||
end
|
||||
|
||||
ActiveRecord::Base.connection.execute('REINDEX INDEX index_users_on_unconfirmed_email;') if ActiveRecord::Migrator.current_version >= 2023_07_02_151753
|
||||
ActiveRecord::Base.connection.execute('REINDEX INDEX index_users_on_unconfirmed_email;') if migrator_version >= 2023_07_02_151753
|
||||
end
|
||||
|
||||
def deduplicate_users_process_confirmation_token
|
||||
@ -292,7 +292,7 @@ module Mastodon::CLI
|
||||
end
|
||||
|
||||
def deduplicate_users_process_remember_token
|
||||
if ActiveRecord::Migrator.current_version < 2022_01_18_183010
|
||||
if migrator_version < 2022_01_18_183010
|
||||
ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM users WHERE remember_token IS NOT NULL GROUP BY remember_token HAVING count(*) > 1").each do |row|
|
||||
users = User.where(id: row['ids'].split(',')).sort_by(&:updated_at).reverse.drop(1)
|
||||
say "Unsetting remember token for those accounts: #{users.map { |user| user.account.acct }.join(', ')}", :yellow
|
||||
@ -346,7 +346,7 @@ module Mastodon::CLI
|
||||
|
||||
remove_index_if_exists!(:announcement_reactions, 'index_announcement_reactions_on_account_id_and_announcement_id')
|
||||
|
||||
say 'Removing duplicate account identity proofs…'
|
||||
say 'Removing duplicate announcement reactions…'
|
||||
ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM announcement_reactions GROUP BY account_id, announcement_id, name HAVING count(*) > 1").each do |row|
|
||||
AnnouncementReaction.where(id: row['ids'].split(',')).sort_by(&:id).reverse.drop(1).each(&:destroy)
|
||||
end
|
||||
@ -371,7 +371,7 @@ module Mastodon::CLI
|
||||
end
|
||||
|
||||
say 'Restoring conversations indexes…'
|
||||
if ActiveRecord::Migrator.current_version < 2022_03_07_083603
|
||||
if migrator_version < 2022_03_07_083603
|
||||
ActiveRecord::Base.connection.add_index :conversations, ['uri'], name: 'index_conversations_on_uri', unique: true
|
||||
else
|
||||
ActiveRecord::Base.connection.add_index :conversations, ['uri'], name: 'index_conversations_on_uri', unique: true, where: 'uri IS NOT NULL', opclass: :text_pattern_ops
|
||||
@ -431,7 +431,7 @@ module Mastodon::CLI
|
||||
def deduplicate_domain_blocks!
|
||||
remove_index_if_exists!(:domain_blocks, 'index_domain_blocks_on_domain')
|
||||
|
||||
say 'Deduplicating domain_allows…'
|
||||
say 'Deduplicating domain_blocks…'
|
||||
ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM domain_blocks GROUP BY domain HAVING count(*) > 1").each do |row|
|
||||
domain_blocks = DomainBlock.where(id: row['ids'].split(',')).by_severity.reverse.to_a
|
||||
|
||||
@ -462,7 +462,7 @@ module Mastodon::CLI
|
||||
UnavailableDomain.where(id: row['ids'].split(',')).sort_by(&:id).reverse.drop(1).each(&:destroy)
|
||||
end
|
||||
|
||||
say 'Restoring domain_allows indexes…'
|
||||
say 'Restoring unavailable_domains indexes…'
|
||||
ActiveRecord::Base.connection.add_index :unavailable_domains, ['domain'], name: 'index_unavailable_domains_on_domain', unique: true
|
||||
end
|
||||
|
||||
@ -488,7 +488,7 @@ module Mastodon::CLI
|
||||
end
|
||||
|
||||
say 'Restoring media_attachments indexes…'
|
||||
if ActiveRecord::Migrator.current_version < 2022_03_10_060626
|
||||
if migrator_version < 2022_03_10_060626
|
||||
ActiveRecord::Base.connection.add_index :media_attachments, ['shortcode'], name: 'index_media_attachments_on_shortcode', unique: true
|
||||
else
|
||||
ActiveRecord::Base.connection.add_index :media_attachments, ['shortcode'], name: 'index_media_attachments_on_shortcode', unique: true, where: 'shortcode IS NOT NULL', opclass: :text_pattern_ops
|
||||
@ -521,7 +521,7 @@ module Mastodon::CLI
|
||||
end
|
||||
|
||||
say 'Restoring statuses indexes…'
|
||||
if ActiveRecord::Migrator.current_version < 2022_03_10_060706
|
||||
if migrator_version < 2022_03_10_060706
|
||||
ActiveRecord::Base.connection.add_index :statuses, ['uri'], name: 'index_statuses_on_uri', unique: true
|
||||
else
|
||||
ActiveRecord::Base.connection.add_index :statuses, ['uri'], name: 'index_statuses_on_uri', unique: true, where: 'uri IS NOT NULL', opclass: :text_pattern_ops
|
||||
@ -543,7 +543,7 @@ module Mastodon::CLI
|
||||
end
|
||||
|
||||
say 'Restoring tags indexes…'
|
||||
if ActiveRecord::Migrator.current_version < 2021_04_21_121431
|
||||
if migrator_version < 2021_04_21_121431
|
||||
ActiveRecord::Base.connection.add_index :tags, 'lower((name)::text)', name: 'index_tags_on_name_lower', unique: true
|
||||
else
|
||||
ActiveRecord::Base.connection.execute 'CREATE UNIQUE INDEX CONCURRENTLY index_tags_on_name_lower_btree ON tags (lower(name) text_pattern_ops)'
|
||||
@ -707,12 +707,16 @@ module Mastodon::CLI
|
||||
end
|
||||
end
|
||||
|
||||
def migrator_version
|
||||
ActiveRecord::Migrator.current_version
|
||||
end
|
||||
|
||||
def find_duplicate_accounts
|
||||
ActiveRecord::Base.connection.select_all("SELECT string_agg(id::text, ',') AS ids FROM accounts GROUP BY lower(username), COALESCE(lower(domain), '') HAVING count(*) > 1")
|
||||
end
|
||||
|
||||
def remove_index_if_exists!(table, name)
|
||||
ActiveRecord::Base.connection.remove_index(table, name: name)
|
||||
ActiveRecord::Base.connection.remove_index(table, name: name) if ActiveRecord::Base.connection.index_name_exists?(table, name)
|
||||
rescue ArgumentError, ActiveRecord::StatementInvalid
|
||||
nil
|
||||
end
|
||||
|
@ -205,7 +205,7 @@
|
||||
"prettier": "^3.0.0",
|
||||
"react-test-renderer": "^18.2.0",
|
||||
"stylelint": "^15.10.1",
|
||||
"stylelint-config-standard-scss": "^11.0.0",
|
||||
"stylelint-config-standard-scss": "^12.0.0",
|
||||
"typescript": "^5.0.4",
|
||||
"webpack-dev-server": "^3.11.3",
|
||||
"yargs": "^17.7.2"
|
||||
|
@ -1,23 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Accounts::IdentityProofsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns http success' do
|
||||
get :index, params: { account_id: account.id, limit: 2 }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
@ -1,25 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Accounts::ListsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:lists') }
|
||||
let(:account) { Fabricate(:account) }
|
||||
let(:list) { Fabricate(:list, account: user.account) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
user.account.follow!(account)
|
||||
list.accounts << account
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns http success' do
|
||||
get :index, params: { account_id: account.id }
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
@ -1,23 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Accounts::LookupController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
get :show, params: { account_id: account.id, acct: account.acct }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
@ -1,40 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::Accounts::PinsController do
|
||||
let(:john) { Fabricate(:user) }
|
||||
let(:kevin) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: john.id, scopes: 'write:accounts') }
|
||||
|
||||
before do
|
||||
kevin.account.followers << john.account
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
subject { post :create, params: { account_id: kevin.account.id } }
|
||||
|
||||
it 'creates account_pin', :aggregate_failures do
|
||||
expect do
|
||||
subject
|
||||
end.to change { AccountPin.where(account: john.account, target_account: kevin.account).count }.by(1)
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
subject { delete :destroy, params: { account_id: kevin.account.id } }
|
||||
|
||||
before do
|
||||
Fabricate(:account_pin, account: john.account, target_account: kevin.account)
|
||||
end
|
||||
|
||||
it 'destroys account_pin', :aggregate_failures do
|
||||
expect do
|
||||
subject
|
||||
end.to change { AccountPin.where(account: john.account, target_account: kevin.account).count }.by(-1)
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
@ -1,22 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V1::Accounts::SearchController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
it 'returns http success' do
|
||||
get :show, params: { q: 'query' }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
@ -1,23 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::FeaturedTags::SuggestionsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns http success' do
|
||||
get :index, params: { account_id: account.id, limit: 2 }
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
@ -1,22 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V2::SuggestionsController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read') }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'returns http success' do
|
||||
get :index
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
File diff suppressed because it is too large
Load Diff
@ -4,22 +4,29 @@ require 'rails_helper'
|
||||
require 'mastodon/cli/cache'
|
||||
|
||||
describe Mastodon::CLI::Cache do
|
||||
subject { cli.invoke(action, arguments, options) }
|
||||
|
||||
let(:cli) { described_class.new }
|
||||
let(:arguments) { [] }
|
||||
let(:options) { {} }
|
||||
|
||||
it_behaves_like 'CLI Command'
|
||||
|
||||
describe '#clear' do
|
||||
let(:action) { :clear }
|
||||
|
||||
before { allow(Rails.cache).to receive(:clear) }
|
||||
|
||||
it 'clears the Rails cache' do
|
||||
expect { cli.invoke(:clear) }.to output(
|
||||
a_string_including('OK')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
expect(Rails.cache).to have_received(:clear)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#recount' do
|
||||
let(:action) { :recount }
|
||||
|
||||
context 'with the `accounts` argument' do
|
||||
let(:arguments) { ['accounts'] }
|
||||
let(:account_stat) { Fabricate(:account_stat) }
|
||||
@ -29,9 +36,8 @@ describe Mastodon::CLI::Cache do
|
||||
end
|
||||
|
||||
it 're-calculates account records in the cache' do
|
||||
expect { cli.invoke(:recount, arguments) }.to output(
|
||||
a_string_including('OK')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(account_stat.reload.statuses_count).to be_zero
|
||||
end
|
||||
@ -46,9 +52,8 @@ describe Mastodon::CLI::Cache do
|
||||
end
|
||||
|
||||
it 're-calculates account records in the cache' do
|
||||
expect { cli.invoke(:recount, arguments) }.to output(
|
||||
a_string_including('OK')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(status_stat.reload.replies_count).to be_zero
|
||||
end
|
||||
@ -58,9 +63,9 @@ describe Mastodon::CLI::Cache do
|
||||
let(:arguments) { ['other-type'] }
|
||||
|
||||
it 'Exits with an error message' do
|
||||
expect { cli.invoke(:recount, arguments) }.to output(
|
||||
a_string_including('Unknown')
|
||||
).to_stdout.and raise_error(SystemExit)
|
||||
expect { subject }
|
||||
.to output_results('Unknown')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -4,42 +4,45 @@ require 'rails_helper'
|
||||
require 'mastodon/cli/canonical_email_blocks'
|
||||
|
||||
describe Mastodon::CLI::CanonicalEmailBlocks do
|
||||
subject { cli.invoke(action, arguments, options) }
|
||||
|
||||
let(:cli) { described_class.new }
|
||||
let(:arguments) { [] }
|
||||
let(:options) { {} }
|
||||
|
||||
it_behaves_like 'CLI Command'
|
||||
|
||||
describe '#find' do
|
||||
let(:action) { :find }
|
||||
let(:arguments) { ['user@example.com'] }
|
||||
|
||||
context 'when a block is present' do
|
||||
before { Fabricate(:canonical_email_block, email: 'user@example.com') }
|
||||
|
||||
it 'announces the presence of the block' do
|
||||
expect { cli.invoke(:find, arguments) }.to output(
|
||||
a_string_including('user@example.com is blocked')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('user@example.com is blocked')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a block is not present' do
|
||||
it 'announces the absence of the block' do
|
||||
expect { cli.invoke(:find, arguments) }.to output(
|
||||
a_string_including('user@example.com is not blocked')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('user@example.com is not blocked')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#remove' do
|
||||
let(:action) { :remove }
|
||||
let(:arguments) { ['user@example.com'] }
|
||||
|
||||
context 'when a block is present' do
|
||||
before { Fabricate(:canonical_email_block, email: 'user@example.com') }
|
||||
|
||||
it 'removes the block' do
|
||||
expect { cli.invoke(:remove, arguments) }.to output(
|
||||
a_string_including('Unblocked user@example.com')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('Unblocked user@example.com')
|
||||
|
||||
expect(CanonicalEmailBlock.matching_email('user@example.com')).to be_empty
|
||||
end
|
||||
@ -47,9 +50,8 @@ describe Mastodon::CLI::CanonicalEmailBlocks do
|
||||
|
||||
context 'when a block is not present' do
|
||||
it 'announces the absence of the block' do
|
||||
expect { cli.invoke(:remove, arguments) }.to output(
|
||||
a_string_including('user@example.com is not blocked')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('user@example.com is not blocked')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -4,22 +4,75 @@ require 'rails_helper'
|
||||
require 'mastodon/cli/domains'
|
||||
|
||||
describe Mastodon::CLI::Domains do
|
||||
subject { cli.invoke(action, arguments, options) }
|
||||
|
||||
let(:cli) { described_class.new }
|
||||
let(:arguments) { [] }
|
||||
let(:options) { {} }
|
||||
|
||||
it_behaves_like 'CLI Command'
|
||||
|
||||
describe '#purge' do
|
||||
let(:action) { :purge }
|
||||
|
||||
context 'with accounts from the domain' do
|
||||
let(:options) { {} }
|
||||
let(:domain) { 'host.example' }
|
||||
let!(:account) { Fabricate(:account, domain: domain) }
|
||||
let(:arguments) { [domain] }
|
||||
|
||||
it 'removes the account' do
|
||||
expect { cli.invoke(:purge, [domain], options) }.to output(
|
||||
a_string_including('Removed 1 accounts')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('Removed 1 accounts')
|
||||
|
||||
expect { account.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#crawl' do
|
||||
let(:action) { :crawl }
|
||||
|
||||
context 'with accounts from the domain' do
|
||||
let(:domain) { 'host.example' }
|
||||
|
||||
before do
|
||||
Fabricate(:account, domain: domain)
|
||||
stub_request(:get, 'https://host.example/api/v1/instance').to_return(status: 200, body: {}.to_json)
|
||||
stub_request(:get, 'https://host.example/api/v1/instance/peers').to_return(status: 200, body: {}.to_json)
|
||||
stub_request(:get, 'https://host.example/api/v1/instance/activity').to_return(status: 200, body: {}.to_json)
|
||||
stub_const('Mastodon::CLI::Domains::CRAWL_SLEEP_TIME', 0)
|
||||
end
|
||||
|
||||
context 'with --format of summary' do
|
||||
let(:options) { { format: 'summary' } }
|
||||
|
||||
it 'crawls the domains and summarizes results' do
|
||||
expect { subject }
|
||||
.to output_results('Visited 1 domains, 0 failed')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with --format of domains' do
|
||||
let(:options) { { format: 'domains' } }
|
||||
|
||||
it 'crawls the domains and summarizes results' do
|
||||
expect { subject }
|
||||
.to output_results(domain)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with --format of json' do
|
||||
let(:options) { { format: 'json' } }
|
||||
|
||||
it 'crawls the domains and summarizes results' do
|
||||
expect { subject }
|
||||
.to output_results(json_summary)
|
||||
end
|
||||
|
||||
def json_summary
|
||||
Oj.dump('host.example': { activity: {} })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -4,96 +4,99 @@ require 'rails_helper'
|
||||
require 'mastodon/cli/email_domain_blocks'
|
||||
|
||||
describe Mastodon::CLI::EmailDomainBlocks do
|
||||
subject { cli.invoke(action, arguments, options) }
|
||||
|
||||
let(:cli) { described_class.new }
|
||||
let(:arguments) { [] }
|
||||
let(:options) { {} }
|
||||
|
||||
it_behaves_like 'CLI Command'
|
||||
|
||||
describe '#list' do
|
||||
let(:action) { :list }
|
||||
|
||||
context 'with email domain block records' do
|
||||
let!(:parent_block) { Fabricate(:email_domain_block) }
|
||||
let!(:child_block) { Fabricate(:email_domain_block, parent: parent_block) }
|
||||
let(:options) { {} }
|
||||
|
||||
it 'lists the blocks' do
|
||||
expect { cli.invoke(:list, [], options) }.to output(
|
||||
a_string_including(parent_block.domain)
|
||||
.and(a_string_including(child_block.domain))
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results(
|
||||
parent_block.domain,
|
||||
child_block.domain
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#add' do
|
||||
context 'without any options' do
|
||||
let(:options) { {} }
|
||||
let(:action) { :add }
|
||||
|
||||
context 'without any options' do
|
||||
it 'warns about usage and exits' do
|
||||
expect { cli.invoke(:add, [], options) }.to output(
|
||||
a_string_including('No domain(s) given')
|
||||
).to_stdout.and raise_error(SystemExit)
|
||||
expect { subject }
|
||||
.to output_results('No domain(s) given')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when blocks exist' do
|
||||
let(:options) { {} }
|
||||
let(:domain) { 'host.example' }
|
||||
let(:arguments) { [domain] }
|
||||
|
||||
before { Fabricate(:email_domain_block, domain: domain) }
|
||||
|
||||
it 'does not add a new block' do
|
||||
expect { cli.invoke(:add, [domain], options) }.to output(
|
||||
a_string_including('is already blocked')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('is already blocked')
|
||||
.and(not_change(EmailDomainBlock, :count))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no blocks exist' do
|
||||
let(:options) { {} }
|
||||
let(:domain) { 'host.example' }
|
||||
let(:arguments) { [domain] }
|
||||
|
||||
it 'adds a new block' do
|
||||
expect { cli.invoke(:add, [domain], options) }.to output(
|
||||
a_string_including('Added 1')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('Added 1')
|
||||
.and(change(EmailDomainBlock, :count).by(1))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#remove' do
|
||||
context 'without any options' do
|
||||
let(:options) { {} }
|
||||
let(:action) { :remove }
|
||||
|
||||
context 'without any options' do
|
||||
it 'warns about usage and exits' do
|
||||
expect { cli.invoke(:remove, [], options) }.to output(
|
||||
a_string_including('No domain(s) given')
|
||||
).to_stdout.and raise_error(SystemExit)
|
||||
expect { subject }
|
||||
.to output_results('No domain(s) given')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when blocks exist' do
|
||||
let(:options) { {} }
|
||||
let(:domain) { 'host.example' }
|
||||
let(:arguments) { [domain] }
|
||||
|
||||
before { Fabricate(:email_domain_block, domain: domain) }
|
||||
|
||||
it 'removes the block' do
|
||||
expect { cli.invoke(:remove, [domain], options) }.to output(
|
||||
a_string_including('Removed 1')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('Removed 1')
|
||||
.and(change(EmailDomainBlock, :count).by(-1))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no blocks exist' do
|
||||
let(:options) { {} }
|
||||
let(:domain) { 'host.example' }
|
||||
let(:arguments) { [domain] }
|
||||
|
||||
it 'does not remove a block' do
|
||||
expect { cli.invoke(:remove, [domain], options) }.to output(
|
||||
a_string_including('is not yet blocked')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('is not yet blocked')
|
||||
.and(not_change(EmailDomainBlock, :count))
|
||||
end
|
||||
end
|
||||
|
@ -4,10 +4,10 @@ require 'rails_helper'
|
||||
require 'mastodon/cli/emoji'
|
||||
|
||||
describe Mastodon::CLI::Emoji do
|
||||
subject { cli.invoke(action, args, options) }
|
||||
subject { cli.invoke(action, arguments, options) }
|
||||
|
||||
let(:cli) { described_class.new }
|
||||
let(:args) { [] }
|
||||
let(:arguments) { [] }
|
||||
let(:options) { {} }
|
||||
|
||||
it_behaves_like 'CLI Command'
|
||||
@ -29,7 +29,7 @@ describe Mastodon::CLI::Emoji do
|
||||
context 'with existing custom emoji' do
|
||||
let(:import_path) { Rails.root.join('spec', 'fixtures', 'files', 'elite-assets.tar.gz') }
|
||||
let(:action) { :import }
|
||||
let(:args) { [import_path] }
|
||||
let(:arguments) { [import_path] }
|
||||
|
||||
it 'reports about imported emoji' do
|
||||
expect { subject }
|
||||
@ -51,7 +51,7 @@ describe Mastodon::CLI::Emoji do
|
||||
after { FileUtils.rm_rf(export_path.dirname) }
|
||||
|
||||
let(:export_path) { Rails.root.join('tmp', 'cli-tests', 'export.tar.gz') }
|
||||
let(:args) { [export_path.dirname.to_s] }
|
||||
let(:arguments) { [export_path.dirname.to_s] }
|
||||
let(:action) { :export }
|
||||
|
||||
it 'reports about exported emoji' do
|
||||
@ -61,8 +61,4 @@ describe Mastodon::CLI::Emoji do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def output_results(string)
|
||||
output(a_string_including(string)).to_stdout
|
||||
end
|
||||
end
|
||||
|
@ -4,20 +4,25 @@ require 'rails_helper'
|
||||
require 'mastodon/cli/feeds'
|
||||
|
||||
describe Mastodon::CLI::Feeds do
|
||||
subject { cli.invoke(action, arguments, options) }
|
||||
|
||||
let(:cli) { described_class.new }
|
||||
let(:arguments) { [] }
|
||||
let(:options) { {} }
|
||||
|
||||
it_behaves_like 'CLI Command'
|
||||
|
||||
describe '#build' do
|
||||
let(:action) { :build }
|
||||
|
||||
before { Fabricate(:account) }
|
||||
|
||||
context 'with --all option' do
|
||||
let(:options) { { all: true } }
|
||||
|
||||
it 'regenerates feeds for all accounts' do
|
||||
expect { cli.invoke(:build, [], options) }.to output(
|
||||
a_string_including('Regenerated feeds')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('Regenerated feeds')
|
||||
end
|
||||
end
|
||||
|
||||
@ -27,9 +32,8 @@ describe Mastodon::CLI::Feeds do
|
||||
let(:arguments) { ['alice'] }
|
||||
|
||||
it 'regenerates feeds for the account' do
|
||||
expect { cli.invoke(:build, arguments) }.to output(
|
||||
a_string_including('OK')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
end
|
||||
end
|
||||
|
||||
@ -37,22 +41,23 @@ describe Mastodon::CLI::Feeds do
|
||||
let(:arguments) { ['invalid-username'] }
|
||||
|
||||
it 'displays an error and exits' do
|
||||
expect { cli.invoke(:build, arguments) }.to output(
|
||||
a_string_including('No such account')
|
||||
).to_stdout.and raise_error(SystemExit)
|
||||
expect { subject }
|
||||
.to output_results('No such account')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#clear' do
|
||||
let(:action) { :clear }
|
||||
|
||||
before do
|
||||
allow(redis).to receive(:del).with(key_namespace)
|
||||
end
|
||||
|
||||
it 'clears the redis `feed:*` namespace' do
|
||||
expect { cli.invoke(:clear) }.to output(
|
||||
a_string_including('OK')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('OK')
|
||||
|
||||
expect(redis).to have_received(:del).with(key_namespace).once
|
||||
end
|
||||
|
@ -4,11 +4,16 @@ require 'rails_helper'
|
||||
require 'mastodon/cli/ip_blocks'
|
||||
|
||||
describe Mastodon::CLI::IpBlocks do
|
||||
subject { cli.invoke(action, arguments, options) }
|
||||
|
||||
let(:cli) { described_class.new }
|
||||
let(:arguments) { [] }
|
||||
let(:options) { {} }
|
||||
|
||||
it_behaves_like 'CLI Command'
|
||||
|
||||
describe '#add' do
|
||||
let(:action) { :add }
|
||||
let(:ip_list) do
|
||||
[
|
||||
'192.0.2.1',
|
||||
@ -25,29 +30,28 @@ describe Mastodon::CLI::IpBlocks do
|
||||
]
|
||||
end
|
||||
let(:options) { { severity: 'no_access' } }
|
||||
let(:arguments) { ip_list }
|
||||
|
||||
shared_examples 'ip address blocking' do
|
||||
it 'blocks all specified IP addresses' do
|
||||
cli.invoke(:add, ip_list, options)
|
||||
|
||||
blocked_ip_addresses = IpBlock.where(ip: ip_list).pluck(:ip)
|
||||
expected_ip_addresses = ip_list.map { |ip| IPAddr.new(ip) }
|
||||
|
||||
expect(blocked_ip_addresses).to match_array(expected_ip_addresses)
|
||||
def blocked_ip_addresses
|
||||
IpBlock.where(ip: ip_list).pluck(:ip)
|
||||
end
|
||||
|
||||
it 'sets the severity for all blocked IP addresses' do
|
||||
cli.invoke(:add, ip_list, options)
|
||||
|
||||
blocked_ips_severity = IpBlock.where(ip: ip_list).pluck(:severity).all?(options[:severity])
|
||||
|
||||
expect(blocked_ips_severity).to be(true)
|
||||
def expected_ip_addresses
|
||||
ip_list.map { |ip| IPAddr.new(ip) }
|
||||
end
|
||||
|
||||
it 'displays a success message with a summary' do
|
||||
expect { cli.invoke(:add, ip_list, options) }.to output(
|
||||
a_string_including("Added #{ip_list.size}, skipped 0, failed 0")
|
||||
).to_stdout
|
||||
def blocked_ips_severity
|
||||
IpBlock.where(ip: ip_list).pluck(:severity).all?(options[:severity])
|
||||
end
|
||||
|
||||
it 'blocks and sets severity for ip address and displays summary' do
|
||||
expect { subject }
|
||||
.to output_results("Added #{ip_list.size}, skipped 0, failed 0")
|
||||
expect(blocked_ip_addresses)
|
||||
.to match_array(expected_ip_addresses)
|
||||
expect(blocked_ips_severity)
|
||||
.to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
@ -57,27 +61,23 @@ describe Mastodon::CLI::IpBlocks do
|
||||
|
||||
context 'when a specified IP address is already blocked' do
|
||||
let!(:blocked_ip) { IpBlock.create(ip: ip_list.last, severity: options[:severity]) }
|
||||
let(:arguments) { ip_list }
|
||||
|
||||
it 'skips the already blocked IP address' do
|
||||
allow(IpBlock).to receive(:new).and_call_original
|
||||
before { allow(IpBlock).to receive(:new).and_call_original }
|
||||
|
||||
cli.invoke(:add, ip_list, options)
|
||||
it 'skips already block ip and displays the correct summary' do
|
||||
expect { subject }
|
||||
.to output_results("#{ip_list.last} is already blocked\nAdded #{ip_list.size - 1}, skipped 1, failed 0")
|
||||
|
||||
expect(IpBlock).to_not have_received(:new).with(ip: ip_list.last)
|
||||
end
|
||||
|
||||
it 'displays the correct summary' do
|
||||
expect { cli.invoke(:add, ip_list, options) }.to output(
|
||||
a_string_including("#{ip_list.last} is already blocked\nAdded #{ip_list.size - 1}, skipped 1, failed 0")
|
||||
).to_stdout
|
||||
end
|
||||
|
||||
context 'with --force option' do
|
||||
let!(:blocked_ip) { IpBlock.create(ip: ip_list.last, severity: 'no_access') }
|
||||
let(:options) { { severity: 'sign_up_requires_approval', force: true } }
|
||||
|
||||
it 'overwrites the existing IP block record' do
|
||||
expect { cli.invoke(:add, ip_list, options) }
|
||||
expect { subject }
|
||||
.to change { blocked_ip.reload.severity }
|
||||
.from('no_access')
|
||||
.to('sign_up_requires_approval')
|
||||
@ -89,11 +89,11 @@ describe Mastodon::CLI::IpBlocks do
|
||||
|
||||
context 'when a specified IP address is invalid' do
|
||||
let(:ip_list) { ['320.15.175.0', '9.5.105.255', '0.0.0.0'] }
|
||||
let(:arguments) { ip_list }
|
||||
|
||||
it 'displays the correct summary' do
|
||||
expect { cli.invoke(:add, ip_list, options) }.to output(
|
||||
a_string_including("#{ip_list.first} is invalid\nAdded #{ip_list.size - 1}, skipped 0, failed 1")
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results("#{ip_list.first} is invalid\nAdded #{ip_list.size - 1}, skipped 0, failed 1")
|
||||
end
|
||||
end
|
||||
|
||||
@ -124,6 +124,7 @@ describe Mastodon::CLI::IpBlocks do
|
||||
context 'when a specified IP address fails to be blocked' do
|
||||
let(:ip_address) { '127.0.0.1' }
|
||||
let(:ip_block) { instance_double(IpBlock, ip: ip_address, save: false) }
|
||||
let(:arguments) { [ip_address] }
|
||||
|
||||
before do
|
||||
allow(IpBlock).to receive(:new).and_return(ip_block)
|
||||
@ -132,24 +133,25 @@ describe Mastodon::CLI::IpBlocks do
|
||||
end
|
||||
|
||||
it 'displays an error message' do
|
||||
expect { cli.invoke(:add, [ip_address], options) }
|
||||
.to output(
|
||||
a_string_including("#{ip_address} could not be saved")
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results("#{ip_address} could not be saved")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no IP address is provided' do
|
||||
let(:arguments) { [] }
|
||||
|
||||
it 'exits with an error message' do
|
||||
expect { cli.add }.to output(
|
||||
a_string_including('No IP(s) given')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('No IP(s) given')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#remove' do
|
||||
let(:action) { :remove }
|
||||
|
||||
context 'when removing exact matches' do
|
||||
let(:ip_list) do
|
||||
[
|
||||
@ -166,22 +168,17 @@ describe Mastodon::CLI::IpBlocks do
|
||||
'::/128',
|
||||
]
|
||||
end
|
||||
let(:arguments) { ip_list }
|
||||
|
||||
before do
|
||||
ip_list.each { |ip| IpBlock.create(ip: ip, severity: :no_access) }
|
||||
end
|
||||
|
||||
it 'removes exact IP blocks' do
|
||||
cli.invoke(:remove, ip_list)
|
||||
|
||||
it 'removes exact ip blocks and displays success message with a summary' do
|
||||
expect { subject }
|
||||
.to output_results("Removed #{ip_list.size}, skipped 0")
|
||||
expect(IpBlock.where(ip: ip_list)).to_not exist
|
||||
end
|
||||
|
||||
it 'displays success message with a summary' do
|
||||
expect { cli.invoke(:remove, ip_list) }.to output(
|
||||
a_string_including("Removed #{ip_list.size}, skipped 0")
|
||||
).to_stdout
|
||||
end
|
||||
end
|
||||
|
||||
context 'with --force option' do
|
||||
@ -191,62 +188,60 @@ describe Mastodon::CLI::IpBlocks do
|
||||
let(:arguments) { ['192.168.0.5', '10.0.1.50'] }
|
||||
let(:options) { { force: true } }
|
||||
|
||||
it 'removes blocks for IP ranges that cover given IP(s)' do
|
||||
cli.invoke(:remove, arguments, options)
|
||||
it 'removes blocks for IP ranges that cover given IP(s) and keeps other ranges' do
|
||||
subject
|
||||
|
||||
expect(IpBlock.where(id: [first_ip_range_block.id, second_ip_range_block.id])).to_not exist
|
||||
expect(covered_ranges).to_not exist
|
||||
expect(other_ranges).to exist
|
||||
end
|
||||
|
||||
it 'does not remove other IP ranges' do
|
||||
cli.invoke(:remove, arguments, options)
|
||||
def covered_ranges
|
||||
IpBlock.where(id: [first_ip_range_block.id, second_ip_range_block.id])
|
||||
end
|
||||
|
||||
expect(IpBlock.where(id: third_ip_range_block.id)).to exist
|
||||
def other_ranges
|
||||
IpBlock.where(id: third_ip_range_block.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a specified IP address is not blocked' do
|
||||
let(:unblocked_ip) { '192.0.2.1' }
|
||||
let(:arguments) { [unblocked_ip] }
|
||||
|
||||
it 'skips the IP address' do
|
||||
expect { cli.invoke(:remove, [unblocked_ip]) }.to output(
|
||||
a_string_including("#{unblocked_ip} is not yet blocked")
|
||||
).to_stdout
|
||||
end
|
||||
|
||||
it 'displays the summary correctly' do
|
||||
expect { cli.invoke(:remove, [unblocked_ip]) }.to output(
|
||||
a_string_including('Removed 0, skipped 1')
|
||||
).to_stdout
|
||||
it 'skips the IP address and displays summary' do
|
||||
expect { subject }
|
||||
.to output_results(
|
||||
"#{unblocked_ip} is not yet blocked",
|
||||
'Removed 0, skipped 1'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a specified IP address is invalid' do
|
||||
let(:invalid_ip) { '320.15.175.0' }
|
||||
let(:arguments) { [invalid_ip] }
|
||||
|
||||
it 'skips the invalid IP address' do
|
||||
expect { cli.invoke(:remove, [invalid_ip]) }.to output(
|
||||
a_string_including("#{invalid_ip} is invalid")
|
||||
).to_stdout
|
||||
end
|
||||
|
||||
it 'displays the summary correctly' do
|
||||
expect { cli.invoke(:remove, [invalid_ip]) }.to output(
|
||||
a_string_including('Removed 0, skipped 1')
|
||||
).to_stdout
|
||||
it 'skips the invalid IP address and displays summary' do
|
||||
expect { subject }
|
||||
.to output_results(
|
||||
"#{invalid_ip} is invalid",
|
||||
'Removed 0, skipped 1'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no IP address is provided' do
|
||||
it 'exits with an error message' do
|
||||
expect { cli.remove }.to output(
|
||||
a_string_including('No IP(s) given')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('No IP(s) given')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#export' do
|
||||
let(:action) { :export }
|
||||
|
||||
let(:first_ip_range_block) { IpBlock.create(ip: '192.168.0.0/24', severity: :no_access) }
|
||||
let(:second_ip_range_block) { IpBlock.create(ip: '10.0.0.0/16', severity: :no_access) }
|
||||
let(:third_ip_range_block) { IpBlock.create(ip: '127.0.0.1', severity: :sign_up_block) }
|
||||
@ -255,15 +250,13 @@ describe Mastodon::CLI::IpBlocks do
|
||||
let(:options) { { format: 'plain' } }
|
||||
|
||||
it 'exports blocked IPs with "no_access" severity in plain format' do
|
||||
expect { cli.invoke(:export, nil, options) }.to output(
|
||||
a_string_including("#{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}\n#{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix}")
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results("#{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}\n#{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix}")
|
||||
end
|
||||
|
||||
it 'does not export bloked IPs with different severities' do
|
||||
expect { cli.invoke(:export, nil, options) }.to_not output(
|
||||
a_string_including("#{third_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}")
|
||||
).to_stdout
|
||||
it 'does not export blocked IPs with different severities' do
|
||||
expect { subject }
|
||||
.to_not output_results("#{third_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}")
|
||||
end
|
||||
end
|
||||
|
||||
@ -271,23 +264,20 @@ describe Mastodon::CLI::IpBlocks do
|
||||
let(:options) { { format: 'nginx' } }
|
||||
|
||||
it 'exports blocked IPs with "no_access" severity in plain format' do
|
||||
expect { cli.invoke(:export, nil, options) }.to output(
|
||||
a_string_including("deny #{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix};\ndeny #{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix};")
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results("deny #{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix};\ndeny #{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix};")
|
||||
end
|
||||
|
||||
it 'does not export bloked IPs with different severities' do
|
||||
expect { cli.invoke(:export, nil, options) }.to_not output(
|
||||
a_string_including("deny #{third_ip_range_block.ip}/#{first_ip_range_block.ip.prefix};")
|
||||
).to_stdout
|
||||
it 'does not export blocked IPs with different severities' do
|
||||
expect { subject }
|
||||
.to_not output_results("deny #{third_ip_range_block.ip}/#{first_ip_range_block.ip.prefix};")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when --format option is not provided' do
|
||||
it 'exports blocked IPs in plain format by default' do
|
||||
expect { cli.export }.to output(
|
||||
a_string_including("#{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}\n#{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix}")
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results("#{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}\n#{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -4,13 +4,20 @@ require 'rails_helper'
|
||||
require 'mastodon/cli/main'
|
||||
|
||||
describe Mastodon::CLI::Main do
|
||||
subject { cli.invoke(action, arguments, options) }
|
||||
|
||||
let(:cli) { described_class.new }
|
||||
let(:arguments) { [] }
|
||||
let(:options) { {} }
|
||||
|
||||
it_behaves_like 'CLI Command'
|
||||
|
||||
describe 'version' do
|
||||
describe '#version' do
|
||||
let(:action) { :version }
|
||||
|
||||
it 'returns the Mastodon version' do
|
||||
expect { described_class.new.invoke(:version) }.to output(
|
||||
a_string_including(Mastodon::Version.to_s)
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results(Mastodon::Version.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -4,20 +4,26 @@ require 'rails_helper'
|
||||
require 'mastodon/cli/maintenance'
|
||||
|
||||
describe Mastodon::CLI::Maintenance do
|
||||
subject { cli.invoke(action, arguments, options) }
|
||||
|
||||
let(:cli) { described_class.new }
|
||||
let(:arguments) { [] }
|
||||
let(:options) { {} }
|
||||
|
||||
it_behaves_like 'CLI Command'
|
||||
|
||||
describe '#fix_duplicates' do
|
||||
let(:action) { :fix_duplicates }
|
||||
|
||||
context 'when the database version is too old' do
|
||||
before do
|
||||
allow(ActiveRecord::Migrator).to receive(:current_version).and_return(2000_01_01_000000) # Earlier than minimum
|
||||
end
|
||||
|
||||
it 'Exits with error message' do
|
||||
expect { cli.invoke :fix_duplicates }.to output(
|
||||
a_string_including('is too old')
|
||||
).to_stdout.and raise_error(SystemExit)
|
||||
expect { subject }
|
||||
.to output_results('is too old')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
@ -28,9 +34,9 @@ describe Mastodon::CLI::Maintenance do
|
||||
end
|
||||
|
||||
it 'Exits with error message' do
|
||||
expect { cli.invoke :fix_duplicates }.to output(
|
||||
a_string_including('more recent')
|
||||
).to_stdout.and raise_error(SystemExit)
|
||||
expect { subject }
|
||||
.to output_results('more recent')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
@ -41,9 +47,9 @@ describe Mastodon::CLI::Maintenance do
|
||||
end
|
||||
|
||||
it 'Exits with error message' do
|
||||
expect { cli.invoke :fix_duplicates }.to output(
|
||||
a_string_including('Sidekiq is running')
|
||||
).to_stdout.and raise_error(SystemExit)
|
||||
expect { subject }
|
||||
.to output_results('Sidekiq is running')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -4,18 +4,24 @@ require 'rails_helper'
|
||||
require 'mastodon/cli/media'
|
||||
|
||||
describe Mastodon::CLI::Media do
|
||||
subject { cli.invoke(action, arguments, options) }
|
||||
|
||||
let(:cli) { described_class.new }
|
||||
let(:arguments) { [] }
|
||||
let(:options) { {} }
|
||||
|
||||
it_behaves_like 'CLI Command'
|
||||
|
||||
describe '#remove' do
|
||||
let(:action) { :remove }
|
||||
|
||||
context 'with --prune-profiles and --remove-headers' do
|
||||
let(:options) { { prune_profiles: true, remove_headers: true } }
|
||||
|
||||
it 'warns about usage and exits' do
|
||||
expect { cli.invoke(:remove, [], options) }.to output(
|
||||
a_string_including('--prune-profiles and --remove-headers should not be specified simultaneously')
|
||||
).to_stdout.and raise_error(SystemExit)
|
||||
expect { subject }
|
||||
.to output_results('--prune-profiles and --remove-headers should not be specified simultaneously')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
@ -23,9 +29,9 @@ describe Mastodon::CLI::Media do
|
||||
let(:options) { { include_follows: true } }
|
||||
|
||||
it 'warns about usage and exits' do
|
||||
expect { cli.invoke(:remove, [], options) }.to output(
|
||||
a_string_including('--include-follows can only be used with --prune-profiles or --remove-headers')
|
||||
).to_stdout.and raise_error(SystemExit)
|
||||
expect { subject }
|
||||
.to output_results('--include-follows can only be used with --prune-profiles or --remove-headers')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
@ -38,9 +44,8 @@ describe Mastodon::CLI::Media do
|
||||
let(:options) { { prune_profiles: true } }
|
||||
|
||||
it 'removes account avatars' do
|
||||
expect { cli.invoke(:remove, [], options) }.to output(
|
||||
a_string_including('Visited 1')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('Visited 1')
|
||||
|
||||
expect(account.reload.avatar).to be_blank
|
||||
end
|
||||
@ -50,9 +55,8 @@ describe Mastodon::CLI::Media do
|
||||
let(:options) { { remove_headers: true } }
|
||||
|
||||
it 'removes account header' do
|
||||
expect { cli.invoke(:remove, [], options) }.to output(
|
||||
a_string_including('Visited 1')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('Visited 1')
|
||||
|
||||
expect(account.reload.header).to be_blank
|
||||
end
|
||||
@ -64,9 +68,8 @@ describe Mastodon::CLI::Media do
|
||||
|
||||
context 'without options' do
|
||||
it 'removes account avatars' do
|
||||
expect { cli.invoke(:remove) }.to output(
|
||||
a_string_including('Removed 1')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('Removed 1')
|
||||
|
||||
expect(media_attachment.reload.file).to be_blank
|
||||
expect(media_attachment.reload.thumbnail).to be_blank
|
||||
@ -76,25 +79,50 @@ describe Mastodon::CLI::Media do
|
||||
end
|
||||
|
||||
describe '#usage' do
|
||||
context 'without options' do
|
||||
let(:options) { {} }
|
||||
let(:action) { :usage }
|
||||
|
||||
context 'without options' do
|
||||
it 'reports about storage size' do
|
||||
expect { cli.invoke(:usage, [], options) }.to output(
|
||||
a_string_including('0 Bytes')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('0 Bytes')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#lookup' do
|
||||
let(:action) { :lookup }
|
||||
let(:arguments) { [url] }
|
||||
|
||||
context 'with valid url not connected to a record' do
|
||||
let(:url) { 'https://example.host/assets/1' }
|
||||
|
||||
it 'warns about url and exits' do
|
||||
expect { subject }
|
||||
.to output_results('Not a media URL')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a valid media url' do
|
||||
let(:status) { Fabricate(:status) }
|
||||
let(:media_attachment) { Fabricate(:media_attachment, status: status) }
|
||||
let(:url) { media_attachment.file.url(:original) }
|
||||
|
||||
it 'displays the url of a connected status' do
|
||||
expect { subject }
|
||||
.to output_results(status.id.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#refresh' do
|
||||
context 'without any options' do
|
||||
let(:options) { {} }
|
||||
let(:action) { :refresh }
|
||||
|
||||
context 'without any options' do
|
||||
it 'warns about usage and exits' do
|
||||
expect { cli.invoke(:refresh, [], options) }.to output(
|
||||
a_string_including('Specify the source')
|
||||
).to_stdout.and raise_error(SystemExit)
|
||||
expect { subject }
|
||||
.to output_results('Specify the source')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
@ -108,9 +136,8 @@ describe Mastodon::CLI::Media do
|
||||
let(:status) { Fabricate(:status) }
|
||||
|
||||
it 'redownloads the attachment file' do
|
||||
expect { cli.invoke(:refresh, [], options) }.to output(
|
||||
a_string_including('Downloaded 1 media')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('Downloaded 1 media')
|
||||
end
|
||||
end
|
||||
|
||||
@ -119,9 +146,9 @@ describe Mastodon::CLI::Media do
|
||||
let(:options) { { account: 'not-real-user@example.host' } }
|
||||
|
||||
it 'warns about usage and exits' do
|
||||
expect { cli.invoke(:refresh, [], options) }.to output(
|
||||
a_string_including('No such account')
|
||||
).to_stdout.and raise_error(SystemExit)
|
||||
expect { subject }
|
||||
.to output_results('No such account')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
@ -135,9 +162,8 @@ describe Mastodon::CLI::Media do
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
it 'redownloads the attachment file' do
|
||||
expect { cli.invoke(:refresh, [], options) }.to output(
|
||||
a_string_including('Downloaded 1 media')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('Downloaded 1 media')
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -153,9 +179,8 @@ describe Mastodon::CLI::Media do
|
||||
let(:account) { Fabricate(:account, domain: domain) }
|
||||
|
||||
it 'redownloads the attachment file' do
|
||||
expect { cli.invoke(:refresh, [], options) }.to output(
|
||||
a_string_including('Downloaded 1 media')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('Downloaded 1 media')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -4,11 +4,17 @@ require 'rails_helper'
|
||||
require 'mastodon/cli/preview_cards'
|
||||
|
||||
describe Mastodon::CLI::PreviewCards do
|
||||
subject { cli.invoke(action, arguments, options) }
|
||||
|
||||
let(:cli) { described_class.new }
|
||||
let(:arguments) { [] }
|
||||
let(:options) { {} }
|
||||
|
||||
it_behaves_like 'CLI Command'
|
||||
|
||||
describe '#remove' do
|
||||
let(:action) { :remove }
|
||||
|
||||
context 'with relevant preview cards' do
|
||||
before do
|
||||
Fabricate(:preview_card, updated_at: 10.years.ago, type: :link)
|
||||
@ -18,10 +24,11 @@ describe Mastodon::CLI::PreviewCards do
|
||||
|
||||
context 'with no arguments' do
|
||||
it 'deletes thumbnails for local preview cards' do
|
||||
expect { cli.invoke(:remove) }.to output(
|
||||
a_string_including('Removed 2 preview cards')
|
||||
.and(a_string_including('approx. 119 KB'))
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results(
|
||||
'Removed 2 preview cards',
|
||||
'approx. 119 KB'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@ -29,10 +36,11 @@ describe Mastodon::CLI::PreviewCards do
|
||||
let(:options) { { link: true } }
|
||||
|
||||
it 'deletes thumbnails for local preview cards' do
|
||||
expect { cli.invoke(:remove, [], options) }.to output(
|
||||
a_string_including('Removed 1 link-type preview cards')
|
||||
.and(a_string_including('approx. 59.6 KB'))
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results(
|
||||
'Removed 1 link-type preview cards',
|
||||
'approx. 59.6 KB'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@ -40,10 +48,11 @@ describe Mastodon::CLI::PreviewCards do
|
||||
let(:options) { { days: 365 } }
|
||||
|
||||
it 'deletes thumbnails for local preview cards' do
|
||||
expect { cli.invoke(:remove, [], options) }.to output(
|
||||
a_string_including('Removed 1 preview cards')
|
||||
.and(a_string_including('approx. 59.6 KB'))
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results(
|
||||
'Removed 1 preview cards',
|
||||
'approx. 59.6 KB'
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -4,5 +4,79 @@ require 'rails_helper'
|
||||
require 'mastodon/cli/search'
|
||||
|
||||
describe Mastodon::CLI::Search do
|
||||
subject { cli.invoke(action, arguments, options) }
|
||||
|
||||
let(:cli) { described_class.new }
|
||||
let(:arguments) { [] }
|
||||
let(:options) { {} }
|
||||
|
||||
it_behaves_like 'CLI Command'
|
||||
|
||||
describe '#deploy' do
|
||||
let(:action) { :deploy }
|
||||
|
||||
context 'with concurrency out of range' do
|
||||
let(:options) { { concurrency: -100 } }
|
||||
|
||||
it 'Exits with error message' do
|
||||
expect { subject }
|
||||
.to output_results('this concurrency setting')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with batch size out of range' do
|
||||
let(:options) { { batch_size: -100_000 } }
|
||||
|
||||
it 'Exits with error message' do
|
||||
expect { subject }
|
||||
.to output_results('this batch_size setting')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'without options' do
|
||||
before { stub_search_indexes }
|
||||
|
||||
let(:indexed_count) { 1 }
|
||||
let(:deleted_count) { 2 }
|
||||
|
||||
it 'reports about storage size' do
|
||||
expect { subject }
|
||||
.to output_results(
|
||||
"Indexed #{described_class::INDICES.size * indexed_count} records",
|
||||
"de-indexed #{described_class::INDICES.size * deleted_count}"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def stub_search_indexes
|
||||
described_class::INDICES.each do |index|
|
||||
allow(index)
|
||||
.to receive_messages(
|
||||
specification: instance_double(Chewy::Index::Specification, changed?: true, lock!: nil),
|
||||
purge: nil
|
||||
)
|
||||
|
||||
importer_double = importer_double_for(index)
|
||||
allow(importer_double).to receive(:on_progress).and_yield([indexed_count, deleted_count])
|
||||
allow("Importer::#{index}Importer".constantize)
|
||||
.to receive(:new)
|
||||
.and_return(importer_double)
|
||||
end
|
||||
end
|
||||
|
||||
def importer_double_for(index)
|
||||
instance_double(
|
||||
"Importer::#{index}Importer".constantize,
|
||||
clean_up!: nil,
|
||||
estimate!: 100,
|
||||
import!: nil,
|
||||
on_failure: nil,
|
||||
# on_progress: nil,
|
||||
optimize_for_import!: nil,
|
||||
optimize_for_search!: nil
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -7,59 +7,53 @@ describe Mastodon::CLI::Settings do
|
||||
it_behaves_like 'CLI Command'
|
||||
|
||||
describe 'subcommand "registrations"' do
|
||||
subject { cli.invoke(action, arguments, options) }
|
||||
|
||||
let(:cli) { Mastodon::CLI::Registrations.new }
|
||||
let(:arguments) { [] }
|
||||
let(:options) { {} }
|
||||
|
||||
before do
|
||||
Setting.registrations_mode = nil
|
||||
end
|
||||
|
||||
describe '#open' do
|
||||
it 'changes "registrations_mode" to "open"' do
|
||||
expect { cli.open }.to change(Setting, :registrations_mode).from(nil).to('open')
|
||||
end
|
||||
let(:action) { :open }
|
||||
|
||||
it 'displays success message' do
|
||||
expect { cli.open }.to output(
|
||||
a_string_including('OK')
|
||||
).to_stdout
|
||||
it 'changes "registrations_mode" to "open" and displays success' do
|
||||
expect { subject }
|
||||
.to change(Setting, :registrations_mode).from(nil).to('open')
|
||||
.and output_results('OK')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#approved' do
|
||||
it 'changes "registrations_mode" to "approved"' do
|
||||
expect { cli.approved }.to change(Setting, :registrations_mode).from(nil).to('approved')
|
||||
end
|
||||
let(:action) { :approved }
|
||||
|
||||
it 'displays success message' do
|
||||
expect { cli.approved }.to output(
|
||||
a_string_including('OK')
|
||||
).to_stdout
|
||||
it 'changes "registrations_mode" to "approved" and displays success' do
|
||||
expect { subject }
|
||||
.to change(Setting, :registrations_mode).from(nil).to('approved')
|
||||
.and output_results('OK')
|
||||
end
|
||||
|
||||
context 'with --require-reason' do
|
||||
before do
|
||||
cli.options = { require_reason: true }
|
||||
end
|
||||
let(:options) { { require_reason: true } }
|
||||
|
||||
it 'changes "registrations_mode" to "approved"' do
|
||||
expect { cli.approved }.to change(Setting, :registrations_mode).from(nil).to('approved')
|
||||
end
|
||||
|
||||
it 'sets "require_invite_text" to "true"' do
|
||||
expect { cli.approved }.to change(Setting, :require_invite_text).from(false).to(true)
|
||||
it 'changes registrations_mode and require_invite_text' do
|
||||
expect { subject }
|
||||
.to change(Setting, :registrations_mode).from(nil).to('approved')
|
||||
.and change(Setting, :require_invite_text).from(false).to(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#close' do
|
||||
it 'changes "registrations_mode" to "none"' do
|
||||
expect { cli.close }.to change(Setting, :registrations_mode).from(nil).to('none')
|
||||
end
|
||||
let(:action) { :close }
|
||||
|
||||
it 'displays success message' do
|
||||
expect { cli.close }.to output(
|
||||
a_string_including('OK')
|
||||
).to_stdout
|
||||
it 'changes "registrations_mode" to "none" and displays success' do
|
||||
expect { subject }
|
||||
.to change(Setting, :registrations_mode).from(nil).to('none')
|
||||
.and output_results('OK')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -4,26 +4,31 @@ require 'rails_helper'
|
||||
require 'mastodon/cli/statuses'
|
||||
|
||||
describe Mastodon::CLI::Statuses do
|
||||
subject { cli.invoke(action, arguments, options) }
|
||||
|
||||
let(:cli) { described_class.new }
|
||||
let(:arguments) { [] }
|
||||
let(:options) { {} }
|
||||
|
||||
it_behaves_like 'CLI Command'
|
||||
|
||||
describe '#remove', use_transactional_tests: false do
|
||||
let(:action) { :remove }
|
||||
|
||||
context 'with small batch size' do
|
||||
let(:options) { { batch_size: 0 } }
|
||||
|
||||
it 'exits with error message' do
|
||||
expect { cli.invoke :remove, [], options }.to output(
|
||||
a_string_including('Cannot run')
|
||||
).to_stdout.and raise_error(SystemExit)
|
||||
expect { subject }
|
||||
.to output_results('Cannot run')
|
||||
.and raise_error(SystemExit)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with default batch size' do
|
||||
it 'removes unreferenced statuses' do
|
||||
expect { cli.invoke :remove }.to output(
|
||||
a_string_including('Done after')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('Done after')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -4,23 +4,26 @@ require 'rails_helper'
|
||||
require 'mastodon/cli/upgrade'
|
||||
|
||||
describe Mastodon::CLI::Upgrade do
|
||||
subject { cli.invoke(action, arguments, options) }
|
||||
|
||||
let(:cli) { described_class.new }
|
||||
let(:arguments) { [] }
|
||||
let(:options) { {} }
|
||||
|
||||
it_behaves_like 'CLI Command'
|
||||
|
||||
describe '#storage_schema' do
|
||||
context 'with records that dont need upgrading' do
|
||||
let(:options) { {} }
|
||||
let(:action) { :storage_schema }
|
||||
|
||||
context 'with records that dont need upgrading' do
|
||||
before do
|
||||
Fabricate(:account)
|
||||
Fabricate(:media_attachment)
|
||||
end
|
||||
|
||||
it 'does not upgrade storage for the attachments' do
|
||||
expect { cli.invoke(:storage_schema, [], options) }.to output(
|
||||
a_string_including('Upgraded storage schema of 0 records')
|
||||
).to_stdout
|
||||
expect { subject }
|
||||
.to output_results('Upgraded storage schema of 0 records')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -88,6 +88,7 @@ RSpec.configure do |config|
|
||||
config.include Chewy::Rspec::Helpers
|
||||
config.include Redisable
|
||||
config.include SignedRequestHelpers, type: :request
|
||||
config.include CommandLineHelpers, type: :cli
|
||||
|
||||
config.around(:each, use_transactional_tests: false) do |example|
|
||||
self.use_transactional_tests = false
|
||||
|
@ -2,20 +2,16 @@
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Accounts::FamiliarFollowersController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:follows') }
|
||||
describe 'Accounts Familiar Followers API' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:scopes) { 'read:follows' }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
describe 'GET /api/v1/accounts/familiar_followers' do
|
||||
it 'returns http success' do
|
||||
get :index, params: { account_id: account.id, limit: 2 }
|
||||
get '/api/v1/accounts/familiar_followers', params: { account_id: account.id, limit: 2 }, headers: headers
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
@ -26,7 +22,7 @@ describe Api::V1::Accounts::FamiliarFollowersController do
|
||||
|
||||
it 'removes duplicate account IDs from params' do
|
||||
account_ids = [account_a, account_b, account_b, account_a, account_a].map { |a| a.id.to_s }
|
||||
get :index, params: { id: account_ids }
|
||||
get '/api/v1/accounts/familiar_followers', params: { id: account_ids }, headers: headers
|
||||
|
||||
expect(body_as_json.pluck(:id)).to contain_exactly(account_a.id.to_s, account_b.id.to_s)
|
||||
end
|
19
spec/requests/api/v1/accounts/identity_proofs_spec.rb
Normal file
19
spec/requests/api/v1/accounts/identity_proofs_spec.rb
Normal file
@ -0,0 +1,19 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'Accounts Identity Proofs API' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:scopes) { 'read:accounts' }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
describe 'GET /api/v1/accounts/identity_proofs' do
|
||||
it 'returns http success' do
|
||||
get "/api/v1/accounts/#{account.id}/identity_proofs", params: { limit: 2 }, headers: headers
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
25
spec/requests/api/v1/accounts/lists_spec.rb
Normal file
25
spec/requests/api/v1/accounts/lists_spec.rb
Normal file
@ -0,0 +1,25 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'Accounts Lists API' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:scopes) { 'read:lists' }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
let(:account) { Fabricate(:account) }
|
||||
let(:list) { Fabricate(:list, account: user.account) }
|
||||
|
||||
before do
|
||||
user.account.follow!(account)
|
||||
list.accounts << account
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/lists' do
|
||||
it 'returns http success' do
|
||||
get "/api/v1/accounts/#{account.id}/lists", headers: headers
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
19
spec/requests/api/v1/accounts/lookup_spec.rb
Normal file
19
spec/requests/api/v1/accounts/lookup_spec.rb
Normal file
@ -0,0 +1,19 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'Accounts Lookup API' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:scopes) { 'read:accounts' }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
describe 'GET /api/v1/accounts/lookup' do
|
||||
it 'returns http success' do
|
||||
get '/api/v1/accounts/lookup', params: { account_id: account.id, acct: account.acct }, headers: headers
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
@ -2,21 +2,17 @@
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe Api::V1::Accounts::NotesController do
|
||||
render_views
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:accounts') }
|
||||
describe 'Accounts Notes API' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:scopes) { 'write:accounts' }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
let(:account) { Fabricate(:account) }
|
||||
let(:comment) { 'foo' }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
describe 'POST /api/v1/accounts/:account_id/note' do
|
||||
subject do
|
||||
post :create, params: { account_id: account.id, comment: comment }
|
||||
post "/api/v1/accounts/#{account.id}/note", params: { comment: comment }, headers: headers
|
||||
end
|
||||
|
||||
context 'when account note has reasonable length', :aggregate_failures do
|
41
spec/requests/api/v1/accounts/pins_spec.rb
Normal file
41
spec/requests/api/v1/accounts/pins_spec.rb
Normal file
@ -0,0 +1,41 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'Accounts Pins API' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:scopes) { 'write:accounts' }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
let(:kevin) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
kevin.account.followers << user.account
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/accounts/:account_id/pin' do
|
||||
subject { post "/api/v1/accounts/#{kevin.account.id}/pin", headers: headers }
|
||||
|
||||
it 'creates account_pin', :aggregate_failures do
|
||||
expect do
|
||||
subject
|
||||
end.to change { AccountPin.where(account: user.account, target_account: kevin.account).count }.by(1)
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /api/v1/accounts/:account_id/unpin' do
|
||||
subject { post "/api/v1/accounts/#{kevin.account.id}/unpin", headers: headers }
|
||||
|
||||
before do
|
||||
Fabricate(:account_pin, account: user.account, target_account: kevin.account)
|
||||
end
|
||||
|
||||
it 'destroys account_pin', :aggregate_failures do
|
||||
expect do
|
||||
subject
|
||||
end.to change { AccountPin.where(account: user.account, target_account: kevin.account).count }.by(-1)
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
@ -31,8 +31,8 @@ describe 'GET /api/v1/accounts/relationships' do
|
||||
.to have_http_status(200)
|
||||
expect(body_as_json)
|
||||
.to be_an(Enumerable)
|
||||
.and have_attributes(
|
||||
first: include(
|
||||
.and contain_exactly(
|
||||
include(
|
||||
following: true,
|
||||
followed_by: false
|
||||
)
|
||||
@ -53,9 +53,11 @@ describe 'GET /api/v1/accounts/relationships' do
|
||||
expect(body_as_json)
|
||||
.to be_an(Enumerable)
|
||||
.and have_attributes(
|
||||
size: 2,
|
||||
first: include(simon_item),
|
||||
second: include(lewis_item)
|
||||
size: 2
|
||||
)
|
||||
.and contain_exactly(
|
||||
include(simon_item),
|
||||
include(lewis_item)
|
||||
)
|
||||
end
|
||||
end
|
||||
@ -71,10 +73,12 @@ describe 'GET /api/v1/accounts/relationships' do
|
||||
expect(body_as_json)
|
||||
.to be_an(Enumerable)
|
||||
.and have_attributes(
|
||||
size: 3,
|
||||
first: include(simon_item),
|
||||
second: include(lewis_item),
|
||||
third: include(bob_item)
|
||||
size: 3
|
||||
)
|
||||
.and contain_exactly(
|
||||
include(simon_item),
|
||||
include(lewis_item),
|
||||
include(bob_item)
|
||||
)
|
||||
end
|
||||
end
|
||||
@ -88,9 +92,11 @@ describe 'GET /api/v1/accounts/relationships' do
|
||||
expect(body_as_json)
|
||||
.to be_an(Enumerable)
|
||||
.and have_attributes(
|
||||
size: 2,
|
||||
first: include(simon_item),
|
||||
second: include(lewis_item)
|
||||
size: 2
|
||||
)
|
||||
.and contain_exactly(
|
||||
include(simon_item),
|
||||
include(lewis_item)
|
||||
)
|
||||
end
|
||||
end
|
||||
@ -116,7 +122,6 @@ describe 'GET /api/v1/accounts/relationships' do
|
||||
muting: false,
|
||||
requested: false,
|
||||
domain_blocking: false,
|
||||
|
||||
}
|
||||
end
|
||||
|
||||
@ -129,7 +134,6 @@ describe 'GET /api/v1/accounts/relationships' do
|
||||
muting: false,
|
||||
requested: false,
|
||||
domain_blocking: false,
|
||||
|
||||
}
|
||||
end
|
||||
end
|
||||
@ -149,8 +153,10 @@ describe 'GET /api/v1/accounts/relationships' do
|
||||
expect(body_as_json)
|
||||
.to be_an(Enumerable)
|
||||
.and have_attributes(
|
||||
size: 1,
|
||||
first: include(
|
||||
size: 1
|
||||
)
|
||||
.and contain_exactly(
|
||||
include(
|
||||
following: true,
|
||||
showing_reblogs: true
|
||||
)
|
||||
@ -168,8 +174,8 @@ describe 'GET /api/v1/accounts/relationships' do
|
||||
|
||||
expect(body_as_json)
|
||||
.to be_an(Enumerable)
|
||||
.and have_attributes(
|
||||
first: include(
|
||||
.and contain_exactly(
|
||||
include(
|
||||
following: false,
|
||||
showing_reblogs: false
|
||||
)
|
||||
|
18
spec/requests/api/v1/accounts/search_spec.rb
Normal file
18
spec/requests/api/v1/accounts/search_spec.rb
Normal file
@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'Accounts Search API' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:scopes) { 'read:accounts' }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
|
||||
describe 'GET /api/v1/accounts/search' do
|
||||
it 'returns http success' do
|
||||
get '/api/v1/accounts/search', params: { q: 'query' }, headers: headers
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
19
spec/requests/api/v1/featured_tags/suggestions_spec.rb
Normal file
19
spec/requests/api/v1/featured_tags/suggestions_spec.rb
Normal file
@ -0,0 +1,19 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'Featured Tags Suggestions API' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:scopes) { 'read:accounts' }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
let(:account) { Fabricate(:account) }
|
||||
|
||||
describe 'GET /api/v1/featured_tags/suggestions' do
|
||||
it 'returns http success' do
|
||||
get '/api/v1/featured_tags/suggestions', params: { account_id: account.id, limit: 2 }, headers: headers
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
@ -2,25 +2,21 @@
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::V2::SearchController do
|
||||
render_views
|
||||
|
||||
describe 'Search API' do
|
||||
context 'with token' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:search') }
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:scopes) { 'read:search' }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:doorkeeper_token) { token }
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
describe 'GET /api/v2/search' do
|
||||
let!(:bob) { Fabricate(:account, username: 'bob_test') }
|
||||
let!(:ana) { Fabricate(:account, username: 'ana_test') }
|
||||
let!(:tom) { Fabricate(:account, username: 'tom_test') }
|
||||
let(:params) { { q: 'test' } }
|
||||
|
||||
it 'returns http success' do
|
||||
get :index, params: params
|
||||
get '/api/v2/search', headers: headers, params: params
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
@ -29,7 +25,7 @@ RSpec.describe Api::V2::SearchController do
|
||||
let(:params) { { q: 'test', type: 'accounts' } }
|
||||
|
||||
it 'returns all matching accounts' do
|
||||
get :index, params: params
|
||||
get '/api/v2/search', headers: headers, params: params
|
||||
|
||||
expect(body_as_json[:accounts].pluck(:id)).to contain_exactly(bob.id.to_s, ana.id.to_s, tom.id.to_s)
|
||||
end
|
||||
@ -38,7 +34,7 @@ RSpec.describe Api::V2::SearchController do
|
||||
let(:params) { { q: 'test1', resolve: '1' } }
|
||||
|
||||
it 'returns http unauthorized' do
|
||||
get :index, params: params
|
||||
get '/api/v2/search', headers: headers, params: params
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
@ -48,7 +44,7 @@ RSpec.describe Api::V2::SearchController do
|
||||
let(:params) { { q: 'test1', offset: 1 } }
|
||||
|
||||
it 'returns http unauthorized' do
|
||||
get :index, params: params
|
||||
get '/api/v2/search', headers: headers, params: params
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
@ -62,7 +58,7 @@ RSpec.describe Api::V2::SearchController do
|
||||
end
|
||||
|
||||
it 'returns only the followed accounts' do
|
||||
get :index, params: params
|
||||
get '/api/v2/search', headers: headers, params: params
|
||||
|
||||
expect(body_as_json[:accounts].pluck(:id)).to contain_exactly(ana.id.to_s)
|
||||
end
|
||||
@ -73,7 +69,7 @@ RSpec.describe Api::V2::SearchController do
|
||||
before { allow(Search).to receive(:new).and_raise(Mastodon::SyntaxError) }
|
||||
|
||||
it 'returns http unprocessable_entity' do
|
||||
get :index, params: params
|
||||
get '/api/v2/search', headers: headers, params: params
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
end
|
||||
@ -83,7 +79,7 @@ RSpec.describe Api::V2::SearchController do
|
||||
before { allow(Search).to receive(:new).and_raise(ActiveRecord::RecordNotFound) }
|
||||
|
||||
it 'returns http not_found' do
|
||||
get :index, params: params
|
||||
get '/api/v2/search', headers: headers, params: params
|
||||
|
||||
expect(response).to have_http_status(404)
|
||||
end
|
||||
@ -92,11 +88,11 @@ RSpec.describe Api::V2::SearchController do
|
||||
end
|
||||
|
||||
context 'without token' do
|
||||
describe 'GET #index' do
|
||||
describe 'GET /api/v2/search' do
|
||||
let(:search_params) { nil }
|
||||
|
||||
before do
|
||||
get :index, params: search_params
|
||||
get '/api/v2/search', params: search_params
|
||||
end
|
||||
|
||||
context 'without a `q` param' do
|
18
spec/requests/api/v2/suggestions_spec.rb
Normal file
18
spec/requests/api/v2/suggestions_spec.rb
Normal file
@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'Suggestions API' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:scopes) { 'read' }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
|
||||
describe 'GET /api/v2/suggestions' do
|
||||
it 'returns http success' do
|
||||
get '/api/v2/suggestions', headers: headers
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
end
|
||||
end
|
||||
end
|
@ -6,11 +6,12 @@ RSpec.describe FanOutOnWriteService, type: :service do
|
||||
subject { described_class.new }
|
||||
|
||||
let(:last_active_at) { Time.now.utc }
|
||||
let(:status) { Fabricate(:status, account: alice, visibility: visibility, text: 'Hello @bob #hoge') }
|
||||
let(:status) { Fabricate(:status, account: alice, visibility: visibility, text: 'Hello @bob @eve #hoge') }
|
||||
|
||||
let!(:alice) { Fabricate(:user, current_sign_in_at: last_active_at).account }
|
||||
let!(:bob) { Fabricate(:user, current_sign_in_at: last_active_at, account_attributes: { username: 'bob' }).account }
|
||||
let!(:tom) { Fabricate(:user, current_sign_in_at: last_active_at).account }
|
||||
let!(:eve) { Fabricate(:user, current_sign_in_at: last_active_at, account_attributes: { username: 'eve' }).account }
|
||||
|
||||
before do
|
||||
bob.follow!(alice)
|
||||
@ -109,5 +110,24 @@ RSpec.describe FanOutOnWriteService, type: :service do
|
||||
expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge', anything)
|
||||
expect(redis).to_not have_received(:publish).with('timeline:public', anything)
|
||||
end
|
||||
|
||||
context 'when handling status updates', :sidekiq_fake do
|
||||
before do
|
||||
subject.call(status)
|
||||
|
||||
status.snapshot!(at_time: status.created_at, rate_limit: false)
|
||||
status.update!(text: 'Hello @bob @eve #hoge (edited)')
|
||||
status.snapshot!(account_id: status.account_id)
|
||||
|
||||
redis.set("subscribed:timeline:#{eve.id}:notifications", '1')
|
||||
|
||||
Sidekiq::Worker.clear_all
|
||||
end
|
||||
|
||||
it 'pushes the update to mentioned users through the notifications streaming channel' do
|
||||
subject.call(status, update: true)
|
||||
expect(PushUpdateWorker).to have_enqueued_sidekiq_job(anything, status.id, "timeline:#{eve.id}:notifications", { 'update' => true })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
9
spec/support/command_line_helpers.rb
Normal file
9
spec/support/command_line_helpers.rb
Normal file
@ -0,0 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module CommandLineHelpers
|
||||
def output_results(*args)
|
||||
output(
|
||||
include(*args)
|
||||
).to_stdout
|
||||
end
|
||||
end
|
397
yarn.lock
397
yarn.lock
@ -52,7 +52,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9, @babel/compat-data@npm:^7.23.3, @babel/compat-data@npm:^7.23.5":
|
||||
"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.23.3, @babel/compat-data@npm:^7.23.5":
|
||||
version: 7.23.5
|
||||
resolution: "@babel/compat-data@npm:7.23.5"
|
||||
checksum: 081278ed46131a890ad566a59c61600a5f9557bd8ee5e535890c8548192532ea92590742fd74bd9db83d74c669ef8a04a7e1c85cdea27f960233e3b83c3a957c
|
||||
@ -60,37 +60,37 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@babel/core@npm:^7.10.4, @babel/core@npm:^7.11.1, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.22.1":
|
||||
version: 7.23.5
|
||||
resolution: "@babel/core@npm:7.23.5"
|
||||
version: 7.23.6
|
||||
resolution: "@babel/core@npm:7.23.6"
|
||||
dependencies:
|
||||
"@ampproject/remapping": "npm:^2.2.0"
|
||||
"@babel/code-frame": "npm:^7.23.5"
|
||||
"@babel/generator": "npm:^7.23.5"
|
||||
"@babel/helper-compilation-targets": "npm:^7.22.15"
|
||||
"@babel/generator": "npm:^7.23.6"
|
||||
"@babel/helper-compilation-targets": "npm:^7.23.6"
|
||||
"@babel/helper-module-transforms": "npm:^7.23.3"
|
||||
"@babel/helpers": "npm:^7.23.5"
|
||||
"@babel/parser": "npm:^7.23.5"
|
||||
"@babel/helpers": "npm:^7.23.6"
|
||||
"@babel/parser": "npm:^7.23.6"
|
||||
"@babel/template": "npm:^7.22.15"
|
||||
"@babel/traverse": "npm:^7.23.5"
|
||||
"@babel/types": "npm:^7.23.5"
|
||||
"@babel/traverse": "npm:^7.23.6"
|
||||
"@babel/types": "npm:^7.23.6"
|
||||
convert-source-map: "npm:^2.0.0"
|
||||
debug: "npm:^4.1.0"
|
||||
gensync: "npm:^1.0.0-beta.2"
|
||||
json5: "npm:^2.2.3"
|
||||
semver: "npm:^6.3.1"
|
||||
checksum: 311a512a870ee330a3f9a7ea89e5df790b2b5af0b1bd98b10b4edc0de2ac440f0df4d69ea2c0ee38a4b89041b9a495802741d93603be7d4fd834ec8bb6970bd2
|
||||
checksum: a02bae7d916029b70706dc301535e1b31e5d216f55d4ee6f64a15825c6b69ee2c14c52a213d1497ec414e925ed4e9d897d41fb0d75df9fea28ed2c0008790e31
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/generator@npm:^7.23.5, @babel/generator@npm:^7.7.2":
|
||||
version: 7.23.5
|
||||
resolution: "@babel/generator@npm:7.23.5"
|
||||
"@babel/generator@npm:^7.23.6, @babel/generator@npm:^7.7.2":
|
||||
version: 7.23.6
|
||||
resolution: "@babel/generator@npm:7.23.6"
|
||||
dependencies:
|
||||
"@babel/types": "npm:^7.23.5"
|
||||
"@babel/types": "npm:^7.23.6"
|
||||
"@jridgewell/gen-mapping": "npm:^0.3.2"
|
||||
"@jridgewell/trace-mapping": "npm:^0.3.17"
|
||||
jsesc: "npm:^2.5.1"
|
||||
checksum: 14c6e874f796c4368e919bed6003bb0adc3ce837760b08f9e646d20aeb5ae7d309723ce6e4f06bcb4a2b5753145446c8e4425851380f695e40e71e1760f49e7b
|
||||
checksum: 53540e905cd10db05d9aee0a5304e36927f455ce66f95d1253bb8a179f286b88fa7062ea0db354c566fe27f8bb96567566084ffd259f8feaae1de5eccc8afbda
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -122,16 +122,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-compilation-targets@npm:^7.22.15, @babel/helper-compilation-targets@npm:^7.22.6":
|
||||
version: 7.22.15
|
||||
resolution: "@babel/helper-compilation-targets@npm:7.22.15"
|
||||
"@babel/helper-compilation-targets@npm:^7.22.15, @babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.23.6":
|
||||
version: 7.23.6
|
||||
resolution: "@babel/helper-compilation-targets@npm:7.23.6"
|
||||
dependencies:
|
||||
"@babel/compat-data": "npm:^7.22.9"
|
||||
"@babel/helper-validator-option": "npm:^7.22.15"
|
||||
browserslist: "npm:^4.21.9"
|
||||
"@babel/compat-data": "npm:^7.23.5"
|
||||
"@babel/helper-validator-option": "npm:^7.23.5"
|
||||
browserslist: "npm:^4.22.2"
|
||||
lru-cache: "npm:^5.1.1"
|
||||
semver: "npm:^6.3.1"
|
||||
checksum: 45b9286861296e890f674a3abb199efea14a962a27d9b8adeb44970a9fd5c54e73a9e342e8414d2851cf4f98d5994537352fbce7b05ade32e9849bbd327f9ff1
|
||||
checksum: ba38506d11185f48b79abf439462ece271d3eead1673dd8814519c8c903c708523428806f05f2ec5efd0c56e4e278698fac967e5a4b5ee842c32415da54bc6fa
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -342,14 +342,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helpers@npm:^7.23.5":
|
||||
version: 7.23.5
|
||||
resolution: "@babel/helpers@npm:7.23.5"
|
||||
"@babel/helpers@npm:^7.23.6":
|
||||
version: 7.23.6
|
||||
resolution: "@babel/helpers@npm:7.23.6"
|
||||
dependencies:
|
||||
"@babel/template": "npm:^7.22.15"
|
||||
"@babel/traverse": "npm:^7.23.5"
|
||||
"@babel/types": "npm:^7.23.5"
|
||||
checksum: a37e2728eb4378a4888e5d614e28de7dd79b55ac8acbecd0e5c761273e2a02a8f33b34b1932d9069db55417ace2937cbf8ec37c42f1030ce6d228857d7ccaa4f
|
||||
"@babel/traverse": "npm:^7.23.6"
|
||||
"@babel/types": "npm:^7.23.6"
|
||||
checksum: df1cf6607676ad36f52f652ec03536f2732d70aef5e76dba5c964e34d49f3c2d3dcf9fb3740db359f53071d74b64606a833d5ba156f79f437f71bfe06e2e7e19
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -364,12 +364,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.5":
|
||||
version: 7.23.5
|
||||
resolution: "@babel/parser@npm:7.23.5"
|
||||
"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.6":
|
||||
version: 7.23.6
|
||||
resolution: "@babel/parser@npm:7.23.6"
|
||||
bin:
|
||||
parser: ./bin/babel-parser.js
|
||||
checksum: 3356aa90d7bafb4e2c7310e7c2c3d443c4be4db74913f088d3d577a1eb914ea4188e05fd50a47ce907a27b755c4400c4e3cbeee73dbeb37761f6ca85954f5a20
|
||||
checksum: 6f76cd5ccae1fa9bcab3525b0865c6222e9c1d22f87abc69f28c5c7b2c8816a13361f5bd06bddbd5faf903f7320a8feba02545c981468acec45d12a03db7755e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -836,14 +836,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/plugin-transform-for-of@npm:^7.23.3":
|
||||
version: 7.23.3
|
||||
resolution: "@babel/plugin-transform-for-of@npm:7.23.3"
|
||||
"@babel/plugin-transform-for-of@npm:^7.23.6":
|
||||
version: 7.23.6
|
||||
resolution: "@babel/plugin-transform-for-of@npm:7.23.6"
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils": "npm:^7.22.5"
|
||||
"@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5"
|
||||
peerDependencies:
|
||||
"@babel/core": ^7.0.0-0
|
||||
checksum: 8a36202cfee312ba80e509c7c2131e6773524e572b4dc64a8ee95bd912634fdeb5ea91c6c7747ee30e03562d0f0d333f88ed7dbb929b36b60b8d74189189e12f
|
||||
checksum: 46681b6ab10f3ca2d961f50d4096b62ab5d551e1adad84e64be1ee23e72eb2f26a1e30e617e853c74f1349fffe4af68d33921a128543b6f24b6d46c09a3e2aec
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -1200,8 +1201,8 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@babel/plugin-transform-runtime@npm:^7.22.4":
|
||||
version: 7.23.4
|
||||
resolution: "@babel/plugin-transform-runtime@npm:7.23.4"
|
||||
version: 7.23.6
|
||||
resolution: "@babel/plugin-transform-runtime@npm:7.23.6"
|
||||
dependencies:
|
||||
"@babel/helper-module-imports": "npm:^7.22.15"
|
||||
"@babel/helper-plugin-utils": "npm:^7.22.5"
|
||||
@ -1211,7 +1212,7 @@ __metadata:
|
||||
semver: "npm:^6.3.1"
|
||||
peerDependencies:
|
||||
"@babel/core": ^7.0.0-0
|
||||
checksum: 6ac29012550cdd10b65ec43fef0c7f43904ec458c43d597f627d8f52807413e57ea94e3986dbace576d734e67c2d09be5e43e77c72567d18f8c4ac5e19844625
|
||||
checksum: 94a7ee92f073df53fd8bebf9ed391a95553716077da1c6c3a57f10f042358c938495d55e6b09b4b50544c01f03560c4770c17698e1c24817a15d3668e8231249
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -1333,11 +1334,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@babel/preset-env@npm:^7.11.0, @babel/preset-env@npm:^7.12.1, @babel/preset-env@npm:^7.22.4":
|
||||
version: 7.23.5
|
||||
resolution: "@babel/preset-env@npm:7.23.5"
|
||||
version: 7.23.6
|
||||
resolution: "@babel/preset-env@npm:7.23.6"
|
||||
dependencies:
|
||||
"@babel/compat-data": "npm:^7.23.5"
|
||||
"@babel/helper-compilation-targets": "npm:^7.22.15"
|
||||
"@babel/helper-compilation-targets": "npm:^7.23.6"
|
||||
"@babel/helper-plugin-utils": "npm:^7.22.5"
|
||||
"@babel/helper-validator-option": "npm:^7.23.5"
|
||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.23.3"
|
||||
@ -1377,7 +1378,7 @@ __metadata:
|
||||
"@babel/plugin-transform-dynamic-import": "npm:^7.23.4"
|
||||
"@babel/plugin-transform-exponentiation-operator": "npm:^7.23.3"
|
||||
"@babel/plugin-transform-export-namespace-from": "npm:^7.23.4"
|
||||
"@babel/plugin-transform-for-of": "npm:^7.23.3"
|
||||
"@babel/plugin-transform-for-of": "npm:^7.23.6"
|
||||
"@babel/plugin-transform-function-name": "npm:^7.23.3"
|
||||
"@babel/plugin-transform-json-strings": "npm:^7.23.4"
|
||||
"@babel/plugin-transform-literals": "npm:^7.23.3"
|
||||
@ -1418,7 +1419,7 @@ __metadata:
|
||||
semver: "npm:^6.3.1"
|
||||
peerDependencies:
|
||||
"@babel/core": ^7.0.0-0
|
||||
checksum: 2a0e1274dec045186e131c6433659b75492583290e8d41633c616f6bff829cb2e4b2f9a57f556283a54db3bd6aa697911e56a36f607911a29b731c445a5b5a06
|
||||
checksum: 5b24d179af52f082d04b9b98cc4777e37bf31a97cef5a91d8917e996dbd75f2f743c88c40f80744cb8529355bb674619d150c0260c32d834aa4067e21d0c8962
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -1483,11 +1484,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2":
|
||||
version: 7.23.5
|
||||
resolution: "@babel/runtime@npm:7.23.5"
|
||||
version: 7.23.6
|
||||
resolution: "@babel/runtime@npm:7.23.6"
|
||||
dependencies:
|
||||
regenerator-runtime: "npm:^0.14.0"
|
||||
checksum: ca679cc91bb7e424bc2db87bb58cc3b06ade916b9adb21fbbdc43e54cdaacb3eea201ceba2a0464b11d2eb65b9fe6a6ffcf4d7521fa52994f19be96f1af14788
|
||||
checksum: d886954e985ef8e421222f7a2848884d96a752e0020d3078b920dd104e672fdf23bcc6f51a44313a048796319f1ac9d09c2c88ec8cbb4e1f09174bcd3335b9ff
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -1502,32 +1503,32 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/traverse@npm:7, @babel/traverse@npm:^7.23.5":
|
||||
version: 7.23.5
|
||||
resolution: "@babel/traverse@npm:7.23.5"
|
||||
"@babel/traverse@npm:7, @babel/traverse@npm:^7.23.6":
|
||||
version: 7.23.6
|
||||
resolution: "@babel/traverse@npm:7.23.6"
|
||||
dependencies:
|
||||
"@babel/code-frame": "npm:^7.23.5"
|
||||
"@babel/generator": "npm:^7.23.5"
|
||||
"@babel/generator": "npm:^7.23.6"
|
||||
"@babel/helper-environment-visitor": "npm:^7.22.20"
|
||||
"@babel/helper-function-name": "npm:^7.23.0"
|
||||
"@babel/helper-hoist-variables": "npm:^7.22.5"
|
||||
"@babel/helper-split-export-declaration": "npm:^7.22.6"
|
||||
"@babel/parser": "npm:^7.23.5"
|
||||
"@babel/types": "npm:^7.23.5"
|
||||
debug: "npm:^4.1.0"
|
||||
"@babel/parser": "npm:^7.23.6"
|
||||
"@babel/types": "npm:^7.23.6"
|
||||
debug: "npm:^4.3.1"
|
||||
globals: "npm:^11.1.0"
|
||||
checksum: c5ea793080ca6719b0a1612198fd25e361cee1f3c14142d7a518d2a1eeb5c1d21f7eec1b26c20ea6e1ddd8ed12ab50b960ff95ffd25be353b6b46e1b54d6f825
|
||||
checksum: 5b4ebb94a00a7e1daf111e4b0b45a7998d5b7598637a14e75e855e88cc1b702789e09a958726b5d599a003be1e9032dbdfde4b88ea6061332228738950d5582d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.5, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3":
|
||||
version: 7.23.5
|
||||
resolution: "@babel/types@npm:7.23.5"
|
||||
"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.6, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3":
|
||||
version: 7.23.6
|
||||
resolution: "@babel/types@npm:7.23.6"
|
||||
dependencies:
|
||||
"@babel/helper-string-parser": "npm:^7.23.4"
|
||||
"@babel/helper-validator-identifier": "npm:^7.22.20"
|
||||
to-fast-properties: "npm:^2.0.0"
|
||||
checksum: 7dd5e2f59828ed046ad0b06b039df2524a8b728d204affb4fc08da2502b9dd3140b1356b5166515d229dc811539a8b70dcd4bc507e06d62a89f4091a38d0b0fb
|
||||
checksum: 42cefce8a68bd09bb5828b4764aa5586c53c60128ac2ac012e23858e1c179347a4aac9c66fc577994fbf57595227611c5ec8270bf0cfc94ff033bbfac0550b70
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -1726,9 +1727,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@eslint/eslintrc@npm:^2.1.3":
|
||||
version: 2.1.3
|
||||
resolution: "@eslint/eslintrc@npm:2.1.3"
|
||||
"@eslint/eslintrc@npm:^2.1.4":
|
||||
version: 2.1.4
|
||||
resolution: "@eslint/eslintrc@npm:2.1.4"
|
||||
dependencies:
|
||||
ajv: "npm:^6.12.4"
|
||||
debug: "npm:^4.3.2"
|
||||
@ -1739,14 +1740,14 @@ __metadata:
|
||||
js-yaml: "npm:^4.1.0"
|
||||
minimatch: "npm:^3.1.2"
|
||||
strip-json-comments: "npm:^3.1.1"
|
||||
checksum: f4103f4346126292eb15581c5a1d12bef03410fd3719dedbdb92e1f7031d46a5a2d60de8566790445d5d4b70b75ba050876799a11f5fff8265a91ee3fa77dab0
|
||||
checksum: 32f67052b81768ae876c84569ffd562491ec5a5091b0c1e1ca1e0f3c24fb42f804952fdd0a137873bc64303ba368a71ba079a6f691cee25beee9722d94cc8573
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@eslint/js@npm:8.54.0":
|
||||
version: 8.54.0
|
||||
resolution: "@eslint/js@npm:8.54.0"
|
||||
checksum: d61fb4a0be6af2d8cb290121c329697664a75d6255a29926d5454fb02aeb02b87112f67fdf218d10abac42f90c570ac366126751baefc5405d0e017ed0c946c5
|
||||
"@eslint/js@npm:8.55.0":
|
||||
version: 8.55.0
|
||||
resolution: "@eslint/js@npm:8.55.0"
|
||||
checksum: 88ab9fc57a651becd2b32ec40a3958db27fae133b1ae77bebd733aa5bbd00a92f325bb02f20ad680d31c731fa49b22f060a4777dd52eb3e27da013d940bd978d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -2435,7 +2436,7 @@ __metadata:
|
||||
stacktrace-js: "npm:^2.0.2"
|
||||
stringz: "npm:^2.1.0"
|
||||
stylelint: "npm:^15.10.1"
|
||||
stylelint-config-standard-scss: "npm:^11.0.0"
|
||||
stylelint-config-standard-scss: "npm:^12.0.0"
|
||||
substring-trie: "npm:^1.0.2"
|
||||
terser-webpack-plugin: "npm:^4.2.3"
|
||||
tesseract.js: "npm:^2.1.5"
|
||||
@ -3030,11 +3031,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@types/emoji-mart@npm:^3.0.9":
|
||||
version: 3.0.13
|
||||
resolution: "@types/emoji-mart@npm:3.0.13"
|
||||
version: 3.0.14
|
||||
resolution: "@types/emoji-mart@npm:3.0.14"
|
||||
dependencies:
|
||||
"@types/react": "npm:*"
|
||||
checksum: 840f920c3242e1d274f0102e67cb2d00434e1fd370e0bcc8983b43b6b62322b01e3ddcd5fb078c60883e613530a7c70b8c40060624897543cd4da9441ca81486
|
||||
checksum: 23ded65fce9b3355fbe903d3971cb67cc827a5d587464bb7e3f349615527ef4a9197b3bb59fa84c4391d1b901e7f200f686a7fc83f649ae2a51a0fb948cbadfb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -3178,12 +3179,12 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@types/jest@npm:^29.5.2":
|
||||
version: 29.5.10
|
||||
resolution: "@types/jest@npm:29.5.10"
|
||||
version: 29.5.11
|
||||
resolution: "@types/jest@npm:29.5.11"
|
||||
dependencies:
|
||||
expect: "npm:^29.0.0"
|
||||
pretty-format: "npm:^29.0.0"
|
||||
checksum: b46171d59d12a5f69bbe710f65eaf59a8073337c6b4a67dff8158575caec53f1c61f8a7d645b34d6ac3c4ea398acd30f0c5d1c4a131c0c918798019264a3397d
|
||||
checksum: 524a3394845214581278bf4d75055927261fbeac7e1a89cd621bd0636da37d265fe0a85eac58b5778758faad1cbd7c7c361dfc190c78ebde03a91cce33463261
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -3377,11 +3378,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@types/react-helmet@npm:^6.1.6":
|
||||
version: 6.1.9
|
||||
resolution: "@types/react-helmet@npm:6.1.9"
|
||||
version: 6.1.11
|
||||
resolution: "@types/react-helmet@npm:6.1.11"
|
||||
dependencies:
|
||||
"@types/react": "npm:*"
|
||||
checksum: d1823582903d6e70f1f447c7bec9e844b6f85f5de84cbcde5c8bbeecc064db1394c786ed9b9ded30544afe5c91e57c7e8105171df1643998f64c0aeab9f7f2aa
|
||||
checksum: f7b3bb2151d992a108ae46fed876fb9c8119108397d9a01d150c5642782997542c8b3c52e742b56e8689b7dbfa62ca9cfc76aa7e05dec4e60c652f7ef53fa783
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -3498,13 +3499,13 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7":
|
||||
version: 18.2.41
|
||||
resolution: "@types/react@npm:18.2.41"
|
||||
version: 18.2.43
|
||||
resolution: "@types/react@npm:18.2.43"
|
||||
dependencies:
|
||||
"@types/prop-types": "npm:*"
|
||||
"@types/scheduler": "npm:*"
|
||||
csstype: "npm:^3.0.2"
|
||||
checksum: 5cc72491ce8be95e7bbedd8bf039ca971772ecd22d989feb045af7e73247c7e6cff25a2f1c2200be461fb2f6b5aacef739e1ba9fd83c744209dfd3ce8aa75afe
|
||||
checksum: 10477a50fbd3c0cc5b8a2ade679f442717f68fb27c8460b2aa1d3256cd18c48f742bbe5b9ee37a8c4c5f832ffa37b3a23c09fd96dd880a8e3182d8929c05e803
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -3685,14 +3686,14 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/eslint-plugin@npm:^6.0.0":
|
||||
version: 6.11.0
|
||||
resolution: "@typescript-eslint/eslint-plugin@npm:6.11.0"
|
||||
version: 6.13.2
|
||||
resolution: "@typescript-eslint/eslint-plugin@npm:6.13.2"
|
||||
dependencies:
|
||||
"@eslint-community/regexpp": "npm:^4.5.1"
|
||||
"@typescript-eslint/scope-manager": "npm:6.11.0"
|
||||
"@typescript-eslint/type-utils": "npm:6.11.0"
|
||||
"@typescript-eslint/utils": "npm:6.11.0"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.11.0"
|
||||
"@typescript-eslint/scope-manager": "npm:6.13.2"
|
||||
"@typescript-eslint/type-utils": "npm:6.13.2"
|
||||
"@typescript-eslint/utils": "npm:6.13.2"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.13.2"
|
||||
debug: "npm:^4.3.4"
|
||||
graphemer: "npm:^1.4.0"
|
||||
ignore: "npm:^5.2.4"
|
||||
@ -3705,44 +3706,44 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 6645aa09b9d51c5e3ea781eaf74da75b94f83f3e2d7b3dd988d5ce7eb82dd87e3509471cf2ee8c6b2428d907df5f1b02f29dbd04f54c2653f9566c8c4ce98009
|
||||
checksum: 531a4406d872738d165c6a66cb26e976523c94053b022a8210dc9fd10e91b79b705bc0fcc77145e9744e4108b53bdba55e02a10dc17757b22be92aff57849384
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/parser@npm:^6.0.0":
|
||||
version: 6.11.0
|
||||
resolution: "@typescript-eslint/parser@npm:6.11.0"
|
||||
version: 6.13.2
|
||||
resolution: "@typescript-eslint/parser@npm:6.13.2"
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager": "npm:6.11.0"
|
||||
"@typescript-eslint/types": "npm:6.11.0"
|
||||
"@typescript-eslint/typescript-estree": "npm:6.11.0"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.11.0"
|
||||
"@typescript-eslint/scope-manager": "npm:6.13.2"
|
||||
"@typescript-eslint/types": "npm:6.13.2"
|
||||
"@typescript-eslint/typescript-estree": "npm:6.13.2"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.13.2"
|
||||
debug: "npm:^4.3.4"
|
||||
peerDependencies:
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: e7caeb20069102e21f468fc0dbe7ff6fb6b1efa9e72f4c9f39d4a865ed0633f39130b593ef9ae8f394ca1d70563e15410faf30a482a97809951eaac6ed3a67da
|
||||
checksum: 2c62b8cd8a37eb2ea59cd00e559f51a9f57af746e2040e872af3c58ddd3f4071ad7b7009789bdeb0e0d4ee0343bfe96ee77288020f3ae22d08e1674203f5e156
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/scope-manager@npm:6.11.0":
|
||||
version: 6.11.0
|
||||
resolution: "@typescript-eslint/scope-manager@npm:6.11.0"
|
||||
"@typescript-eslint/scope-manager@npm:6.13.2":
|
||||
version: 6.13.2
|
||||
resolution: "@typescript-eslint/scope-manager@npm:6.13.2"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": "npm:6.11.0"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.11.0"
|
||||
checksum: d8999e2d1a4cbde8a79df5e3ec416f0e3db9532d39f2f4bb5a0ebdf954ae75c183d3277579ba05268fe2c88e88ef87f0fa12f02bb8d95d9e67d92e411241f3a3
|
||||
"@typescript-eslint/types": "npm:6.13.2"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.13.2"
|
||||
checksum: 9b159e5bb10dfb5953e71488200b4126378fc7e987ce7d90946aea9ec40cd66c7ada92399657c5d9794189b764ca6f4eb38a8dcb9e4c5aa50ab6000a39636b9c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/type-utils@npm:6.11.0":
|
||||
version: 6.11.0
|
||||
resolution: "@typescript-eslint/type-utils@npm:6.11.0"
|
||||
"@typescript-eslint/type-utils@npm:6.13.2":
|
||||
version: 6.13.2
|
||||
resolution: "@typescript-eslint/type-utils@npm:6.13.2"
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree": "npm:6.11.0"
|
||||
"@typescript-eslint/utils": "npm:6.11.0"
|
||||
"@typescript-eslint/typescript-estree": "npm:6.13.2"
|
||||
"@typescript-eslint/utils": "npm:6.13.2"
|
||||
debug: "npm:^4.3.4"
|
||||
ts-api-utils: "npm:^1.0.1"
|
||||
peerDependencies:
|
||||
@ -3750,23 +3751,23 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: ff68f2e052b8d688f1dc1a0050746704c8e0ab6263b47f1f52da73a7d251678e4950af23a95e1cd8e3fcea2457e6e5294ddbe01d29dafa2fdfb5b11ed9452a3f
|
||||
checksum: 1ca97c78abdf479aea0c54e869fda2ae2f69de1974cc063062ce7b5b16c7fdf497ea15c50a29dd5941ea1b6b77e8f1213a5c272a747e334ac69ede083f327468
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/types@npm:6.11.0":
|
||||
version: 6.11.0
|
||||
resolution: "@typescript-eslint/types@npm:6.11.0"
|
||||
checksum: 23182813db39a5e9b9bcc1e85306c953f7b8b22d3885e41fcac0bd725c170fbcb70f4ce55633678cc5921dcf062fa0e55635eb39480c118a4411a00354820223
|
||||
"@typescript-eslint/types@npm:6.13.2":
|
||||
version: 6.13.2
|
||||
resolution: "@typescript-eslint/types@npm:6.13.2"
|
||||
checksum: 029918ca5b1442bb4bc435773504ce32191e2c3e2fde8d4176bb6513f03e3dfa2aa9724b2d22b1640656d666b97f7a7ebfeaf67b881d5e07250828fa83e3ebe8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/typescript-estree@npm:6.11.0":
|
||||
version: 6.11.0
|
||||
resolution: "@typescript-eslint/typescript-estree@npm:6.11.0"
|
||||
"@typescript-eslint/typescript-estree@npm:6.13.2":
|
||||
version: 6.13.2
|
||||
resolution: "@typescript-eslint/typescript-estree@npm:6.13.2"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": "npm:6.11.0"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.11.0"
|
||||
"@typescript-eslint/types": "npm:6.13.2"
|
||||
"@typescript-eslint/visitor-keys": "npm:6.13.2"
|
||||
debug: "npm:^4.3.4"
|
||||
globby: "npm:^11.1.0"
|
||||
is-glob: "npm:^4.0.3"
|
||||
@ -3775,34 +3776,34 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 3e183e554e1bc74f065da3015f7137eb40c262f989c547701b1e3f4f20134e574e56b749288cd00d77b9d1ddb705546613c2457661ffc63b6060ffa97ba3aac8
|
||||
checksum: 1c4c59dce0c51fdfee34d9f418e64fe28e3ec1a97661efc8a3d2780bdff36aff38de9090d356a968f394fa6d4e9c058936ce9cd260d4c44a52761ecd74915bce
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/utils@npm:6.11.0, @typescript-eslint/utils@npm:^6.5.0":
|
||||
version: 6.11.0
|
||||
resolution: "@typescript-eslint/utils@npm:6.11.0"
|
||||
"@typescript-eslint/utils@npm:6.13.2, @typescript-eslint/utils@npm:^6.5.0":
|
||||
version: 6.13.2
|
||||
resolution: "@typescript-eslint/utils@npm:6.13.2"
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils": "npm:^4.4.0"
|
||||
"@types/json-schema": "npm:^7.0.12"
|
||||
"@types/semver": "npm:^7.5.0"
|
||||
"@typescript-eslint/scope-manager": "npm:6.11.0"
|
||||
"@typescript-eslint/types": "npm:6.11.0"
|
||||
"@typescript-eslint/typescript-estree": "npm:6.11.0"
|
||||
"@typescript-eslint/scope-manager": "npm:6.13.2"
|
||||
"@typescript-eslint/types": "npm:6.13.2"
|
||||
"@typescript-eslint/typescript-estree": "npm:6.13.2"
|
||||
semver: "npm:^7.5.4"
|
||||
peerDependencies:
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
checksum: c91eb4578607959acc2b43ddc791571682e45601a19b25d5d120786ed4af607656f83c5c1fa71972e549ddfb5542acf2f7d443ae93b32ee28192c22c106b8883
|
||||
checksum: 84969be91e7949868eaaa289288c9d71927f0e427b572501b0991d8d62b40a4234f7287c35b35d276ccbb53e9ea5457b8250fcf4941e60e6b9ba4065fbfba416
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/visitor-keys@npm:6.11.0":
|
||||
version: 6.11.0
|
||||
resolution: "@typescript-eslint/visitor-keys@npm:6.11.0"
|
||||
"@typescript-eslint/visitor-keys@npm:6.13.2":
|
||||
version: 6.13.2
|
||||
resolution: "@typescript-eslint/visitor-keys@npm:6.13.2"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": "npm:6.11.0"
|
||||
"@typescript-eslint/types": "npm:6.13.2"
|
||||
eslint-visitor-keys: "npm:^3.4.1"
|
||||
checksum: 5f48329422b7f286196661d39e93e9defd7c5cf80e6c84c8d03459853f5d9f86a5e91c5e80ea572dcdb907ebbe503bbcc77aeb8b468c294b2aa7b3ccfc81cb88
|
||||
checksum: c173bc1fcc42c3075a5ee094e7f3bf0279d98315c25ff49e20d02d79022b1d0402accfa113b070afb4d52a6f6d180594b67baa8b6a784eabdf82b54dd1ff454c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -5180,17 +5181,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"browserslist@npm:^4.0.0, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.21.9, browserslist@npm:^4.22.1":
|
||||
version: 4.22.1
|
||||
resolution: "browserslist@npm:4.22.1"
|
||||
"browserslist@npm:^4.0.0, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.22.1, browserslist@npm:^4.22.2":
|
||||
version: 4.22.2
|
||||
resolution: "browserslist@npm:4.22.2"
|
||||
dependencies:
|
||||
caniuse-lite: "npm:^1.0.30001541"
|
||||
electron-to-chromium: "npm:^1.4.535"
|
||||
node-releases: "npm:^2.0.13"
|
||||
caniuse-lite: "npm:^1.0.30001565"
|
||||
electron-to-chromium: "npm:^1.4.601"
|
||||
node-releases: "npm:^2.0.14"
|
||||
update-browserslist-db: "npm:^1.0.13"
|
||||
bin:
|
||||
browserslist: cli.js
|
||||
checksum: 6810f2d63f171d0b7b8d38cf091708e00cb31525501810a507839607839320d66e657293b0aa3d7f051ecbc025cb07390a90c037682c1d05d12604991e41050b
|
||||
checksum: 2a331aab90503130043ca41dd5d281fa1e89d5e076d07a2d75e76bf4d693bd56e73d5abcd8c4f39119da6328d450578c216cf1cd5c99b82d8a90a2ae6271b465
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -5418,10 +5419,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001538, caniuse-lite@npm:^1.0.30001541":
|
||||
version: 1.0.30001561
|
||||
resolution: "caniuse-lite@npm:1.0.30001561"
|
||||
checksum: 6e84c84026fee53edbdbb5aded7a04a036aae4c2e367cf6bdc90c6783a591e2fdcfcdebcc4e774aca61092e542a61200c8c16b06659396492426033c4dbcc618
|
||||
"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001538, caniuse-lite@npm:^1.0.30001565":
|
||||
version: 1.0.30001568
|
||||
resolution: "caniuse-lite@npm:1.0.30001568"
|
||||
checksum: 13f01e5a2481134bd61cf565ce9fecbd8e107902927a0dcf534230a92191a81f1715792170f5f39719c767c3a96aa6df9917a8d5601f15bbd5e4041a8cfecc99
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -6423,7 +6424,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.2, debug@npm:^4.3.4":
|
||||
"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4":
|
||||
version: 4.3.4
|
||||
resolution: "debug@npm:4.3.4"
|
||||
dependencies:
|
||||
@ -6965,10 +6966,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"electron-to-chromium@npm:^1.4.535":
|
||||
version: 1.4.576
|
||||
resolution: "electron-to-chromium@npm:1.4.576"
|
||||
checksum: b0b9e7ba803bf93ffac9cb830ed2b0e0eb07f20066127065f9ab9e08e4e6a5812040e03d76f6ee9bc59e03fb938fd414e83d4883b29111303e9e88633cf2dce4
|
||||
"electron-to-chromium@npm:^1.4.601":
|
||||
version: 1.4.609
|
||||
resolution: "electron-to-chromium@npm:1.4.609"
|
||||
checksum: 9675a79388acbaff5953a4c61589af7da93e0d1f9d6a3b284c7630f10126eb0998557b07448514214d5a3d19025310039b55f405ab701b1253130fc94907f743
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -7323,13 +7324,13 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"eslint-config-prettier@npm:^9.0.0":
|
||||
version: 9.0.0
|
||||
resolution: "eslint-config-prettier@npm:9.0.0"
|
||||
version: 9.1.0
|
||||
resolution: "eslint-config-prettier@npm:9.1.0"
|
||||
peerDependencies:
|
||||
eslint: ">=7.0.0"
|
||||
bin:
|
||||
eslint-config-prettier: bin/cli.js
|
||||
checksum: bc1f661915845c631824178942e5d02f858fe6d0ea796f0050d63e0f681927b92696e81139dd04714c08c3e7de580fd079c66162e40070155ba79eaee78ab5d0
|
||||
checksum: 6d332694b36bc9ac6fdb18d3ca2f6ac42afa2ad61f0493e89226950a7091e38981b66bac2b47ba39d15b73fff2cd32c78b850a9cf9eed9ca9a96bfb2f3a2f10d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -7565,13 +7566,13 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"eslint@npm:^8.41.0":
|
||||
version: 8.54.0
|
||||
resolution: "eslint@npm:8.54.0"
|
||||
version: 8.55.0
|
||||
resolution: "eslint@npm:8.55.0"
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils": "npm:^4.2.0"
|
||||
"@eslint-community/regexpp": "npm:^4.6.1"
|
||||
"@eslint/eslintrc": "npm:^2.1.3"
|
||||
"@eslint/js": "npm:8.54.0"
|
||||
"@eslint/eslintrc": "npm:^2.1.4"
|
||||
"@eslint/js": "npm:8.55.0"
|
||||
"@humanwhocodes/config-array": "npm:^0.11.13"
|
||||
"@humanwhocodes/module-importer": "npm:^1.0.1"
|
||||
"@nodelib/fs.walk": "npm:^1.2.8"
|
||||
@ -7608,7 +7609,7 @@ __metadata:
|
||||
text-table: "npm:^0.2.0"
|
||||
bin:
|
||||
eslint: bin/eslint.js
|
||||
checksum: 4f205f832bdbd0218cde374b067791f4f76d7abe8de86b2dc849c273899051126d912ebf71531ee49b8eeaa22cad77febdc8f2876698dc2a76e84a8cb976af22
|
||||
checksum: d28c0b60f19bb7d355cb8393e77b018c8f548dba3f820b799c89bb2e0c436ee26084e700c5e57e1e97e7972ec93065277849141b82e7b0c0d02c2dc1e553a2a1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -11954,10 +11955,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"node-releases@npm:^2.0.13":
|
||||
version: 2.0.13
|
||||
resolution: "node-releases@npm:2.0.13"
|
||||
checksum: 2fb44bf70fc949d27f3a48a7fd1a9d1d603ddad4ccd091f26b3fb8b1da976605d919330d7388ccd55ca2ade0dc8b2e12841ba19ef249c8bb29bf82532d401af7
|
||||
"node-releases@npm:^2.0.14":
|
||||
version: 2.0.14
|
||||
resolution: "node-releases@npm:2.0.14"
|
||||
checksum: 199fc93773ae70ec9969bc6d5ac5b2bbd6eb986ed1907d751f411fef3ede0e4bfdb45ceb43711f8078bea237b6036db8b1bf208f6ff2b70c7d615afd157f3ab9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -13336,11 +13337,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"prettier@npm:^3.0.0":
|
||||
version: 3.1.0
|
||||
resolution: "prettier@npm:3.1.0"
|
||||
version: 3.1.1
|
||||
resolution: "prettier@npm:3.1.1"
|
||||
bin:
|
||||
prettier: bin/prettier.cjs
|
||||
checksum: a45ea70aa97fde162ea4c4aba3dfc7859aa6a732a1db34458d9535dc3c2c16d3bc3fb5689e6cd76aa835562555303b02d9449fd2e15af3b73c8053557e25c5b6
|
||||
checksum: facc944ba20e194ff4db765e830ffbcb642803381f0d2033ed397e79904fa4ccc877dc25ad68f42d36985c01d051c990ca1b905fb83d2d7d65fe69e4386fa1a3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -15781,62 +15782,62 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"stylelint-config-recommended-scss@npm:^13.1.0":
|
||||
version: 13.1.0
|
||||
resolution: "stylelint-config-recommended-scss@npm:13.1.0"
|
||||
"stylelint-config-recommended-scss@npm:^14.0.0":
|
||||
version: 14.0.0
|
||||
resolution: "stylelint-config-recommended-scss@npm:14.0.0"
|
||||
dependencies:
|
||||
postcss-scss: "npm:^4.0.9"
|
||||
stylelint-config-recommended: "npm:^13.0.0"
|
||||
stylelint-scss: "npm:^5.3.0"
|
||||
stylelint-config-recommended: "npm:^14.0.0"
|
||||
stylelint-scss: "npm:^6.0.0"
|
||||
peerDependencies:
|
||||
postcss: ^8.3.3
|
||||
stylelint: ^15.10.0
|
||||
stylelint: ^16.0.2
|
||||
peerDependenciesMeta:
|
||||
postcss:
|
||||
optional: true
|
||||
checksum: e07d0172c7936b4f644138e4129df2f187d297f1f96ce5865ab21ccd1c22caf94220f7caf9d6985e93e515de4c0356f6cb9c924d00df2eee5b3bc237f7e5bb48
|
||||
checksum: 9ddc92e7a5fa131b41cee1ab1f69251934ca35c0e2803dc613329cdead7b8b27d8457048a63db29f61a1442e7cdef14207f88a3abce00ec53fdefe0d604f7de3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"stylelint-config-recommended@npm:^13.0.0":
|
||||
version: 13.0.0
|
||||
resolution: "stylelint-config-recommended@npm:13.0.0"
|
||||
"stylelint-config-recommended@npm:^14.0.0":
|
||||
version: 14.0.0
|
||||
resolution: "stylelint-config-recommended@npm:14.0.0"
|
||||
peerDependencies:
|
||||
stylelint: ^15.10.0
|
||||
checksum: 80420a1ab616e8637b66223f88c597388990d9991cd6a28b8372049b83329d893412f83029bb253a82b52387e497b62e042bc898064a2f22574b0d8921f01dd2
|
||||
stylelint: ^16.0.0
|
||||
checksum: 4ad15c36e8c03291aa7bbe4b672ebfb0f46ab698e7580a0da8d29644046d102d7f31dbf00a2a6eab94b565c390c6fb0d5d528737b83ac3acf6dc2ef085a90b11
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"stylelint-config-standard-scss@npm:^11.0.0":
|
||||
version: 11.1.0
|
||||
resolution: "stylelint-config-standard-scss@npm:11.1.0"
|
||||
"stylelint-config-standard-scss@npm:^12.0.0":
|
||||
version: 12.0.0
|
||||
resolution: "stylelint-config-standard-scss@npm:12.0.0"
|
||||
dependencies:
|
||||
stylelint-config-recommended-scss: "npm:^13.1.0"
|
||||
stylelint-config-standard: "npm:^34.0.0"
|
||||
stylelint-config-recommended-scss: "npm:^14.0.0"
|
||||
stylelint-config-standard: "npm:^35.0.0"
|
||||
peerDependencies:
|
||||
postcss: ^8.3.3
|
||||
stylelint: ^15.10.0
|
||||
stylelint: ^16.0.2
|
||||
peerDependenciesMeta:
|
||||
postcss:
|
||||
optional: true
|
||||
checksum: 22d00e75c1eacce9883fd48c3d67b1107b0e39d7d86e9f73deaa332b11c39a9678c947ae2c34cd5159a452ec9a857694ed58b5a851087480d3c9a66dab629415
|
||||
checksum: 7f3ccfb4175f9c50b69d30ca35a97887008c5ba493dbe7d5bce0b57b1eafd21b268177b82404368e7780600077cba784f98e1046671724be3b29a00c6a7913a4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"stylelint-config-standard@npm:^34.0.0":
|
||||
version: 34.0.0
|
||||
resolution: "stylelint-config-standard@npm:34.0.0"
|
||||
"stylelint-config-standard@npm:^35.0.0":
|
||||
version: 35.0.0
|
||||
resolution: "stylelint-config-standard@npm:35.0.0"
|
||||
dependencies:
|
||||
stylelint-config-recommended: "npm:^13.0.0"
|
||||
stylelint-config-recommended: "npm:^14.0.0"
|
||||
peerDependencies:
|
||||
stylelint: ^15.10.0
|
||||
checksum: 2494468af2359490b6ebb9723d9653f9e31db3a0772b8d9f0e081018b0079ef84ae6f90dcf94c879a3c374f299e334941e3dcff1afb603c2284d3103085b71fb
|
||||
stylelint: ^16.0.0
|
||||
checksum: 791fbc26cc3029ce3c2423a643e903545b5e4cd605251b18f0ce790bac6fbaaf380469845c1ff45f4e320126af9f8a9dc1ca85d0df9274277ae60da91e81895b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"stylelint-scss@npm:^5.3.0":
|
||||
version: 5.3.1
|
||||
resolution: "stylelint-scss@npm:5.3.1"
|
||||
"stylelint-scss@npm:^6.0.0":
|
||||
version: 6.0.0
|
||||
resolution: "stylelint-scss@npm:6.0.0"
|
||||
dependencies:
|
||||
known-css-properties: "npm:^0.29.0"
|
||||
postcss-media-query-parser: "npm:^0.2.3"
|
||||
@ -15844,8 +15845,8 @@ __metadata:
|
||||
postcss-selector-parser: "npm:^6.0.13"
|
||||
postcss-value-parser: "npm:^4.2.0"
|
||||
peerDependencies:
|
||||
stylelint: ^14.5.1 || ^15.0.0
|
||||
checksum: 5dfed5f9ac9812cd2ac6ef0272c720dee0326aaaee2998315a23bdcd71b8f04427f29cad634793eea2b45984182e20f03e90d43501e8e4d55bc956f80e2de477
|
||||
stylelint: ^16.0.2
|
||||
checksum: f5e971d19ef6879ae5c18cb8fba8033fe7928f241178e6afd80357cc080d2feddfd6f7fe564aaa696008aa10345df5885d9a4471c926b3e266088e015927782e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -16519,22 +16520,22 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"typescript@npm:5, typescript@npm:^5.0.4":
|
||||
version: 5.3.2
|
||||
resolution: "typescript@npm:5.3.2"
|
||||
version: 5.3.3
|
||||
resolution: "typescript@npm:5.3.3"
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: d7dbe1fbe19039e36a65468ea64b5d338c976550394ba576b7af9c68ed40c0bc5d12ecce390e4b94b287a09a71bd3229f19c2d5680611f35b7c53a3898791159
|
||||
checksum: e33cef99d82573624fc0f854a2980322714986bc35b9cb4d1ce736ed182aeab78e2cb32b385efa493b2a976ef52c53e20d6c6918312353a91850e2b76f1ea44f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@patch:typescript@npm%3A5#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A^5.0.4#optional!builtin<compat/typescript>":
|
||||
version: 5.3.2
|
||||
resolution: "typescript@patch:typescript@npm%3A5.3.2#optional!builtin<compat/typescript>::version=5.3.2&hash=e012d7"
|
||||
version: 5.3.3
|
||||
resolution: "typescript@patch:typescript@npm%3A5.3.3#optional!builtin<compat/typescript>::version=5.3.3&hash=e012d7"
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: 73c8bad74e732d93211c9d77f28b03307e2f5fc6a0afc73f4b783261ab567686a16d6ae958bdaef383a00be1b0b8c8b6741dd6ca3d13af4963fa7e47456d49c7
|
||||
checksum: 1d0a5f4ce496c42caa9a30e659c467c5686eae15d54b027ee7866744952547f1be1262f2d40de911618c242b510029d51d43ff605dba8fb740ec85ca2d3f9500
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -17762,8 +17763,8 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.14.2":
|
||||
version: 8.14.2
|
||||
resolution: "ws@npm:8.14.2"
|
||||
version: 8.15.0
|
||||
resolution: "ws@npm:8.15.0"
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
utf-8-validate: ">=5.0.2"
|
||||
@ -17772,7 +17773,7 @@ __metadata:
|
||||
optional: true
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
checksum: 35b4c2da048b8015c797fd14bcb5a5766216ce65c8a5965616a5440ca7b6c3681ee3cbd0ea0c184a59975556e9d58f2002abf8485a14d11d3371770811050a16
|
||||
checksum: b778a405b2589ffbf549323e2f404f1f72e372a049d332d2f0b1f33057e9fbb14a05aa474cb156e4584b418cd95edf4297c0ca5263d6519e8009064bf8e0b80d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user