From a8a5c6514f6676155661846398fa0398e7355f5d Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 12 Dec 2023 09:29:46 +0100 Subject: [PATCH 01/28] Fix `LinkCrawlWorker` error when encountering empty OEmbed response (#28268) --- app/services/fetch_oembed_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/fetch_oembed_service.rb b/app/services/fetch_oembed_service.rb index 1ae592238..dc84b16b6 100644 --- a/app/services/fetch_oembed_service.rb +++ b/app/services/fetch_oembed_service.rb @@ -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 From 89a496b42ff94536fc4aa1a8f41651f8bfd52944 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 12 Dec 2023 11:39:21 +0100 Subject: [PATCH 02/28] Fix status edits not always being streamed to mentioned users (#28324) --- app/services/fan_out_on_write_service.rb | 13 +++++++++++ .../services/fan_out_on_write_service_spec.rb | 22 ++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb index f2a79c9fc..50b414bc5 100644 --- a/app/services/fan_out_on_write_service.rb +++ b/app/services/fan_out_on_write_service.rb @@ -74,6 +74,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 @@ -162,4 +171,8 @@ class FanOutOnWriteService < BaseService def broadcastable? @status.public_visibility? && !@status.reblog? && !@account.silenced? end + + def subscribed_to_streaming_api?(account_id) + redis.exists?("subscribed:timeline:#{account_id}") || redis.exists?("subscribed:timeline:#{account_id}:notifications") + end end diff --git a/spec/services/fan_out_on_write_service_spec.rb b/spec/services/fan_out_on_write_service_spec.rb index 3b554f9ea..f657f298d 100644 --- a/spec/services/fan_out_on_write_service_spec.rb +++ b/spec/services/fan_out_on_write_service_spec.rb @@ -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 From 8078520c762e15aedbdf11a50d9c033e7c1f8271 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:40:54 +0100 Subject: [PATCH 03/28] Update dependency oj to v3.16.3 (#28332) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 4b39692d0..405c31ae1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -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) From 14e64bc880ca1e301c6fdd69cb880a9c615efe6d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 12:45:10 +0100 Subject: [PATCH 04/28] New Crowdin Translations (automated) (#28334) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/zh-TW.json | 36 +++++++++++----------- config/locales/activerecord.zh-TW.yml | 2 +- config/locales/doorkeeper.zh-TW.yml | 2 +- config/locales/simple_form.zh-TW.yml | 2 +- config/locales/zh-TW.yml | 10 +++--- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index e6dd008bf..4fb5a12de 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -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} 的訂閱語言", diff --git a/config/locales/activerecord.zh-TW.yml b/config/locales/activerecord.zh-TW.yml index 792a9dbb2..24609332c 100644 --- a/config/locales/activerecord.zh-TW.yml +++ b/config/locales/activerecord.zh-TW.yml @@ -28,7 +28,7 @@ zh-TW: doorkeeper/application: attributes: website: - invalid: 不是有效的 URL + invalid: 不是有效的網址 import: attributes: data: diff --git a/config/locales/doorkeeper.zh-TW.yml b/config/locales/doorkeeper.zh-TW.yml index c0d42ec7b..8ceaf36f3 100644 --- a/config/locales/doorkeeper.zh-TW.yml +++ b/config/locales/doorkeeper.zh-TW.yml @@ -29,7 +29,7 @@ zh-TW: edit: title: 編輯應用程式 form: - error: 唉呦!請看看表單以排查錯誤 + error: 糟糕!請檢查表單以排查錯誤 help: native_redirect_uri: 請使用 %{native_redirect_uri} 作本站測試 redirect_uri: 每行輸入一個 URI diff --git a/config/locales/simple_form.zh-TW.yml b/config/locales/simple_form.zh-TW.yml index 13b2ad30a..a31ad5eb1 100644 --- a/config/locales/simple_form.zh-TW.yml +++ b/config/locales/simple_form.zh-TW.yml @@ -16,7 +16,7 @@ zh-TW: acct: 指定要移動至的帳號的「使用者名稱@網域名稱」 account_warning_preset: text: 您可使用嘟文語法,例如網址、「#」標籤與提及功能 - title: 可選的。不會向收件者顯示 + title: 可選。不會向收件者顯示 admin_account_action: include_statuses: 使用者可看到導致檢舉或警告的嘟文 send_email_notification: 使用者將收到帳號發生之事情的解釋 diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 755ac3403..e17228da3 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -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: 由於您是由外部系統登入,所以不能設定密碼與電子郵件。 From ca51e412394cc10460ff121125262b8593e60729 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 12:45:39 +0100 Subject: [PATCH 05/28] Update dependency stylelint-config-standard-scss to v12 (#28333) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 62 ++++++++++++++++++++++++++-------------------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index 500d6d2cd..37139254c 100644 --- a/package.json +++ b/package.json @@ -202,7 +202,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" diff --git a/yarn.lock b/yarn.lock index 71f1ad160..7903ecc5c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2433,7 +2433,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" @@ -15758,62 +15758,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" @@ -15821,8 +15821,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 From 4a7395d989e40c3bd4ef18173aa5ea850c8ddcdd Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Tue, 12 Dec 2023 06:56:39 -0500 Subject: [PATCH 06/28] Add `migrator_version` method to CLI maintenance script (#28323) --- lib/mastodon/cli/maintenance.rb | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/lib/mastodon/cli/maintenance.rb b/lib/mastodon/cli/maintenance.rb index 553ca056d..43fd7fab3 100644 --- a/lib/mastodon/cli/maintenance.rb +++ b/lib/mastodon/cli/maintenance.rb @@ -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 @@ -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 @@ -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,6 +707,10 @@ 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 From 393e85164980b945ad9bdfda8e906e128f5700a3 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 12 Dec 2023 13:00:23 +0100 Subject: [PATCH 07/28] Change Rails' cache format to 7.0 (#27393) --- config/application.rb | 7 ------- 1 file changed, 7 deletions(-) diff --git a/config/application.rb b/config/application.rb index b6426516e..990a89383 100644 --- a/config/application.rb +++ b/config/application.rb @@ -63,13 +63,6 @@ module Mastodon # Initialize configuration defaults for originally generated Rails version. config.load_defaults 7.0 - # TODO: Release a version which uses the 7.0 defaults as specified above, - # but preserves the 6.1 cache format as set below. In a subsequent change, - # remove this line setting to 6.1 cache format, and then release another version. - # https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#new-activesupport-cache-serialization-format - # https://github.com/mastodon/mastodon/pull/24241#discussion_r1162890242 - config.active_support.cache_format_version = 6.1 - # Please, add to the `ignore` list any other `lib` subdirectories that do # not contain `.rb` files, or that should not be reloaded or eager loaded. # Common ones are `templates`, `generators`, or `middleware`, for example. From f37c93f3d76bcc83f20b83cfc121ff5a08d43706 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 12 Dec 2023 13:01:08 +0100 Subject: [PATCH 08/28] Change cookie rotator to use SHA1 digest for new cookies (#27392) --- config/initializers/cookie_rotator.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/config/initializers/cookie_rotator.rb b/config/initializers/cookie_rotator.rb index b829b1a90..ccc2c6b21 100644 --- a/config/initializers/cookie_rotator.rb +++ b/config/initializers/cookie_rotator.rb @@ -1,9 +1,6 @@ # frozen_string_literal: true -# TODO: Remove after 4.2.0 -Rails.application.configure do - config.active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA1 -end +# TODO: remove this file some time after 4.3.0 Rails.application.config.after_initialize do Rails.application.config.action_dispatch.cookies_rotations.tap do |cookies| @@ -12,9 +9,8 @@ Rails.application.config.after_initialize do secret_key_base = Rails.application.secret_key_base - # TODO: Switch to SHA1 after 4.2.0 key_generator = ActiveSupport::KeyGenerator.new( - secret_key_base, iterations: 1000, hash_digest_class: OpenSSL::Digest::SHA256 + secret_key_base, iterations: 1000, hash_digest_class: OpenSSL::Digest::SHA1 ) key_len = ActiveSupport::MessageEncryptor.key_len From db3220ff77b828870fcb21e0b50a12da0e19b2e6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 15:18:30 +0100 Subject: [PATCH 09/28] Update dependency rubocop to v1.59.0 (#28320) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 405c31ae1..378102437 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -381,7 +381,7 @@ GEM rdoc reline (>= 0.3.8) jmespath (1.6.2) - json (2.7.0) + json (2.7.1) json-canonicalization (1.0.0) json-jwt (1.15.3) activesupport (>= 4.2) @@ -622,7 +622,7 @@ GEM redis (>= 4) redlock (1.3.2) redis (>= 3.0.0, < 6.0) - regexp_parser (2.8.2) + regexp_parser (2.8.3) reline (0.4.1) io-console (~> 0.5) request_store (1.5.1) @@ -662,7 +662,7 @@ GEM rspec-mocks (~> 3.0) sidekiq (>= 5, < 8) rspec-support (3.12.1) - rubocop (1.58.0) + rubocop (1.59.0) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) From 3f1ec16377c11d2d7a48ccc735ed87d6619f6275 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 12 Dec 2023 15:31:37 +0100 Subject: [PATCH 10/28] Fix empty column explainer getting cropped under certain conditions (#28337) --- app/javascript/styles/mastodon/components.scss | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 2106b529d..462dd82ac 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -4398,11 +4398,6 @@ a.status-card { align-items: center; justify-content: center; - @supports (display: grid) { - // hack to fix Chrome <57 - contain: strict; - } - & > span { max-width: 500px; } From dcc24db793dc926823439b81839be1a3bc8e29d3 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 13 Dec 2023 08:47:32 +0100 Subject: [PATCH 11/28] Fix N+1s because of association preloaders not actually getting called (#28339) --- app/lib/inline_renderer.rb | 4 ++-- app/models/announcement.rb | 4 ++-- app/models/concerns/account/search.rb | 4 ++-- app/models/notification.rb | 2 +- app/serializers/initial_state_serializer.rb | 4 ++-- app/services/account_search_service.rb | 2 +- app/services/batched_remove_status_service.rb | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/lib/inline_renderer.rb b/app/lib/inline_renderer.rb index eda3da2c2..0aebb13fc 100644 --- a/app/lib/inline_renderer.rb +++ b/app/lib/inline_renderer.rb @@ -37,13 +37,13 @@ class InlineRenderer private def preload_associations_for_status - ActiveRecord::Associations::Preloader.new(records: @object, associations: { + ActiveRecord::Associations::Preloader.new(records: [@object], associations: { active_mentions: :account, reblog: { active_mentions: :account, }, - }) + }).call end def current_user diff --git a/app/models/announcement.rb b/app/models/announcement.rb index c5d6dd62e..2cd7c1d5e 100644 --- a/app/models/announcement.rb +++ b/app/models/announcement.rb @@ -78,9 +78,9 @@ class Announcement < ApplicationRecord else scope.select("name, custom_emoji_id, count(*) as count, exists(select 1 from announcement_reactions r where r.account_id = #{account.id} and r.announcement_id = announcement_reactions.announcement_id and r.name = announcement_reactions.name) as me") end - end + end.to_a - ActiveRecord::Associations::Preloader.new(records: records, associations: :custom_emoji) + ActiveRecord::Associations::Preloader.new(records: records, associations: :custom_emoji).call records end diff --git a/app/models/concerns/account/search.rb b/app/models/concerns/account/search.rb index b02b9bd46..40d87aaaa 100644 --- a/app/models/concerns/account/search.rb +++ b/app/models/concerns/account/search.rb @@ -124,7 +124,7 @@ module Account::Search tsquery = generate_query_for_search(terms) find_by_sql([BASIC_SEARCH_SQL, { limit: limit, offset: offset, tsquery: tsquery }]).tap do |records| - ActiveRecord::Associations::Preloader.new(records: records, associations: :account_stat) + ActiveRecord::Associations::Preloader.new(records: records, associations: [:account_stat, { user: :role }]).call end end @@ -133,7 +133,7 @@ module Account::Search sql_template = following ? ADVANCED_SEARCH_WITH_FOLLOWING : ADVANCED_SEARCH_WITHOUT_FOLLOWING find_by_sql([sql_template, { id: account.id, limit: limit, offset: offset, tsquery: tsquery }]).tap do |records| - ActiveRecord::Associations::Preloader.new(records: records, associations: :account_stat) + ActiveRecord::Associations::Preloader.new(records: records, associations: [:account_stat, { user: :role }]).call end end diff --git a/app/models/notification.rb b/app/models/notification.rb index 60f834a63..54212d675 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -111,7 +111,7 @@ class Notification < ApplicationRecord # Instead of using the usual `includes`, manually preload each type. # If polymorphic associations are loaded with the usual `includes`, other types of associations will be loaded more. - ActiveRecord::Associations::Preloader.new(records: grouped_notifications, associations: associations) + ActiveRecord::Associations::Preloader.new(records: grouped_notifications, associations: associations).call end unique_target_statuses = notifications.filter_map(&:target_status).uniq diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index a8af45990..f606836ba 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -86,8 +86,8 @@ class InitialStateSerializer < ActiveModel::Serializer ActiveRecord::Associations::Preloader.new( records: [object.current_account, object.admin, object.owner, object.disabled_account, object.moved_to_account].compact, - associations: [:account_stat, :user, { moved_to_account: [:account_stat, :user] }] - ) + associations: [:account_stat, { user: :role, moved_to_account: [:account_stat, { user: :role }] }] + ).call store[object.current_account.id.to_s] = serialized_account(object.current_account) if object.current_account store[object.admin.id.to_s] = serialized_account(object.admin) if object.admin diff --git a/app/services/account_search_service.rb b/app/services/account_search_service.rb index b437ff475..7b85b09d8 100644 --- a/app/services/account_search_service.rb +++ b/app/services/account_search_service.rb @@ -218,7 +218,7 @@ class AccountSearchService < BaseService records = query_builder.build.limit(limit_for_non_exact_results).offset(offset).objects.compact - ActiveRecord::Associations::Preloader.new(records: records, associations: :account_stat) + ActiveRecord::Associations::Preloader.new(records: records, associations: [:account_stat, { user: :role }]).call records rescue Faraday::ConnectionFailed, Parslet::ParseFailed diff --git a/app/services/batched_remove_status_service.rb b/app/services/batched_remove_status_service.rb index c54cc1d35..de4ee16e9 100644 --- a/app/services/batched_remove_status_service.rb +++ b/app/services/batched_remove_status_service.rb @@ -11,7 +11,7 @@ class BatchedRemoveStatusService < BaseService ActiveRecord::Associations::Preloader.new( records: statuses, associations: options[:skip_side_effects] ? :reblogs : [:account, :tags, reblogs: :account] - ) + ).call statuses_and_reblogs = statuses.flat_map { |status| [status] + status.reblogs } @@ -23,7 +23,7 @@ class BatchedRemoveStatusService < BaseService ActiveRecord::Associations::Preloader.new( records: statuses_with_account_conversations, associations: [mentions: :account] - ) + ).call statuses_with_account_conversations.each(&:unlink_from_conversations!) From aae4b5644f0fb02ce811f8f9a13d0965621d05a2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 10:52:33 +0100 Subject: [PATCH 12/28] Update dependency haml_lint to v0.52.0 (#28345) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 378102437..07b1a4bbe 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -326,7 +326,7 @@ GEM ruby-progressbar (~> 1.4) globalid (1.2.1) activesupport (>= 6.1) - haml (6.2.0) + haml (6.3.0) temple (>= 0.8.2) thor tilt @@ -335,7 +335,7 @@ GEM activesupport (>= 5.1) haml (>= 4.0.6) railties (>= 5.1) - haml_lint (0.51.0) + haml_lint (0.52.0) haml (>= 4.0) parallel (~> 1.10) rainbow From b2f915b31ae884e3893e93a99da4e2b8d7e9ef7b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 10:52:37 +0100 Subject: [PATCH 13/28] New Crowdin Translations (automated) (#28344) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/et.json | 1 + app/javascript/mastodon/locales/ja.json | 23 ++++++++++---------- app/javascript/mastodon/locales/ne.json | 29 ++++++++++++++++++++++++- config/locales/et.yml | 29 +++++++++++++++++++++++++ config/locales/ja.yml | 2 +- 5 files changed, 71 insertions(+), 13 deletions(-) diff --git a/app/javascript/mastodon/locales/et.json b/app/javascript/mastodon/locales/et.json index a67aa6fee..a41aa02f8 100644 --- a/app/javascript/mastodon/locales/et.json +++ b/app/javascript/mastodon/locales/et.json @@ -606,6 +606,7 @@ "search.quick_action.status_search": "Sobivad postitused {x}", "search.search_or_paste": "Otsi või kleebi URL", "search_popout.full_text_search_disabled_message": "Pole saadaval kohas {domain}.", + "search_popout.full_text_search_logged_out_message": "Saadaval vaid kui sisse logitud.", "search_popout.language_code": "Keele ISO-kood", "search_popout.options": "Otsimisvalikud", "search_popout.quick_actions": "Kiirtegevused", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index 3cb0565d0..5ad9d6dc9 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -21,7 +21,7 @@ "account.blocked": "ブロック済み", "account.browse_more_on_origin_server": "リモートで表示", "account.cancel_follow_request": "フォローリクエストの取り消し", - "account.copy": "プロフィールのリンクをコピーして下さい", + "account.copy": "プロフィールへのリンクをコピー", "account.direct": "@{name}さんに非公開でメンション", "account.disable_notifications": "@{name}さんの投稿時の通知を停止", "account.domain_blocked": "ドメインブロック中", @@ -192,7 +192,7 @@ "conversation.mark_as_read": "既読にする", "conversation.open": "会話を表示", "conversation.with": "{names}", - "copy_icon_button.copied": "クリップボードにコピーされた", + "copy_icon_button.copied": "コピーしました", "copypaste.copied": "コピーしました", "copypaste.copy_to_clipboard": "クリップボードにコピー", "directory.federated": "既知の連合より", @@ -392,7 +392,7 @@ "lists.search": "フォローしている人の中から検索", "lists.subheading": "あなたのリスト", "load_pending": "{count}件の新着", - "loading_indicator.label": "", + "loading_indicator.label": "読み込み中…", "media_gallery.toggle_visible": "{number, plural, one {画像を閉じる} other {画像を閉じる}}", "moved_to_account_banner.text": "あなたのアカウント『{disabledAccount}』は『{movedToAccount}』に移動したため現在無効になっています。", "mute_modal.duration": "ミュートする期間", @@ -481,17 +481,17 @@ "onboarding.follows.empty": "表示できる結果はありません。検索やエクスプローラーを使ったり、ほかのアカウントをフォローしたり、後でもう一度試しください。", "onboarding.follows.lead": "ホームタイムラインはMastodonの軸足となる場所です。たくさんのユーザーをフォローすることで、ホームタイムラインはよりにぎやかでおもしろいものになります。手はじめに、おすすめのアカウントから何人かフォローしてみましょう:", "onboarding.follows.title": "ホームタイムラインを埋める", - "onboarding.profile.discoverable": "自分のプロフィールが発見できないようにする", - "onboarding.profile.discoverable_hint": "マストドンの見つけやすくする機能が個人情報を利用することに承諾すると、あなたの投稿が検索結果やトレンドに表示されることがあります。また、あなたのプロフィールがあなたと似た興味関心を持つ人に提案されることがあります。", + "onboarding.profile.discoverable": "自分のプロフィールが見つけられるようにする", + "onboarding.profile.discoverable_hint": "Mastodonの「見つける」機能にオプトインすると、あなたの投稿が検索結果やトレンドに表示されることがあります。また、あなたに似た関心を持つ人にプロフィールがおすすめされることがあります。", "onboarding.profile.display_name": "表示名", - "onboarding.profile.display_name_hint": "あなたのフルネーム、または楽しい名前…", - "onboarding.profile.lead": "このことは後でいつでも設定から完了させることが出来ますし、設定では更に多くのカスタマイズが利用可能になっています。", + "onboarding.profile.display_name_hint": "フルネーム、あるいは面白い名前など", + "onboarding.profile.lead": "あとでいつでも修正できますし、設定画面にはこれ以外のカスタマイズ項目もあります。", "onboarding.profile.note": "自己紹介", - "onboarding.profile.note_hint": "@を使用して他の人々にメンションをすることができます。また#でハッシュタグが使用できます", - "onboarding.profile.save_and_continue": "保存してから続行して下さい", + "onboarding.profile.note_hint": "ほかの人に @言及 したり、#ハッシュタグ を付けたりできます", + "onboarding.profile.save_and_continue": "保存して続ける", "onboarding.profile.title": "プロフィールの設定", - "onboarding.profile.upload_avatar": "プロフィール画像をアップロードしてください", - "onboarding.profile.upload_header": "プロフィールのヘッダー画像をアップロードして下さい", + "onboarding.profile.upload_avatar": "プロフィール画像をアップロード", + "onboarding.profile.upload_header": "プロフィールのヘッダー画像をアップロード", "onboarding.share.lead": "新しいMastodonのアカウントをみんなに紹介しましょう。", "onboarding.share.message": "「{username}」で #Mastodon はじめました! {url}", "onboarding.share.next_steps": "次のステップに進む:", @@ -606,6 +606,7 @@ "search.quick_action.status_search": "{x}に該当する投稿", "search.search_or_paste": "検索またはURLを入力", "search_popout.full_text_search_disabled_message": "{domain}では利用できません。", + "search_popout.full_text_search_logged_out_message": "ログイン時のみ利用できます。", "search_popout.language_code": "ISO言語コード", "search_popout.options": "検索オプション", "search_popout.quick_actions": "クイック操作", diff --git a/app/javascript/mastodon/locales/ne.json b/app/javascript/mastodon/locales/ne.json index 95f8e703c..229d4f471 100644 --- a/app/javascript/mastodon/locales/ne.json +++ b/app/javascript/mastodon/locales/ne.json @@ -49,5 +49,32 @@ "admin.dashboard.retention.average": "औसत", "admin.dashboard.retention.cohort_size": "नयाँ प्रयोगकर्ताहरू", "alert.rate_limited.message": "कृपया {retry_time, time, medium} पछि पुन: प्रयास गर्नुहोस्।", - "alert.unexpected.message": "एउटा अनपेक्षित त्रुटि भयो।" + "alert.unexpected.message": "एउटा अनपेक्षित त्रुटि भयो।", + "bundle_column_error.retry": "पुन: प्रयास गर्नुहोस्", + "bundle_modal_error.close": "बन्द गर्नुहोस्", + "bundle_modal_error.message": "यो कम्पोनेन्ट लोड गर्दा केही गडबड भयो।", + "bundle_modal_error.retry": "Try again", + "closed_registrations.other_server_instructions": "Mastodon विकेन्द्रीकृत भएकोले, तपाइँ अर्को सर्भरमा खाता खोल्न सक्नुहुन्छ र पनि यो सर्भरसँग अन्तरक्रिया गर्न सक्नुहुन्छ।", + "closed_registrations_modal.description": "हाल {domain} मा खाता सिर्जना गर्न सम्भव छैन, तर कृपया ध्यान राख्नुहोस् कि तपाईंले Mastodon प्रयोग गर्नको लागि {domain} मा नै खाता खोल्न आवश्यक छैन।", + "closed_registrations_modal.find_another_server": "अर्को सर्भर खोज्नुहोस्", + "closed_registrations_modal.title": "Mastodon मा साइन अप गर्दै", + "column.blocks": "ब्लक गरिएको प्रयोगकर्ताहरु", + "column.directory": "प्रोफाइल ब्राउज गर्नुहोस्", + "column.domain_blocks": "ब्लक गरिएको डोमेन", + "column.follow_requests": "फलो अनुरोधहरू", + "column.lists": "सूचीहरू", + "column.notifications": "सूचनाहरू", + "column_header.hide_settings": "सेटिङ्हरू लुकाउनुहोस्", + "column_subheading.settings": "सेटिङहरू", + "compose.language.change": "भाषा परिवर्तन गर्नुहोस्", + "compose.language.search": "भाषाहरू खोज्नुहोस्...", + "compose_form.direct_message_warning_learn_more": "थप जान्नुहोस्", + "compose_form.poll.add_option": "विकल्प थप्नुहोस्", + "compose_form.poll.remove_option": "यो विकल्प हटाउनुहोस्", + "compose_form.publish_form": "नयाँ पोस्ट", + "compose_form.save_changes": "परिवर्तनहरू सेभ गर्नुहोस", + "compose_form.sensitive.hide": "{count, plural, one {संवेदनशील मिडियाको रूपमा चिन्ह लगाउनुहोस्} other {संवेदनशील मिडियाहरूको रूपमा चिन्ह लगाउनुहोस्}}", + "compose_form.sensitive.marked": "{count, plural, one {मिडियालाई संवेदनशील रूपमा चिन्ह लगाइएको छ} other {मिडियाहरूलाई संवेदनशील रूपमा चिन्ह लगाइएको छ}}", + "compose_form.sensitive.unmarked": "{count, plural, one {मिडियालाई संवेदनशील रूपमा चिन्ह लगाइएको छैन} other {मिडियाहरूलाई संवेदनशील रूपमा चिन्ह लगाइएको छैन}}", + "compose_form.spoiler_placeholder": "यहाँ आफ्नो चेतावनी लेख्नुहोस्" } diff --git a/config/locales/et.yml b/config/locales/et.yml index fb0fdc3a3..2d48edc29 100644 --- a/config/locales/et.yml +++ b/config/locales/et.yml @@ -534,6 +534,7 @@ et: total_reported: Nende kohta teateid total_storage: Lisatud meedia totals_time_period_hint_html: Allpool kuvatud summad sisaldavad andmed kogu aja kohta. + unknown_instance: Hetkel pole selle domeeni jaoks siin serveris kirjet. invites: deactivate_all: Peata kõik filter: @@ -610,6 +611,7 @@ et: created_at: Teavitatud delete_and_resolve: Kustuta postitused forwarded: Edastatud + forwarded_replies_explanation: See aruanne pärineb kaugkasutajalt ja käsitleb kaugsisu. See on edastatud sulle, sest raporteeritud sisu on vastus ühele sinu kasutajale. forwarded_to: Edastatud %{domain} domeeni mark_as_resolved: Märgi lahendatuks mark_as_sensitive: Märgi kui tundlik sisu @@ -832,6 +834,20 @@ et: system_checks: database_schema_check: message_html: On ootel andmebaasi migreerimisi. Rakenduse ootuspäraseks toimimiseks palun käivita need + elasticsearch_health_red: + message_html: Elasticsearch klaster on ebaterve (punane staatus), otsingufunktsioonid ei ole saadaval + elasticsearch_health_yellow: + message_html: Elasticsearch klaster on ebaterve (kollane staatus), võiksid uurida põhjust + elasticsearch_index_mismatch: + message_html: Elasticsearchi indeksite kaardistused on vananenud. Palun käivita tootctl search deploy --only=%{value} + elasticsearch_preset: + action: Vaata dokumentatsiooni + message_html: Elasticsearchi klastris on rohkem kui üks sõlme, kuid Mastodon ei ole nende kasutamiseks konfigureeritud. + elasticsearch_preset_single_node: + action: Vaata dokumentatsiooni + message_html: Elasticsearchi klastris on ainult üks sõlm ES_PRESET peaks olema seatud väärtusele single_node_cluster. + elasticsearch_reset_chewy: + message_html: Elasticsearchi süsteemiindeks on seadistuse muutumise tõttu vananenud. Palun käivita tootctl search deploy --reset-chewy selle uuendamiseks. elasticsearch_running_check: message_html: Elasticsearch ei vasta. Kontrolli, kas see töötab või keela täistekstiotsing elasticsearch_version_check: @@ -1024,6 +1040,14 @@ et: hint_html: Üks asi veel! Me peame veenduma, et oled inimene (et me saaksime spämmi väljaspoole jätta!). Lahenda allpool olev CAPTCHA ja klõpsa "Jätka". title: Turvalisuse kontroll confirmations: + awaiting_review: E-posti aadress on kinnitatud! %{domain} töötajad vaatavad praegu registreeringut läbi. Saad e-kirja, kui nad kiidavad konto heaks! + awaiting_review_title: Su registreeringut vaadatakse läbi + clicking_this_link: klõpsates seda linki + login_link: logi sisse + proceed_to_login_html: Saad nüüd jätkata valikuga %{login_link}. + redirect_to_app_html: Sind oleks pidanud suunatama rakendusse %{app_name}. Kui seda ei juhtunud, proovi %{clicking_this_link} või naase käsitsi rakendusse. + registration_complete: Sinu registreering domeenil %{domain} on nüüd valmis! + welcome_title: Tere tulemast, %{name}! wrong_email_hint: Kui see e-postiaadress pole korrektne, saad seda kontosätetes muuta. delete_account: Konto kustutamine delete_account_html: Kui soovid oma konto kustutada, siis jätka siit. Pead kustutamise eraldi kinnitama. @@ -1085,6 +1109,7 @@ et: functional: Konto on täies mahus kasutatav. pending: Taotlus ootab ülevaatamist meie personali poolt. See võib võtta mõne aja. Kui taotlus on vastu võetud, saadetakse sulle e-kiri. redirecting_to: See konto pole aktiivne, sest on suunatud aadressile %{acct}. + self_destruct: Kuna %{domain} on sulgemisel, saad oma kontole vaid piiratud ligipääsu. view_strikes: Vaata enda eelnevaid juhtumeid too_fast: Vorm esitatud liiga kiirelt, proovi uuesti. use_security_key: Kasuta turvavõtit @@ -1342,6 +1367,7 @@ et: '86400': 1 päev expires_in_prompt: Mitte kunagi generate: Loo + invalid: See kutse pole kehtiv invited_by: 'Sind kutsus:' max_uses: one: 1 kasutus @@ -1554,6 +1580,9 @@ et: over_daily_limit: Lubatud ajastatud postituste arv %{limit} päevas on tänaseks ületatud over_total_limit: Oled jõudnud ajastatud postituste lubatud maksimumarvuni %{limit} too_soon: Ajastatud kuupäev peab olema tukevikus + self_destruct: + lead_html: Kahjuks suletakse %{domain} lõplikult. Kui sul oli seal konto, ei saa sa seda enam kasutada, kuid siiski võid taotleda oma andmete varukoopiat. + title: See server suletakse sessions: activity: Viimane aktiivsus browser: Veebilehitseja diff --git a/config/locales/ja.yml b/config/locales/ja.yml index f7a2c2817..8682f37ee 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -599,7 +599,7 @@ ja: created_at: 通報日時 delete_and_resolve: 投稿を削除 forwarded: 転送済み - forwarded_replies_explanation: この報告はリモートユーザーからのものであり、またリモートコンテンツに関するものです。報告されたコンテンツがあなたのユーザーの内の一人に対するリプライの中にあるため、あなたに転送されました。 + forwarded_replies_explanation: これはリモートユーザーによる、リモートコンテンツについての報告です。問題のコンテンツはあなたのサーバー利用者への返信なので、こちらにも転送されて来ました。 forwarded_to: "%{domain}に転送されました" mark_as_resolved: 解決済みとしてマーク mark_as_sensitive: 閲覧注意にする From 49150e2f1d6ae197b160a9dc701f5ac154929ca2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 10:52:40 +0100 Subject: [PATCH 14/28] Update dependency ws to v8.15.1 (#28343) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7903ecc5c..bd2545cf6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17739,8 +17739,8 @@ __metadata: linkType: hard "ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.14.2": - version: 8.15.0 - resolution: "ws@npm:8.15.0" + version: 8.15.1 + resolution: "ws@npm:8.15.1" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -17749,7 +17749,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: b778a405b2589ffbf549323e2f404f1f72e372a049d332d2f0b1f33057e9fbb14a05aa474cb156e4584b418cd95edf4297c0ca5263d6519e8009064bf8e0b80d + checksum: 9964360dd5ab35c7376bd7c4295a3c8bd44ea0838c9413742548a6fb3ec371fc6c18552d5b8e76bdc21536db1909765612815bae072674b5ec69971605395a96 languageName: node linkType: hard From 3a59365e40733a502b4a20515e15f8e18b7abe5f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 10:52:43 +0100 Subject: [PATCH 15/28] Update dependency test-prof to v1.3.1 (#28342) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 07b1a4bbe..e53e18292 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -759,7 +759,7 @@ GEM unicode-display_width (>= 1.1.1, < 3) terrapin (0.6.0) climate_control (>= 0.0.3, < 1.0) - test-prof (1.3.0) + test-prof (1.3.1) thor (1.3.0) tilt (2.3.0) timeout (0.4.1) From 8a3d8c6c14f4e9b57967104286fa6eaa305e6412 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Wed, 13 Dec 2023 05:14:19 -0500 Subject: [PATCH 16/28] Remove the `stub_stdout` wrapper around CLI specs (#28340) --- lib/mastodon/cli/search.rb | 12 ++- spec/lib/mastodon/cli/accounts_spec.rb | 138 ++++++++++++++++-------- spec/lib/mastodon/cli/ip_blocks_spec.rb | 6 +- spec/lib/mastodon/cli/settings_spec.rb | 3 +- spec/rails_helper.rb | 9 -- 5 files changed, 110 insertions(+), 58 deletions(-) diff --git a/lib/mastodon/cli/search.rb b/lib/mastodon/cli/search.rb index 25a595aad..77c455f04 100644 --- a/lib/mastodon/cli/search.rb +++ b/lib/mastodon/cli/search.rb @@ -42,7 +42,13 @@ module Mastodon::CLI pool = Concurrent::FixedThreadPool.new(options[:concurrency], max_queue: options[:concurrency] * 10) importers = indices.index_with { |index| "Importer::#{index.name}Importer".constantize.new(batch_size: options[:batch_size], executor: pool) } - progress = ProgressBar.create(total: nil, format: '%t%c/%u |%b%i| %e (%r docs/s)', autofinish: false) + progress = ProgressBar.create( + { + total: nil, + format: '%t%c/%u |%b%i| %e (%r docs/s)', + autofinish: false, + }.merge(progress_output_options) + ) Chewy::Stash::Specification.reset! if options[:reset_chewy] @@ -116,5 +122,9 @@ module Mastodon::CLI say('Cannot run with this batch_size setting, must be at least 1', :red) exit(1) end + + def progress_output_options + Rails.env.test? ? { output: ProgressBar::Outputs::Null } : {} + end end end diff --git a/spec/lib/mastodon/cli/accounts_spec.rb b/spec/lib/mastodon/cli/accounts_spec.rb index 563f6e877..64df29ebb 100644 --- a/spec/lib/mastodon/cli/accounts_spec.rb +++ b/spec/lib/mastodon/cli/accounts_spec.rb @@ -77,7 +77,8 @@ describe Mastodon::CLI::Accounts do it_behaves_like 'a new user with given email address and username' it 'creates a new user with confirmed status' do - subject + expect { subject } + .to output_results('New password') user = User.find_by(email: options[:email]) @@ -95,7 +96,8 @@ describe Mastodon::CLI::Accounts do it_behaves_like 'a new user with given email address and username' it 'creates a new user with approved status' do - subject + expect { subject } + .to output_results('New password') user = User.find_by(email: options[:email]) @@ -111,7 +113,8 @@ describe Mastodon::CLI::Accounts do it_behaves_like 'a new user with given email address and username' it 'creates a new user and assigns the specified role' do - subject + expect { subject } + .to output_results('New password') role = User.find_by(email: options[:email])&.role @@ -148,7 +151,8 @@ describe Mastodon::CLI::Accounts do let(:options) { { email: 'tootctl_new@example.com', reattach: true, force: true } } it 'reattaches the account to the new user and deletes the previous user' do - subject + expect { subject } + .to output_results('New password') user = Account.find_local('tootctl_username')&.user @@ -220,7 +224,8 @@ describe Mastodon::CLI::Accounts do let(:options) { { role: default_role.name } } it "updates the user's role to the specified role" do - subject + expect { subject } + .to output_results('OK') role = user.reload.role @@ -235,7 +240,8 @@ describe Mastodon::CLI::Accounts do let(:user) { Fabricate(:user, role: role) } it "removes the user's role successfully" do - subject + expect { subject } + .to output_results('OK') role = user.reload.role @@ -248,13 +254,15 @@ describe Mastodon::CLI::Accounts do let(:options) { { email: 'new_email@email.com' } } it "sets the user's unconfirmed email to the provided email address" do - subject + expect { subject } + .to output_results('OK') expect(user.reload.unconfirmed_email).to eq(options[:email]) end it "does not update the user's original email address" do - subject + expect { subject } + .to output_results('OK') expect(user.reload.email).to eq('old_email@email.com') end @@ -264,13 +272,15 @@ describe Mastodon::CLI::Accounts do let(:options) { { email: 'new_email@email.com', confirm: true } } it "updates the user's email address to the provided email" do - subject + expect { subject } + .to output_results('OK') expect(user.reload.email).to eq(options[:email]) end it "sets the user's email address as confirmed" do - subject + expect { subject } + .to output_results('OK') expect(user.reload.confirmed?).to be(true) end @@ -282,7 +292,8 @@ describe Mastodon::CLI::Accounts do let(:options) { { confirm: true } } it "confirms the user's email address" do - subject + expect { subject } + .to output_results('OK') expect(user.reload.confirmed?).to be(true) end @@ -297,7 +308,9 @@ describe Mastodon::CLI::Accounts do end it 'approves the user' do - expect { subject }.to change { user.reload.approved }.from(false).to(true) + expect { subject } + .to output_results('OK') + .and change { user.reload.approved }.from(false).to(true) end end @@ -306,7 +319,9 @@ describe Mastodon::CLI::Accounts do let(:options) { { disable: true } } it 'disables the user' do - expect { subject }.to change { user.reload.disabled }.from(false).to(true) + expect { subject } + .to output_results('OK') + .and change { user.reload.disabled }.from(false).to(true) end end @@ -315,7 +330,9 @@ describe Mastodon::CLI::Accounts do let(:options) { { enable: true } } it 'enables the user' do - expect { subject }.to change { user.reload.disabled }.from(true).to(false) + expect { subject } + .to output_results('OK') + .and change { user.reload.disabled }.from(true).to(false) end end @@ -335,7 +352,9 @@ describe Mastodon::CLI::Accounts do let(:options) { { disable_2fa: true } } it 'disables the two-factor authentication for the user' do - expect { subject }.to change { user.reload.otp_required_for_login }.from(true).to(false) + expect { subject } + .to output_results('OK') + .and change { user.reload.otp_required_for_login }.from(true).to(false) end end @@ -385,7 +404,8 @@ describe Mastodon::CLI::Accounts do let(:arguments) { [account.username] } it 'deletes the specified user successfully' do - subject + expect { subject } + .to output_results('Deleting') expect(delete_account_service).to have_received(:call).with(account, reserve_email: false).once end @@ -415,7 +435,8 @@ describe Mastodon::CLI::Accounts do let(:options) { { email: account.user.email } } it 'deletes the specified user successfully' do - subject + expect { subject } + .to output_results('Deleting') expect(delete_account_service).to have_received(:call).with(account, reserve_email: false).once end @@ -457,7 +478,8 @@ describe Mastodon::CLI::Accounts do let(:options) { { all: true } } it 'approves all pending registrations' do - subject + expect { subject } + .to output_results('OK') expect(User.pluck(:approved).all?(true)).to be(true) end @@ -468,7 +490,8 @@ describe Mastodon::CLI::Accounts do let(:options) { { number: 2 } } it 'approves the earliest n pending registrations but not the remaining ones' do - subject + expect { subject } + .to output_results('OK') expect(n_earliest_pending_registrations.all?(&:approved?)).to be(true) expect(pending_registrations.all?(&:approved?)).to be(false) @@ -498,7 +521,7 @@ describe Mastodon::CLI::Accounts do it 'approves all users and does not raise any error' do expect { subject } - .to_not raise_error + .to output_results('OK') expect(User.pluck(:approved).all?(true)).to be(true) end end @@ -510,7 +533,8 @@ describe Mastodon::CLI::Accounts do let(:arguments) { [user.account.username] } it 'approves the specified user successfully' do - subject + expect { subject } + .to output_results('OK') expect(user.reload.approved?).to be(true) end @@ -655,7 +679,8 @@ describe Mastodon::CLI::Accounts do allow(remote_account_example_com).to receive(:reset_avatar!) allow(account_example_net).to receive(:reset_avatar!) - cli.refresh + expect { cli.refresh } + .to output_results('Refreshed 2 accounts') expect(cli).to have_received(:parallelize_with_progress).with(scope).once expect(remote_account_example_com).to have_received(:reset_avatar!).once @@ -665,7 +690,8 @@ describe Mastodon::CLI::Accounts do it 'does not refresh avatar for local accounts' do allow(local_account).to receive(:reset_avatar!) - cli.refresh + expect { cli.refresh } + .to output_results('Refreshed 2 accounts') expect(cli).to have_received(:parallelize_with_progress).with(scope).once expect(local_account).to_not have_received(:reset_avatar!) @@ -675,7 +701,8 @@ describe Mastodon::CLI::Accounts do allow(remote_account_example_com).to receive(:reset_header!) allow(account_example_net).to receive(:reset_header!) - cli.refresh + expect { cli.refresh } + .to output_results('Refreshed 2 accounts') expect(cli).to have_received(:parallelize_with_progress).with(scope).once expect(remote_account_example_com).to have_received(:reset_header!).once @@ -685,7 +712,8 @@ describe Mastodon::CLI::Accounts do it 'does not refresh the header for local accounts' do allow(local_account).to receive(:reset_header!) - cli.refresh + expect { cli.refresh } + .to output_results('Refreshed 2 accounts') expect(cli).to have_received(:parallelize_with_progress).with(scope).once expect(local_account).to_not have_received(:reset_header!) @@ -706,7 +734,8 @@ describe Mastodon::CLI::Accounts do allow(remote_account_example_com).to receive(:reset_avatar!) allow(account_example_net).to receive(:reset_avatar!) - cli.refresh + expect { cli.refresh } + .to output_results('Refreshed 2 accounts') expect(cli).to have_received(:parallelize_with_progress).with(scope).once expect(local_account).to_not have_received(:reset_avatar!) @@ -719,7 +748,8 @@ describe Mastodon::CLI::Accounts do allow(remote_account_example_com).to receive(:reset_header!) allow(account_example_net).to receive(:reset_header!) - cli.refresh + expect { cli.refresh } + .to output_results('Refreshed 2 accounts') expect(cli).to have_received(:parallelize_with_progress).with(scope).once expect(local_account).to_not have_received(:reset_header!) @@ -752,7 +782,8 @@ describe Mastodon::CLI::Accounts do allow(account_example_com_a).to receive(:reset_avatar!) allow(account_example_com_b).to receive(:reset_avatar!) - cli.refresh(*arguments) + expect { cli.refresh(*arguments) } + .to output_results('OK') expect(account_example_com_a).to have_received(:reset_avatar!).once expect(account_example_com_b).to have_received(:reset_avatar!).once @@ -761,7 +792,8 @@ describe Mastodon::CLI::Accounts do it 'does not reset the avatar for unspecified accounts' do allow(account_example_net).to receive(:reset_avatar!) - cli.refresh(*arguments) + expect { cli.refresh(*arguments) } + .to output_results('OK') expect(account_example_net).to_not have_received(:reset_avatar!) end @@ -770,7 +802,8 @@ describe Mastodon::CLI::Accounts do allow(account_example_com_a).to receive(:reset_header!) allow(account_example_com_b).to receive(:reset_header!) - cli.refresh(*arguments) + expect { cli.refresh(*arguments) } + .to output_results('OK') expect(account_example_com_a).to have_received(:reset_header!).once expect(account_example_com_b).to have_received(:reset_header!).once @@ -779,7 +812,8 @@ describe Mastodon::CLI::Accounts do it 'does not reset the header for unspecified accounts' do allow(account_example_net).to receive(:reset_header!) - cli.refresh(*arguments) + expect { cli.refresh(*arguments) } + .to output_results('OK') expect(account_example_net).to_not have_received(:reset_header!) end @@ -812,7 +846,8 @@ describe Mastodon::CLI::Accounts do allow(account_example_com_a).to receive(:reset_avatar!) allow(account_example_com_b).to receive(:reset_avatar!) - cli.refresh(*arguments) + expect { cli.refresh(*arguments) } + .to output_results('OK (DRY RUN)') expect(account_example_com_a).to_not have_received(:reset_avatar!) expect(account_example_com_b).to_not have_received(:reset_avatar!) @@ -822,7 +857,8 @@ describe Mastodon::CLI::Accounts do allow(account_example_com_a).to receive(:reset_header!) allow(account_example_com_b).to receive(:reset_header!) - cli.refresh(*arguments) + expect { cli.refresh(*arguments) } + .to output_results('OK (DRY RUN)') expect(account_example_com_a).to_not have_received(:reset_header!) expect(account_example_com_b).to_not have_received(:reset_header!) @@ -848,7 +884,8 @@ describe Mastodon::CLI::Accounts do allow(account_example_com_a).to receive(:reset_avatar!) allow(account_example_com_b).to receive(:reset_avatar!) - cli.refresh + expect { cli.refresh } + .to output_results('Refreshed 2 accounts') expect(cli).to have_received(:parallelize_with_progress).with(scope).once expect(account_example_com_a).to have_received(:reset_avatar!).once @@ -858,7 +895,8 @@ describe Mastodon::CLI::Accounts do it 'does not refresh the avatar for accounts outside specified domain' do allow(account_example_net).to receive(:reset_avatar!) - cli.refresh + expect { cli.refresh } + .to output_results('Refreshed 2 accounts') expect(cli).to have_received(:parallelize_with_progress).with(scope).once expect(account_example_net).to_not have_received(:reset_avatar!) @@ -868,7 +906,8 @@ describe Mastodon::CLI::Accounts do allow(account_example_com_a).to receive(:reset_header!) allow(account_example_com_b).to receive(:reset_header!) - cli.refresh + expect { cli.refresh } + .to output_results('Refreshed 2 accounts') expect(cli).to have_received(:parallelize_with_progress).with(scope) expect(account_example_com_a).to have_received(:reset_header!).once @@ -878,7 +917,8 @@ describe Mastodon::CLI::Accounts do it 'does not refresh the header for accounts outside specified domain' do allow(account_example_net).to receive(:reset_header!) - cli.refresh + expect { cli.refresh } + .to output_results('Refreshed 2 accounts') expect(cli).to have_received(:parallelize_with_progress).with(scope).once expect(account_example_net).to_not have_received(:reset_header!) @@ -913,7 +953,8 @@ describe Mastodon::CLI::Accounts do old_private_key = account.private_key old_public_key = account.public_key - subject + expect { subject } + .to output_results('OK') account.reload expect(account.private_key).to_not eq(old_private_key) @@ -923,7 +964,8 @@ describe Mastodon::CLI::Accounts do it 'broadcasts the new keys for the specified account' do allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_in) - subject + expect { subject } + .to output_results('OK') expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_in).with(anything, account.id, anything).once end @@ -947,7 +989,8 @@ describe Mastodon::CLI::Accounts do old_private_keys = accounts.map(&:private_key) old_public_keys = accounts.map(&:public_key) - subject + expect { subject } + .to output_results('rotated') accounts.each(&:reload) expect(accounts.map(&:private_key)).to_not eq(old_private_keys) @@ -957,7 +1000,8 @@ describe Mastodon::CLI::Accounts do it 'broadcasts the new keys for each account' do allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_in) - subject + expect { subject } + .to output_results('rotated') accounts.each do |account| expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_in).with(anything, account.id, anything).once @@ -1036,7 +1080,8 @@ describe Mastodon::CLI::Accounts do end it 'merges `from_account` into `to_account` and deletes `from_account`' do - subject + expect { subject } + .to output_results('OK') expect(to_account).to have_received(:merge_with!).with(from_account).once expect(from_account).to have_received(:destroy).once @@ -1059,7 +1104,8 @@ describe Mastodon::CLI::Accounts do end it 'merges "from_account" into "to_account" and deletes from_account' do - subject + expect { subject } + .to output_results('OK') expect(to_account).to have_received(:merge_with!).with(from_account).once expect(from_account).to have_received(:destroy) @@ -1339,7 +1385,8 @@ describe Mastodon::CLI::Accounts do shared_examples 'a successful migration' do it 'calls the MoveService for the last migration' do - subject + expect { subject } + .to output_results('OK') last_migration = source_account.migrations.last @@ -1449,7 +1496,8 @@ describe Mastodon::CLI::Accounts do end it 'creates a migration for the specified account with the target account' do - subject + expect { subject } + .to output_results('migrated') last_migration = source_account.migrations.last diff --git a/spec/lib/mastodon/cli/ip_blocks_spec.rb b/spec/lib/mastodon/cli/ip_blocks_spec.rb index 1d6c47268..82be10813 100644 --- a/spec/lib/mastodon/cli/ip_blocks_spec.rb +++ b/spec/lib/mastodon/cli/ip_blocks_spec.rb @@ -78,7 +78,8 @@ describe Mastodon::CLI::IpBlocks do it 'overwrites the existing IP block record' do expect { subject } - .to change { blocked_ip.reload.severity } + .to output_results('Added 11') + .and change { blocked_ip.reload.severity } .from('no_access') .to('sign_up_requires_approval') end @@ -189,7 +190,8 @@ describe Mastodon::CLI::IpBlocks do let(:options) { { force: true } } it 'removes blocks for IP ranges that cover given IP(s) and keeps other ranges' do - subject + expect { subject } + .to output_results('Removed 2') expect(covered_ranges).to_not exist expect(other_ranges).to exist diff --git a/spec/lib/mastodon/cli/settings_spec.rb b/spec/lib/mastodon/cli/settings_spec.rb index 568ee0039..e1b353eb9 100644 --- a/spec/lib/mastodon/cli/settings_spec.rb +++ b/spec/lib/mastodon/cli/settings_spec.rb @@ -41,7 +41,8 @@ describe Mastodon::CLI::Settings do it 'changes registrations_mode and require_invite_text' do expect { subject } - .to change(Setting, :registrations_mode).from(nil).to('approved') + .to output_results('OK') + .and change(Setting, :registrations_mode).from(nil).to('approved') .and change(Setting, :require_invite_text).from(false).to(true) end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 4394b470e..0e68fbe12 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -104,7 +104,6 @@ RSpec.configure do |config| end config.before :each, type: :cli do - stub_stdout stub_reset_connection_pools end @@ -163,14 +162,6 @@ def attachment_fixture(name) Rails.root.join('spec', 'fixtures', 'files', name).open end -def stub_stdout - # TODO: Is there a bettery way to: - # - Avoid CLI command output being printed out - # - Allow rspec to assert things against STDOUT - # - Avoid disabling stdout for other desirable output (deprecation warnings, for example) - allow($stdout).to receive(:write) -end - def stub_reset_connection_pools # TODO: Is there a better way to correctly run specs without stubbing this? # (Avoids reset_connection_pools! in test env) From d791b470582f761f819a9862dd0ea81705e60e86 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:26:28 +0100 Subject: [PATCH 17/28] Update dependency chewy to v7.4.0 (#28349) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index e53e18292..ab24f5dca 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -168,7 +168,7 @@ GEM erubi (~> 1.4) parser (>= 2.4) smart_properties - bigdecimal (3.1.4) + bigdecimal (3.1.5) bindata (2.4.15) binding_of_caller (1.0.0) debug_inspector (>= 0.0.1) @@ -197,7 +197,7 @@ GEM activesupport cbor (0.5.9.6) charlock_holmes (0.7.7) - chewy (7.3.5) + chewy (7.4.0) activesupport (>= 5.2) elasticsearch (>= 7.12.0, < 7.14.0) elasticsearch-dsl From 28e1a7a394db5586bdeb1d872f2bf4bfc18b5d0a Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 14 Dec 2023 05:29:10 -0500 Subject: [PATCH 18/28] Improve spec coverage for `models/announcement` class (#28350) --- spec/controllers/emojis_controller_spec.rb | 2 +- .../announcement_mute_fabricator.rb | 6 + .../announcement_reaction_fabricator.rb | 7 + spec/fabricators/custom_emoji_fabricator.rb | 2 +- spec/models/announcement_spec.rb | 210 ++++++++++++++++++ spec/models/custom_emoji_spec.rb | 2 +- spec/requests/api/v1/custom_emojis_spec.rb | 2 +- 7 files changed, 227 insertions(+), 4 deletions(-) create mode 100644 spec/fabricators/announcement_mute_fabricator.rb create mode 100644 spec/fabricators/announcement_reaction_fabricator.rb create mode 100644 spec/models/announcement_spec.rb diff --git a/spec/controllers/emojis_controller_spec.rb b/spec/controllers/emojis_controller_spec.rb index 3fe19ee5c..dd139de93 100644 --- a/spec/controllers/emojis_controller_spec.rb +++ b/spec/controllers/emojis_controller_spec.rb @@ -5,7 +5,7 @@ require 'rails_helper' describe EmojisController do render_views - let(:emoji) { Fabricate(:custom_emoji) } + let(:emoji) { Fabricate(:custom_emoji, shortcode: 'coolcat') } describe 'GET #show' do let(:response) { get :show, params: { id: emoji.id, format: :json } } diff --git a/spec/fabricators/announcement_mute_fabricator.rb b/spec/fabricators/announcement_mute_fabricator.rb new file mode 100644 index 000000000..0adc1d60b --- /dev/null +++ b/spec/fabricators/announcement_mute_fabricator.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +Fabricator(:announcement_mute) do + announcement { Fabricate.build(:announcement) } + account { Fabricate.build(:account) } +end diff --git a/spec/fabricators/announcement_reaction_fabricator.rb b/spec/fabricators/announcement_reaction_fabricator.rb new file mode 100644 index 000000000..e84579729 --- /dev/null +++ b/spec/fabricators/announcement_reaction_fabricator.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +Fabricator(:announcement_reaction) do + account { Fabricate.build(:account) } + announcement { Fabricate.build(:announcement) } + name { Fabricate(:custom_emoji).shortcode } +end diff --git a/spec/fabricators/custom_emoji_fabricator.rb b/spec/fabricators/custom_emoji_fabricator.rb index fa570eec6..7ef875286 100644 --- a/spec/fabricators/custom_emoji_fabricator.rb +++ b/spec/fabricators/custom_emoji_fabricator.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true Fabricator(:custom_emoji) do - shortcode 'coolcat' + shortcode { sequence(:shortcode) { |i| "code_#{i}" } } domain nil image { Rails.root.join('spec', 'fixtures', 'files', 'emojo.png').open } end diff --git a/spec/models/announcement_spec.rb b/spec/models/announcement_spec.rb new file mode 100644 index 000000000..e37b81a52 --- /dev/null +++ b/spec/models/announcement_spec.rb @@ -0,0 +1,210 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe Announcement do + describe 'Scopes' do + context 'with published and unpublished records' do + let!(:published) { Fabricate(:announcement, published: true) } + let!(:unpublished) { Fabricate(:announcement, published: false, scheduled_at: 10.days.from_now) } + + describe '#unpublished' do + it 'returns records with published false' do + results = described_class.unpublished + + expect(results).to eq([unpublished]) + end + end + + describe '#published' do + it 'returns records with published true' do + results = described_class.published + + expect(results).to eq([published]) + end + end + end + + describe '#without_muted' do + let!(:announcement) { Fabricate(:announcement) } + let(:account) { Fabricate(:account) } + let(:muted_announcement) { Fabricate(:announcement) } + + before do + Fabricate(:announcement_mute, account: account, announcement: muted_announcement) + end + + it 'returns the announcements not muted by the account' do + results = described_class.without_muted(account) + expect(results).to include(announcement) + expect(results).to_not include(muted_announcement) + end + end + + context 'with timestamped announcements' do + let!(:adam_announcement) { Fabricate(:announcement, starts_at: 100.days.ago, scheduled_at: 10.days.ago, published_at: 10.days.ago, ends_at: 5.days.from_now) } + let!(:brenda_announcement) { Fabricate(:announcement, starts_at: 10.days.ago, scheduled_at: 100.days.ago, published_at: 10.days.ago, ends_at: 5.days.from_now) } + let!(:clara_announcement) { Fabricate(:announcement, starts_at: 10.days.ago, scheduled_at: 10.days.ago, published_at: 100.days.ago, ends_at: 5.days.from_now) } + let!(:darnelle_announcement) { Fabricate(:announcement, starts_at: 10.days.ago, scheduled_at: 10.days.ago, published_at: 10.days.ago, ends_at: 5.days.from_now, created_at: 100.days.ago) } + + describe '#chronological' do + it 'orders the records correctly' do + results = described_class.chronological + + expect(results).to eq( + [ + adam_announcement, + brenda_announcement, + clara_announcement, + darnelle_announcement, + ] + ) + end + end + + describe '#reverse_chronological' do + it 'orders the records correctly' do + results = described_class.reverse_chronological + + expect(results).to eq( + [ + darnelle_announcement, + clara_announcement, + brenda_announcement, + adam_announcement, + ] + ) + end + end + end + end + + describe 'Validations' do + describe 'text' do + it 'validates presence of attribute' do + record = Fabricate.build(:announcement, text: nil) + + expect(record).to_not be_valid + expect(record.errors[:text]).to be_present + end + end + + describe 'ends_at' do + it 'validates presence when starts_at is present' do + record = Fabricate.build(:announcement, starts_at: 1.day.ago) + + expect(record).to_not be_valid + expect(record.errors[:ends_at]).to be_present + end + + it 'does not validate presence when starts_at is missing' do + record = Fabricate.build(:announcement, starts_at: nil) + + expect(record).to be_valid + expect(record.errors[:ends_at]).to_not be_present + end + end + end + + describe '#publish!' do + it 'publishes an unpublished record' do + announcement = Fabricate(:announcement, published: false, scheduled_at: 10.days.from_now) + + announcement.publish! + + expect(announcement).to be_published + expect(announcement.published_at).to_not be_nil + expect(announcement.scheduled_at).to be_nil + end + end + + describe '#unpublish!' do + it 'unpublishes a published record' do + announcement = Fabricate(:announcement, published: true) + + announcement.unpublish! + + expect(announcement).to_not be_published + expect(announcement.scheduled_at).to be_nil + end + end + + describe '#time_range?' do + it 'returns false when starts_at and ends_at are missing' do + record = Fabricate.build(:announcement, starts_at: nil, ends_at: nil) + + expect(record.time_range?).to be(false) + end + + it 'returns false when starts_at is present and ends_at is missing' do + record = Fabricate.build(:announcement, starts_at: 5.days.from_now, ends_at: nil) + + expect(record.time_range?).to be(false) + end + + it 'returns false when starts_at is missing and ends_at is present' do + record = Fabricate.build(:announcement, starts_at: nil, ends_at: 5.days.from_now) + + expect(record.time_range?).to be(false) + end + + it 'returns true when starts_at and ends_at are present' do + record = Fabricate.build(:announcement, starts_at: 5.days.from_now, ends_at: 10.days.from_now) + + expect(record.time_range?).to be(true) + end + end + + describe '#reactions' do + context 'with announcement_reactions present' do + let!(:account) { Fabricate(:account) } + let!(:announcement) { Fabricate(:announcement) } + let!(:announcement_reaction) { Fabricate(:announcement_reaction, announcement: announcement, created_at: 10.days.ago) } + let!(:announcement_reaction_account) { Fabricate(:announcement_reaction, announcement: announcement, created_at: 5.days.ago, account: account) } + + before do + Fabricate(:announcement_reaction) + end + + it 'returns the announcement reactions for the announcement' do + results = announcement.reactions + + expect(results.first.name).to eq(announcement_reaction.name) + expect(results.last.name).to eq(announcement_reaction_account.name) + end + + it 'returns the announcement reactions for the announcement limited to account' do + results = announcement.reactions(account) + + expect(results.first.name).to eq(announcement_reaction.name) + end + end + end + + describe '#statuses' do + let(:announcement) { Fabricate(:announcement, status_ids: status_ids) } + + context 'with empty status_ids' do + let(:status_ids) { nil } + + it 'returns empty array' do + results = announcement.statuses + + expect(results).to eq([]) + end + end + + context 'with relevant status_ids' do + let(:status) { Fabricate(:status, visibility: :public) } + let(:direct_status) { Fabricate(:status, visibility: :direct) } + let(:status_ids) { [status.id, direct_status.id] } + + it 'returns public and unlisted statuses' do + results = announcement.statuses + + expect(results).to include(status) + expect(results).to_not include(direct_status) + end + end + end +end diff --git a/spec/models/custom_emoji_spec.rb b/spec/models/custom_emoji_spec.rb index 8a6487c32..06affd634 100644 --- a/spec/models/custom_emoji_spec.rb +++ b/spec/models/custom_emoji_spec.rb @@ -59,7 +59,7 @@ RSpec.describe CustomEmoji do describe '.from_text' do subject { described_class.from_text(text, nil) } - let!(:emojo) { Fabricate(:custom_emoji) } + let!(:emojo) { Fabricate(:custom_emoji, shortcode: 'coolcat') } context 'with plain text' do let(:text) { 'Hello :coolcat:' } diff --git a/spec/requests/api/v1/custom_emojis_spec.rb b/spec/requests/api/v1/custom_emojis_spec.rb index 5de0dda0b..2f0dc7294 100644 --- a/spec/requests/api/v1/custom_emojis_spec.rb +++ b/spec/requests/api/v1/custom_emojis_spec.rb @@ -9,7 +9,7 @@ describe 'Custom Emojis' do describe 'GET /api/v1/custom_emojis' do before do - Fabricate(:custom_emoji, domain: nil, disabled: false, visible_in_picker: true) + Fabricate(:custom_emoji, domain: nil, disabled: false, visible_in_picker: true, shortcode: 'coolcat') end context 'when logged out' do From cd9ebf5f0f476c7d2fb60b59eb9f2674bebce158 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 14 Dec 2023 05:35:54 -0500 Subject: [PATCH 19/28] Update stylelint to version 16.0.2 (#28354) --- package.json | 2 +- yarn.lock | 354 +++++++++++---------------------------------------- 2 files changed, 76 insertions(+), 280 deletions(-) diff --git a/package.json b/package.json index 37139254c..39d387d6f 100644 --- a/package.json +++ b/package.json @@ -201,7 +201,7 @@ "lint-staged": "^15.0.0", "prettier": "^3.0.0", "react-test-renderer": "^18.2.0", - "stylelint": "^15.10.1", + "stylelint": "^16.0.2", "stylelint-config-standard-scss": "^12.0.0", "typescript": "^5.0.4", "webpack-dev-server": "^3.11.3", diff --git a/yarn.lock b/yarn.lock index bd2545cf6..e369f89d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1539,7 +1539,7 @@ __metadata: languageName: node linkType: hard -"@csstools/css-parser-algorithms@npm:^2.3.1": +"@csstools/css-parser-algorithms@npm:^2.3.2": version: 2.3.2 resolution: "@csstools/css-parser-algorithms@npm:2.3.2" peerDependencies: @@ -1548,14 +1548,14 @@ __metadata: languageName: node linkType: hard -"@csstools/css-tokenizer@npm:^2.2.0": +"@csstools/css-tokenizer@npm:^2.2.1": version: 2.2.1 resolution: "@csstools/css-tokenizer@npm:2.2.1" checksum: 0c6901d291e99c567893846a47068057c2a28b3edc4219b6da589a530f55f51ddd4675f906f707b393bfe7a508ab2604bf3f75708f064db857bb277636bd5a44 languageName: node linkType: hard -"@csstools/media-query-list-parser@npm:^2.1.4": +"@csstools/media-query-list-parser@npm:^2.1.5": version: 2.1.5 resolution: "@csstools/media-query-list-parser@npm:2.1.5" peerDependencies: @@ -2432,7 +2432,7 @@ __metadata: sass-loader: "npm:^10.2.0" stacktrace-js: "npm:^2.0.2" stringz: "npm:^2.1.0" - stylelint: "npm:^15.10.1" + stylelint: "npm:^16.0.2" stylelint-config-standard-scss: "npm:^12.0.0" substring-trie: "npm:^1.0.2" terser-webpack-plugin: "npm:^4.2.3" @@ -3252,13 +3252,6 @@ __metadata: languageName: node linkType: hard -"@types/minimist@npm:^1.2.2": - version: 1.2.4 - resolution: "@types/minimist@npm:1.2.4" - checksum: 01403652c09de17b8c6d7d9959cb7a244deccf31e9e7a1a7011fba73fa2724c14fe935718e0fdc48dcd30403fd76a916cb991d4c0ddf229748ccc6c4920c3371 - languageName: node - linkType: hard - "@types/node@npm:*": version: 20.8.10 resolution: "@types/node@npm:20.8.10" @@ -3275,13 +3268,6 @@ __metadata: languageName: node linkType: hard -"@types/normalize-package-data@npm:^2.4.0": - version: 2.4.3 - resolution: "@types/normalize-package-data@npm:2.4.3" - checksum: 9ad94568b53f65d0c7fffed61c74e4a7b8625b1ebbc549f1de25287c2d20e6bca9d9cdc5826e508c9d95e02a48ac69d0282121c300667071661f37090224416b - languageName: node - linkType: hard - "@types/npmlog@npm:^7.0.0": version: 7.0.0 resolution: "@types/npmlog@npm:7.0.0" @@ -4491,13 +4477,6 @@ __metadata: languageName: node linkType: hard -"arrify@npm:^1.0.1": - version: 1.0.1 - resolution: "arrify@npm:1.0.1" - checksum: c35c8d1a81bcd5474c0c57fe3f4bad1a4d46a5fa353cedcff7a54da315df60db71829e69104b859dff96c5d68af46bd2be259fe5e50dc6aa9df3b36bea0383ab - languageName: node - linkType: hard - "arrow-key-navigation@npm:^1.2.0": version: 1.2.0 resolution: "arrow-key-navigation@npm:1.2.0" @@ -5371,18 +5350,6 @@ __metadata: languageName: node linkType: hard -"camelcase-keys@npm:^7.0.0": - version: 7.0.2 - resolution: "camelcase-keys@npm:7.0.2" - dependencies: - camelcase: "npm:^6.3.0" - map-obj: "npm:^4.1.0" - quick-lru: "npm:^5.1.1" - type-fest: "npm:^1.2.1" - checksum: ae86a51168643e9e8a2f2c7bfa17850729979ec3dafc5253056a7d97931cbb0e3ef5b4185e59d54b7a56c54405dee2874b0c82033498d8626e512ff9034cb05c - languageName: node - linkType: hard - "camelcase@npm:^5.0.0, camelcase@npm:^5.3.1": version: 5.3.1 resolution: "camelcase@npm:5.3.1" @@ -5390,7 +5357,7 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^6.2.0, camelcase@npm:^6.3.0": +"camelcase@npm:^6.2.0": version: 6.3.0 resolution: "camelcase@npm:6.3.0" checksum: 0d701658219bd3116d12da3eab31acddb3f9440790c0792e0d398f0a520a6a4058018e546862b6fba89d7ae990efaeb97da71e1913e9ebf5a8b5621a3d55c710 @@ -5987,15 +5954,20 @@ __metadata: languageName: node linkType: hard -"cosmiconfig@npm:^8.2.0": - version: 8.2.0 - resolution: "cosmiconfig@npm:8.2.0" +"cosmiconfig@npm:^9.0.0": + version: 9.0.0 + resolution: "cosmiconfig@npm:9.0.0" dependencies: - import-fresh: "npm:^3.2.1" + env-paths: "npm:^2.2.1" + import-fresh: "npm:^3.3.0" js-yaml: "npm:^4.1.0" - parse-json: "npm:^5.0.0" - path-type: "npm:^4.0.0" - checksum: 4180aa6d1881b75ba591b2fc04b022741a3a4b67e9e243c0eb8d169b6e1efbd3cdf7e8ca19243c0f2e53a9d59ac3eccd5cad5f95f487fcbf4e740f9e86745747 + parse-json: "npm:^5.2.0" + peerDependencies: + typescript: ">=4.9.5" + peerDependenciesMeta: + typescript: + optional: true + checksum: 1c1703be4f02a250b1d6ca3267e408ce16abfe8364193891afc94c2d5c060b69611fdc8d97af74b7e6d5d1aac0ab2fb94d6b079573146bc2d756c2484ce5f0ee languageName: node linkType: hard @@ -6435,30 +6407,13 @@ __metadata: languageName: node linkType: hard -"decamelize-keys@npm:^1.1.0": - version: 1.1.1 - resolution: "decamelize-keys@npm:1.1.1" - dependencies: - decamelize: "npm:^1.1.0" - map-obj: "npm:^1.0.0" - checksum: 4ca385933127437658338c65fb9aead5f21b28d3dd3ccd7956eb29aab0953b5d3c047fbc207111672220c71ecf7a4d34f36c92851b7bbde6fca1a02c541bdd7d - languageName: node - linkType: hard - -"decamelize@npm:^1.1.0, decamelize@npm:^1.2.0": +"decamelize@npm:^1.2.0": version: 1.2.0 resolution: "decamelize@npm:1.2.0" checksum: 85c39fe8fbf0482d4a1e224ef0119db5c1897f8503bcef8b826adff7a1b11414972f6fef2d7dec2ee0b4be3863cf64ac1439137ae9e6af23a3d8dcbe26a5b4b2 languageName: node linkType: hard -"decamelize@npm:^5.0.0": - version: 5.0.1 - resolution: "decamelize@npm:5.0.1" - checksum: 3da71022bc1e85487810fa0833138effb599fa331ca21e179650e93a765d0c4dabeb1ecdd6ad1474fa0bacd2457953c63ea335afb6e53b35f2b4bf779514e2a3 - languageName: node - linkType: hard - "decimal.js@npm:^10.4.2, decimal.js@npm:^10.4.3": version: 10.4.3 resolution: "decimal.js@npm:10.4.3" @@ -7093,7 +7048,7 @@ __metadata: languageName: node linkType: hard -"env-paths@npm:^2.2.0": +"env-paths@npm:^2.2.0, env-paths@npm:^2.2.1": version: 2.2.1 resolution: "env-paths@npm:2.2.1" checksum: 285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 @@ -7941,6 +7896,19 @@ __metadata: languageName: node linkType: hard +"fast-glob@npm:^3.3.2": + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" + dependencies: + "@nodelib/fs.stat": "npm:^2.0.2" + "@nodelib/fs.walk": "npm:^1.2.3" + glob-parent: "npm:^5.1.2" + merge2: "npm:^1.3.0" + micromatch: "npm:^4.0.4" + checksum: 42baad7b9cd40b63e42039132bde27ca2cb3a4950d0a0f9abe4639ea1aa9d3e3b40f98b1fe31cbc0cc17b664c9ea7447d911a152fa34ec5b72977b125a6fc845 + languageName: node + linkType: hard + "fast-json-stable-stringify@npm:^2.0.0, fast-json-stable-stringify@npm:^2.1.0": version: 2.1.0 resolution: "fast-json-stable-stringify@npm:2.1.0" @@ -7998,12 +7966,12 @@ __metadata: languageName: node linkType: hard -"file-entry-cache@npm:^7.0.0": - version: 7.0.1 - resolution: "file-entry-cache@npm:7.0.1" +"file-entry-cache@npm:^7.0.2": + version: 7.0.2 + resolution: "file-entry-cache@npm:7.0.2" dependencies: - flat-cache: "npm:^3.1.1" - checksum: fc0e4f830777e07087f97da9a6734820fdffa2945583355433f40d9819dd97b89f16ac87c07118737a6bc3eb9cf4bd896e7b38b07f0768aefcf44da33e797363 + flat-cache: "npm:^3.2.0" + checksum: 822664e35c3e295e6a8ca7ec490d8d8077017607f41f94b29922f1f49c6dd07025048e3ed528e2909a1439eba66d60f802c0774aa612cf6ee053ee4ecc16c8c5 languageName: node linkType: hard @@ -8137,7 +8105,7 @@ __metadata: languageName: node linkType: hard -"flat-cache@npm:^3.0.4, flat-cache@npm:^3.1.1": +"flat-cache@npm:^3.0.4, flat-cache@npm:^3.2.0": version: 3.2.0 resolution: "flat-cache@npm:3.2.0" dependencies: @@ -8669,13 +8637,6 @@ __metadata: languageName: node linkType: hard -"hard-rejection@npm:^2.1.0": - version: 2.1.0 - resolution: "hard-rejection@npm:2.1.0" - checksum: febc3343a1ad575aedcc112580835b44a89a89e01f400b4eda6e8110869edfdab0b00cd1bd4c3bfec9475a57e79e0b355aecd5be46454b6a62b9a359af60e564 - languageName: node - linkType: hard - "has-bigints@npm:^1.0.1, has-bigints@npm:^1.0.2": version: 1.0.2 resolution: "has-bigints@npm:1.0.2" @@ -8855,15 +8816,6 @@ __metadata: languageName: node linkType: hard -"hosted-git-info@npm:^4.0.1": - version: 4.1.0 - resolution: "hosted-git-info@npm:4.1.0" - dependencies: - lru-cache: "npm:^6.0.0" - checksum: 150fbcb001600336d17fdbae803264abed013548eea7946c2264c49ebe2ebd8c4441ba71dd23dd8e18c65de79d637f98b22d4760ba5fb2e0b15d62543d0fff07 - languageName: node - linkType: hard - "hpack.js@npm:^2.1.6": version: 2.1.6 resolution: "hpack.js@npm:2.1.6" @@ -9124,6 +9076,13 @@ __metadata: languageName: node linkType: hard +"ignore@npm:^5.3.0": + version: 5.3.0 + resolution: "ignore@npm:5.3.0" + checksum: dc06bea5c23aae65d0725a957a0638b57e235ae4568dda51ca142053ed2c352de7e3bc93a69b2b32ac31966a1952e9a93c5ef2e2ab7c6b06aef9808f6b55b571 + languageName: node + linkType: hard + "immer@npm:^9.0.21": version: 9.0.21 resolution: "immer@npm:9.0.21" @@ -9145,7 +9104,7 @@ __metadata: languageName: node linkType: hard -"import-fresh@npm:^3.2.1": +"import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0": version: 3.3.0 resolution: "import-fresh@npm:3.3.0" dependencies: @@ -9155,13 +9114,6 @@ __metadata: languageName: node linkType: hard -"import-lazy@npm:^4.0.0": - version: 4.0.0 - resolution: "import-lazy@npm:4.0.0" - checksum: a3520313e2c31f25c0b06aa66d167f329832b68a4f957d7c9daf6e0fa41822b6e84948191648b9b9d8ca82f94740cdf15eecf2401a5b42cd1c33fd84f2225cca - languageName: node - linkType: hard - "import-local@npm:^2.0.0": version: 2.0.0 resolution: "import-local@npm:2.0.0" @@ -9214,13 +9166,6 @@ __metadata: languageName: node linkType: hard -"indent-string@npm:^5.0.0": - version: 5.0.0 - resolution: "indent-string@npm:5.0.0" - checksum: 8ee77b57d92e71745e133f6f444d6fa3ed503ad0e1bcd7e80c8da08b42375c07117128d670589725ed07b1978065803fa86318c309ba45415b7fe13e7f170220 - languageName: node - linkType: hard - "infer-owner@npm:^1.0.4": version: 1.0.4 resolution: "infer-owner@npm:1.0.4" @@ -9482,7 +9427,7 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.11.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1, is-core-module@npm:^2.5.0, is-core-module@npm:^2.9.0": +"is-core-module@npm:^2.11.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1, is-core-module@npm:^2.9.0": version: 2.13.1 resolution: "is-core-module@npm:2.13.1" dependencies: @@ -9764,13 +9709,6 @@ __metadata: languageName: node linkType: hard -"is-plain-obj@npm:^1.1.0": - version: 1.1.0 - resolution: "is-plain-obj@npm:1.1.0" - checksum: daaee1805add26f781b413fdf192fc91d52409583be30ace35c82607d440da63cc4cac0ac55136716688d6c0a2c6ef3edb2254fecbd1fe06056d6bd15975ee8c - languageName: node - linkType: hard - "is-plain-object@npm:^2.0.3, is-plain-object@npm:^2.0.4": version: 2.0.4 resolution: "is-plain-object@npm:2.0.4" @@ -11264,20 +11202,6 @@ __metadata: languageName: node linkType: hard -"map-obj@npm:^1.0.0": - version: 1.0.1 - resolution: "map-obj@npm:1.0.1" - checksum: ccca88395e7d38671ed9f5652ecf471ecd546924be2fb900836b9da35e068a96687d96a5f93dcdfa94d9a27d649d2f10a84595590f89a347fb4dda47629dcc52 - languageName: node - linkType: hard - -"map-obj@npm:^4.1.0": - version: 4.3.0 - resolution: "map-obj@npm:4.3.0" - checksum: 1c19e1c88513c8abdab25c316367154c6a0a6a0f77e3e8c391bb7c0e093aefed293f539d026dc013d86219e5e4c25f23b0003ea588be2101ccd757bacc12d43b - languageName: node - linkType: hard - "map-visit@npm:^1.0.0": version: 1.0.0 resolution: "map-visit@npm:1.0.0" @@ -11381,23 +11305,10 @@ __metadata: languageName: node linkType: hard -"meow@npm:^10.1.5": - version: 10.1.5 - resolution: "meow@npm:10.1.5" - dependencies: - "@types/minimist": "npm:^1.2.2" - camelcase-keys: "npm:^7.0.0" - decamelize: "npm:^5.0.0" - decamelize-keys: "npm:^1.1.0" - hard-rejection: "npm:^2.1.0" - minimist-options: "npm:4.1.0" - normalize-package-data: "npm:^3.0.2" - read-pkg-up: "npm:^8.0.0" - redent: "npm:^4.0.0" - trim-newlines: "npm:^4.0.2" - type-fest: "npm:^1.2.2" - yargs-parser: "npm:^20.2.9" - checksum: a513849022edd5ddcc41d28c679d31978abe414d9db5bc457e95e537a4327b2910fd2f699cdd883293f9a5da8951a50939bf60fbd62f7fe12b9ddf96a84b1b27 +"meow@npm:^12.1.1": + version: 12.1.1 + resolution: "meow@npm:12.1.1" + checksum: a125ca99a32e2306e2f4cbe651a0d27f6eb67918d43a075f6e80b35e9bf372ebf0fc3a9fbc201cbbc9516444b6265fb3c9f80c5b7ebd32f548aa93eb7c28e088 languageName: node linkType: hard @@ -11520,7 +11431,7 @@ __metadata: languageName: node linkType: hard -"min-indent@npm:^1.0.0, min-indent@npm:^1.0.1": +"min-indent@npm:^1.0.0": version: 1.0.1 resolution: "min-indent@npm:1.0.1" checksum: 7e207bd5c20401b292de291f02913230cb1163abca162044f7db1d951fa245b174dc00869d40dd9a9f32a885ad6a5f3e767ee104cf278f399cb4e92d3f582d5c @@ -11581,17 +11492,6 @@ __metadata: languageName: node linkType: hard -"minimist-options@npm:4.1.0": - version: 4.1.0 - resolution: "minimist-options@npm:4.1.0" - dependencies: - arrify: "npm:^1.0.1" - is-plain-obj: "npm:^1.1.0" - kind-of: "npm:^6.0.3" - checksum: 7871f9cdd15d1e7374e5b013e2ceda3d327a06a8c7b38ae16d9ef941e07d985e952c589e57213f7aa90a8744c60aed9524c0d85e501f5478382d9181f2763f54 - languageName: node - linkType: hard - "minimist@npm:^1.2.0, minimist@npm:^1.2.6": version: 1.2.8 resolution: "minimist@npm:1.2.8" @@ -11949,18 +11849,6 @@ __metadata: languageName: node linkType: hard -"normalize-package-data@npm:^3.0.2": - version: 3.0.3 - resolution: "normalize-package-data@npm:3.0.3" - dependencies: - hosted-git-info: "npm:^4.0.1" - is-core-module: "npm:^2.5.0" - semver: "npm:^7.3.4" - validate-npm-package-license: "npm:^3.0.1" - checksum: e5d0f739ba2c465d41f77c9d950e291ea4af78f8816ddb91c5da62257c40b76d8c83278b0d08ffbcd0f187636ebddad20e181e924873916d03e6e5ea2ef026be - languageName: node - linkType: hard - "normalize-path@npm:^2.1.1": version: 2.1.1 resolution: "normalize-path@npm:2.1.1" @@ -13160,12 +13048,12 @@ __metadata: languageName: node linkType: hard -"postcss-safe-parser@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-safe-parser@npm:6.0.0" +"postcss-safe-parser@npm:^7.0.0": + version: 7.0.0 + resolution: "postcss-safe-parser@npm:7.0.0" peerDependencies: - postcss: ^8.3.3 - checksum: 5b0997b63de6ab4afb4b718a52dd7902e465c21d1f2e516762bcb59047787459b4dc5713132f6a19c9c8c483043b20b8a380a55fb61152ee66cbffcddf3b57f0 + postcss: ^8.4.31 + checksum: 4217afd8ce2809e959dc365e4675f499303cc6b91f94db06c8164422822db2d3b3124df701ee2234db4127ad05619b016bfb9c2bccae9bf9cf898a396f1632c9 languageName: node linkType: hard @@ -13218,7 +13106,7 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.2.15, postcss@npm:^8.4.24, postcss@npm:^8.4.28": +"postcss@npm:^8.2.15, postcss@npm:^8.4.24, postcss@npm:^8.4.32": version: 8.4.32 resolution: "postcss@npm:8.4.32" dependencies: @@ -13541,13 +13429,6 @@ __metadata: languageName: node linkType: hard -"quick-lru@npm:^5.1.1": - version: 5.1.1 - resolution: "quick-lru@npm:5.1.1" - checksum: a24cba5da8cec30d70d2484be37622580f64765fb6390a928b17f60cd69e8dbd32a954b3ff9176fa1b86d86ff2ba05252fae55dc4d40d0291c60412b0ad096da - languageName: node - linkType: hard - "raf@npm:^3.1.0": version: 3.4.1 resolution: "raf@npm:3.4.1" @@ -14027,29 +13908,6 @@ __metadata: languageName: node linkType: hard -"read-pkg-up@npm:^8.0.0": - version: 8.0.0 - resolution: "read-pkg-up@npm:8.0.0" - dependencies: - find-up: "npm:^5.0.0" - read-pkg: "npm:^6.0.0" - type-fest: "npm:^1.0.1" - checksum: cf3905ccbe5cd602f23192cc7ca65ed17561bab117eadb9aed817441d5bfc6b9a11215c2a3e9505f501d046818f3c4180dbea61fa83c42083e0b4e407d5cc745 - languageName: node - linkType: hard - -"read-pkg@npm:^6.0.0": - version: 6.0.0 - resolution: "read-pkg@npm:6.0.0" - dependencies: - "@types/normalize-package-data": "npm:^2.4.0" - normalize-package-data: "npm:^3.0.2" - parse-json: "npm:^5.2.0" - type-fest: "npm:^1.0.1" - checksum: b51ee5eed75324f4fac34c9a40b5e4b403de4c532242be01959c9bbdb1ff9db1c6c2aefaba569622fec49d1ead866e97ba856ab145f6e11039b11f7bec1318ba - languageName: node - linkType: hard - "readable-stream@npm:^2.0.1, readable-stream@npm:^2.0.2, readable-stream@npm:^2.3.3, readable-stream@npm:^2.3.6": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" @@ -14118,16 +13976,6 @@ __metadata: languageName: node linkType: hard -"redent@npm:^4.0.0": - version: 4.0.0 - resolution: "redent@npm:4.0.0" - dependencies: - indent-string: "npm:^5.0.0" - strip-indent: "npm:^4.0.0" - checksum: a9b640c8f4b2b5b26a1a908706475ff404dd50a97d6f094bc3c59717be922622927cc7d601d4ae2857d897ad243fd979bd76d751a0481cee8be7024e5fb4c662 - languageName: node - linkType: hard - "redis-errors@npm:^1.0.0, redis-errors@npm:^1.2.0": version: 1.2.0 resolution: "redis-errors@npm:1.2.0" @@ -15270,16 +15118,6 @@ __metadata: languageName: node linkType: hard -"spdx-correct@npm:^3.0.0": - version: 3.2.0 - resolution: "spdx-correct@npm:3.2.0" - dependencies: - spdx-expression-parse: "npm:^3.0.0" - spdx-license-ids: "npm:^3.0.0" - checksum: 49208f008618b9119208b0dadc9208a3a55053f4fd6a0ae8116861bd22696fc50f4142a35ebfdb389e05ccf2de8ad142573fefc9e26f670522d899f7b2fe7386 - languageName: node - linkType: hard - "spdx-exceptions@npm:^2.1.0": version: 2.3.0 resolution: "spdx-exceptions@npm:2.3.0" @@ -15287,7 +15125,7 @@ __metadata: languageName: node linkType: hard -"spdx-expression-parse@npm:^3.0.0, spdx-expression-parse@npm:^3.0.1": +"spdx-expression-parse@npm:^3.0.1": version: 3.0.1 resolution: "spdx-expression-parse@npm:3.0.1" dependencies: @@ -15723,15 +15561,6 @@ __metadata: languageName: node linkType: hard -"strip-indent@npm:^4.0.0": - version: 4.0.0 - resolution: "strip-indent@npm:4.0.0" - dependencies: - min-indent: "npm:^1.0.1" - checksum: 6b1fb4e22056867f5c9e7a6f3f45922d9a2436cac758607d58aeaac0d3b16ec40b1c43317de7900f1b8dd7a4107352fa47fb960f2c23566538c51e8585c8870e - languageName: node - linkType: hard - "strip-json-comments@npm:^3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" @@ -15739,13 +15568,6 @@ __metadata: languageName: node linkType: hard -"style-search@npm:^0.1.0": - version: 0.1.0 - resolution: "style-search@npm:0.1.0" - checksum: 9e5cb735e5dc4fc2f8c61bebdf211d5352f1cf01511a64da12bb726a01e8c6948c50d357eb8fd7893d44b4e3189655bdddcf8ab338f9d508fe89a8942c650b14 - languageName: node - linkType: hard - "stylehacks@npm:^6.0.0": version: 6.0.0 resolution: "stylehacks@npm:6.0.0" @@ -15826,53 +15648,51 @@ __metadata: languageName: node linkType: hard -"stylelint@npm:^15.10.1": - version: 15.11.0 - resolution: "stylelint@npm:15.11.0" +"stylelint@npm:^16.0.2": + version: 16.0.2 + resolution: "stylelint@npm:16.0.2" dependencies: - "@csstools/css-parser-algorithms": "npm:^2.3.1" - "@csstools/css-tokenizer": "npm:^2.2.0" - "@csstools/media-query-list-parser": "npm:^2.1.4" + "@csstools/css-parser-algorithms": "npm:^2.3.2" + "@csstools/css-tokenizer": "npm:^2.2.1" + "@csstools/media-query-list-parser": "npm:^2.1.5" "@csstools/selector-specificity": "npm:^3.0.0" balanced-match: "npm:^2.0.0" colord: "npm:^2.9.3" - cosmiconfig: "npm:^8.2.0" + cosmiconfig: "npm:^9.0.0" css-functions-list: "npm:^3.2.1" css-tree: "npm:^2.3.1" debug: "npm:^4.3.4" - fast-glob: "npm:^3.3.1" + fast-glob: "npm:^3.3.2" fastest-levenshtein: "npm:^1.0.16" - file-entry-cache: "npm:^7.0.0" + file-entry-cache: "npm:^7.0.2" global-modules: "npm:^2.0.0" globby: "npm:^11.1.0" globjoin: "npm:^0.1.4" html-tags: "npm:^3.3.1" - ignore: "npm:^5.2.4" - import-lazy: "npm:^4.0.0" + ignore: "npm:^5.3.0" imurmurhash: "npm:^0.1.4" is-plain-object: "npm:^5.0.0" known-css-properties: "npm:^0.29.0" mathml-tag-names: "npm:^2.1.3" - meow: "npm:^10.1.5" + meow: "npm:^12.1.1" micromatch: "npm:^4.0.5" normalize-path: "npm:^3.0.0" picocolors: "npm:^1.0.0" - postcss: "npm:^8.4.28" + postcss: "npm:^8.4.32" postcss-resolve-nested-selector: "npm:^0.1.1" - postcss-safe-parser: "npm:^6.0.0" + postcss-safe-parser: "npm:^7.0.0" postcss-selector-parser: "npm:^6.0.13" postcss-value-parser: "npm:^4.2.0" resolve-from: "npm:^5.0.0" string-width: "npm:^4.2.3" - strip-ansi: "npm:^6.0.1" - style-search: "npm:^0.1.0" + strip-ansi: "npm:^7.1.0" supports-hyperlinks: "npm:^3.0.0" svg-tags: "npm:^1.0.0" table: "npm:^6.8.1" write-file-atomic: "npm:^5.0.1" bin: stylelint: bin/stylelint.mjs - checksum: 2d88b7293e308b7e418c14ba4130777b1a28b214304957f03b41a6dc8e00005266caf47479f718a6ec5e572cb52e903ca34aabf3febbe3a3ae32fff6b018d9fd + checksum: 5ec755e209beb1877ff40d50f18c1ebb05bf251925da1f98f28fb3911e4031195eb86adaf641ac5cdb01ba973f4c999bc0c6b0270d08c1d5c070adbdd9e734cf languageName: node linkType: hard @@ -16326,13 +16146,6 @@ __metadata: languageName: node linkType: hard -"trim-newlines@npm:^4.0.2": - version: 4.1.1 - resolution: "trim-newlines@npm:4.1.1" - checksum: 70e60e652305efd0dda1f2bce1a5edc9bb5834a2e00d05dfde178715ec48faa8264a2bc1a7efc593b7936d03f6d42c398616329eef44b7bd5070180a02056981 - languageName: node - linkType: hard - "ts-api-utils@npm:^1.0.1": version: 1.0.3 resolution: "ts-api-utils@npm:1.0.3" @@ -16424,13 +16237,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^1.0.1, type-fest@npm:^1.2.1, type-fest@npm:^1.2.2": - version: 1.4.0 - resolution: "type-fest@npm:1.4.0" - checksum: a3c0f4ee28ff6ddf800d769eafafcdeab32efa38763c1a1b8daeae681920f6e345d7920bf277245235561d8117dab765cb5f829c76b713b4c9de0998a5397141 - languageName: node - linkType: hard - "type-fest@npm:^3.0.0": version: 3.13.1 resolution: "type-fest@npm:3.13.1" @@ -16897,16 +16703,6 @@ __metadata: languageName: node linkType: hard -"validate-npm-package-license@npm:^3.0.1": - version: 3.0.4 - resolution: "validate-npm-package-license@npm:3.0.4" - dependencies: - spdx-correct: "npm:^3.0.0" - spdx-expression-parse: "npm:^3.0.0" - checksum: 7b91e455a8de9a0beaa9fe961e536b677da7f48c9a493edf4d4d4a87fd80a7a10267d438723364e432c2fcd00b5650b5378275cded362383ef570276e6312f4f - languageName: node - linkType: hard - "value-equal@npm:^1.0.1": version: 1.0.1 resolution: "value-equal@npm:1.0.1" @@ -17833,7 +17629,7 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^20.2.1, yargs-parser@npm:^20.2.9": +"yargs-parser@npm:^20.2.1": version: 20.2.9 resolution: "yargs-parser@npm:20.2.9" checksum: 0685a8e58bbfb57fab6aefe03c6da904a59769bd803a722bb098bd5b0f29d274a1357762c7258fb487512811b8063fb5d2824a3415a0a4540598335b3b086c72 From adbfd40a1b38b89587d74d4ce2d27b21b8c90ed1 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 14 Dec 2023 05:38:06 -0500 Subject: [PATCH 20/28] Convert `api/v1/directories` controller spec to request spec (#28356) --- .../api/v1/directories_spec.rb} | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) rename spec/{controllers/api/v1/directories_controller_spec.rb => requests/api/v1/directories_spec.rb} (82%) diff --git a/spec/controllers/api/v1/directories_controller_spec.rb b/spec/requests/api/v1/directories_spec.rb similarity index 82% rename from spec/controllers/api/v1/directories_controller_spec.rb rename to spec/requests/api/v1/directories_spec.rb index 308a8874c..0a1864d13 100644 --- a/spec/controllers/api/v1/directories_controller_spec.rb +++ b/spec/requests/api/v1/directories_spec.rb @@ -2,17 +2,13 @@ require 'rails_helper' -describe Api::V1::DirectoriesController do - render_views - +describe 'Directories API' do let(:user) { Fabricate(:user, confirmed_at: nil) } - let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:follows') } + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } + let(:scopes) { 'read:follows' } + let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } - before do - allow(controller).to receive(:doorkeeper_token) { token } - end - - describe 'GET #show' do + describe 'GET /api/v1/directories' do context 'with no params' do before do local_unconfirmed_account = Fabricate( @@ -58,27 +54,32 @@ describe Api::V1::DirectoriesController do ) domain_blocked_account.create_account_stat! Fabricate(:account_domain_block, account: user.account, domain: 'test.example') + + local_discoverable_account.create_account_stat! + eligible_remote_account.create_account_stat! end - it 'returns the local discoverable account and the remote discoverable account' do - local_discoverable_account = Fabricate( + let(:local_discoverable_account) do + Fabricate( :account, domain: nil, user: Fabricate(:user, confirmed_at: 10.days.ago, approved: true), discoverable: true, username: 'local_discoverable' ) - local_discoverable_account.create_account_stat! + end - eligible_remote_account = Fabricate( + let(:eligible_remote_account) do + Fabricate( :account, domain: 'host.example', discoverable: true, username: 'eligible_remote' ) - eligible_remote_account.create_account_stat! + end - get :show + it 'returns the local discoverable account and the remote discoverable account' do + get '/api/v1/directory', headers: headers expect(response).to have_http_status(200) expect(body_as_json.size).to eq(2) @@ -87,14 +88,17 @@ describe Api::V1::DirectoriesController do end context 'when asking for local accounts only' do - it 'returns only the local accounts' do - user = Fabricate(:user, confirmed_at: 10.days.ago, approved: true) - local_account = Fabricate(:account, domain: nil, user: user) - remote_account = Fabricate(:account, domain: 'host.example') + let(:user) { Fabricate(:user, confirmed_at: 10.days.ago, approved: true) } + let(:local_account) { Fabricate(:account, domain: nil, user: user) } + let(:remote_account) { Fabricate(:account, domain: 'host.example') } + + before do local_account.create_account_stat! remote_account.create_account_stat! + end - get :show, params: { local: '1' } + it 'returns only the local accounts' do + get '/api/v1/directory', headers: headers, params: { local: '1' } expect(response).to have_http_status(200) expect(body_as_json.size).to eq(1) @@ -108,7 +112,7 @@ describe Api::V1::DirectoriesController do old_stat = Fabricate(:account_stat, last_status_at: 1.day.ago) new_stat = Fabricate(:account_stat, last_status_at: 1.minute.ago) - get :show, params: { order: 'active' } + get '/api/v1/directory', headers: headers, params: { order: 'active' } expect(response).to have_http_status(200) expect(body_as_json.size).to eq(2) @@ -123,7 +127,7 @@ describe Api::V1::DirectoriesController do travel_to 10.seconds.from_now account_new = Fabricate(:account_stat).account - get :show, params: { order: 'new' } + get '/api/v1/directory', headers: headers, params: { order: 'new' } expect(response).to have_http_status(200) expect(body_as_json.size).to eq(2) From ef9797a395de7cc9e44f5f29ca3a2f70aff04b48 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 14 Dec 2023 05:46:43 -0500 Subject: [PATCH 21/28] Un-nest contexts in `settings/2fa/webauthn` spec (#28359) --- .../webauthn_credentials_controller_spec.rb | 97 ++++++++----------- 1 file changed, 42 insertions(+), 55 deletions(-) diff --git a/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb index 719ed2f88..41a3ba5eb 100644 --- a/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb +++ b/spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb @@ -194,60 +194,49 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do add_webauthn_credential(user) end - context 'when creation succeeds' do - it 'adds a new credential to user credentials and does not change webauthn_id', :aggregate_failures do - controller.session[:webauthn_challenge] = challenge - - expect do - post :create, params: { credential: new_webauthn_credential, nickname: nickname } - end.to change { user.webauthn_credentials.count }.by(1) - .and not_change(user, :webauthn_id) - - expect(response).to have_http_status(200) - end - end - - context 'when the nickname is already used' do - it 'fails' do - controller.session[:webauthn_challenge] = challenge - - post :create, params: { credential: new_webauthn_credential, nickname: 'USB Key' } - - expect(response).to have_http_status(422) - expect(flash[:error]).to be_present - end - end - - context 'when the credential already exists' do - before do - user2 = Fabricate(:user) - public_key_credential = WebAuthn::Credential.from_create(new_webauthn_credential) - Fabricate(:webauthn_credential, - user_id: user2.id, - external_id: public_key_credential.id, - public_key: public_key_credential.public_key) - end - - it 'fails' do - controller.session[:webauthn_challenge] = challenge + it 'adds a new credential to user credentials and does not change webauthn_id when creation succeeds', :aggregate_failures do + controller.session[:webauthn_challenge] = challenge + expect do post :create, params: { credential: new_webauthn_credential, nickname: nickname } + end.to change { user.webauthn_credentials.count }.by(1) + .and not_change(user, :webauthn_id) - expect(response).to have_http_status(422) - expect(flash[:error]).to be_present - end + expect(response).to have_http_status(200) + end + + it 'fails when the nickname is already used' do + controller.session[:webauthn_challenge] = challenge + + post :create, params: { credential: new_webauthn_credential, nickname: 'USB Key' } + + expect(response).to have_http_status(422) + expect(flash[:error]).to be_present + end + + it 'fails when the credential already exists' do + public_key_credential = WebAuthn::Credential.from_create(new_webauthn_credential) + Fabricate(:webauthn_credential, + user_id: Fabricate(:user).id, + external_id: public_key_credential.id, + public_key: public_key_credential.public_key) + + controller.session[:webauthn_challenge] = challenge + + post :create, params: { credential: new_webauthn_credential, nickname: nickname } + + expect(response).to have_http_status(422) + expect(flash[:error]).to be_present end end - context 'when user have not enabled webauthn' do - context 'when creation succeeds' do - it 'creates a webauthn credential' do - controller.session[:webauthn_challenge] = challenge + context 'when user have not enabled webauthn and creation succeeds' do + it 'creates a webauthn credential' do + controller.session[:webauthn_challenge] = challenge - expect do - post :create, params: { credential: new_webauthn_credential, nickname: nickname } - end.to change { user.webauthn_credentials.count }.by(1) - end + expect do + post :create, params: { credential: new_webauthn_credential, nickname: nickname } + end.to change { user.webauthn_credentials.count }.by(1) end end end @@ -292,15 +281,13 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do add_webauthn_credential(user) end - context 'when deletion succeeds' do - it 'redirects to 2FA methods list and shows flash success and deletes the credential', :aggregate_failures do - expect do - delete :destroy, params: { id: user.webauthn_credentials.take.id } - end.to change { user.webauthn_credentials.count }.by(-1) + it 'redirects to 2FA methods list and shows flash success and deletes the credential when deletion succeeds', :aggregate_failures do + expect do + delete :destroy, params: { id: user.webauthn_credentials.take.id } + end.to change { user.webauthn_credentials.count }.by(-1) - expect(response).to redirect_to settings_two_factor_authentication_methods_path - expect(flash[:success]).to be_present - end + expect(response).to redirect_to settings_two_factor_authentication_methods_path + expect(flash[:success]).to be_present end end From 1c3b5f4a7812a1c7ffaded56684882b02ca26b60 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 14 Dec 2023 09:02:33 -0500 Subject: [PATCH 22/28] Fix reference to non-existent var in CLI maintenance command (#28363) --- lib/mastodon/cli/maintenance.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mastodon/cli/maintenance.rb b/lib/mastodon/cli/maintenance.rb index 43fd7fab3..2e5243468 100644 --- a/lib/mastodon/cli/maintenance.rb +++ b/lib/mastodon/cli/maintenance.rb @@ -254,7 +254,7 @@ module Mastodon::CLI users = User.where(id: row['ids'].split(',')).sort_by(&:updated_at).reverse ref_user = users.shift say "Multiple users registered with e-mail address #{ref_user.email}.", :yellow - say "e-mail will be disabled for the following accounts: #{user.map { |user| user.account.acct }.join(', ')}", :yellow + say "e-mail will be disabled for the following accounts: #{users.map { |user| user.account.acct }.join(', ')}", :yellow say 'Please reach out to them and set another address with `tootctl account modify` or delete them.', :yellow users.each_with_index do |user, index| From e17faedffba569a5925b1da35214c1f56806f6b2 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 14 Dec 2023 09:04:55 -0500 Subject: [PATCH 23/28] Move default `meta` options from `InitialStateSerializer` to private method (AbcSize reduction) (#28355) --- .rubocop_todo.yml | 2 +- app/serializers/initial_state_serializer.rb | 50 +++++++++++---------- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 03543c8e0..03cc2e75d 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -26,7 +26,7 @@ Lint/NonLocalExitFromIterator: # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. Metrics/AbcSize: - Max: 125 + Max: 100 # Configuration parameters: CountBlocks, Max. Metrics/BlockNesting: diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index f606836ba..9f7921461 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -13,29 +13,7 @@ class InitialStateSerializer < ActiveModel::Serializer has_one :role, serializer: REST::RoleSerializer def meta - store = { - streaming_api_base_url: Rails.configuration.x.streaming_api_base_url, - access_token: object.token, - locale: I18n.locale, - domain: Addressable::IDNA.to_unicode(instance_presenter.domain), - title: instance_presenter.title, - admin: object.admin&.id&.to_s, - search_enabled: Chewy.enabled?, - repository: Mastodon::Version.repository, - source_url: instance_presenter.source_url, - version: instance_presenter.version, - limited_federation_mode: Rails.configuration.x.limited_federation_mode, - mascot: instance_presenter.mascot&.file&.url, - profile_directory: Setting.profile_directory, - trends_enabled: Setting.trends, - registrations_open: Setting.registrations_mode != 'none' && !Rails.configuration.x.single_user_mode, - timeline_preview: Setting.timeline_preview, - activity_api_enabled: Setting.activity_api_enabled, - single_user_mode: Rails.configuration.x.single_user_mode, - trends_as_landing_page: Setting.trends_as_landing_page, - status_page_url: Setting.status_page_url, - sso_redirect: sso_redirect, - } + store = default_meta_store if object.current_account store[:me] = object.current_account.id.to_s @@ -108,6 +86,32 @@ class InitialStateSerializer < ActiveModel::Serializer private + def default_meta_store + { + access_token: object.token, + activity_api_enabled: Setting.activity_api_enabled, + admin: object.admin&.id&.to_s, + domain: Addressable::IDNA.to_unicode(instance_presenter.domain), + limited_federation_mode: Rails.configuration.x.limited_federation_mode, + locale: I18n.locale, + mascot: instance_presenter.mascot&.file&.url, + profile_directory: Setting.profile_directory, + registrations_open: Setting.registrations_mode != 'none' && !Rails.configuration.x.single_user_mode, + repository: Mastodon::Version.repository, + search_enabled: Chewy.enabled?, + single_user_mode: Rails.configuration.x.single_user_mode, + source_url: instance_presenter.source_url, + sso_redirect: sso_redirect, + status_page_url: Setting.status_page_url, + streaming_api_base_url: Rails.configuration.x.streaming_api_base_url, + timeline_preview: Setting.timeline_preview, + title: instance_presenter.title, + trends_as_landing_page: Setting.trends_as_landing_page, + trends_enabled: Setting.trends, + version: instance_presenter.version, + } + end + def object_account_user object.current_account.user end From db897eaa5ad517154c531df2b5f0f97fdc53ad16 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 14 Dec 2023 09:07:54 -0500 Subject: [PATCH 24/28] Unwind `map` on single-item array in `spec/services/delete_account_service` spec (#28358) --- spec/services/delete_account_service_spec.rb | 58 +++++++++++--------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/spec/services/delete_account_service_spec.rb b/spec/services/delete_account_service_spec.rb index 8a19d3cf7..a2c57f1c1 100644 --- a/spec/services/delete_account_service_spec.rb +++ b/spec/services/delete_account_service_spec.rb @@ -50,11 +50,11 @@ RSpec.describe DeleteAccountService, type: :service do end def delete_associated_target_records - change do - [ - AccountPin.where(target_account: account), - ].map(&:count) - end.from([1]).to([0]) + change(account_pins_for_account, :count).from(1).to(0) + end + + def account_pins_for_account + AccountPin.where(target_account: account) end def delete_associated_target_notifications @@ -100,28 +100,34 @@ RSpec.describe DeleteAccountService, type: :service do it 'sends expected activities to followed and follower inboxes' do subject - expect(a_request(:post, account.inbox_url).with( - body: - hash_including({ - 'type' => 'Reject', - 'object' => hash_including({ - 'type' => 'Follow', - 'actor' => account.uri, - 'object' => ActivityPub::TagManager.instance.uri_for(local_follower), - }), - }) - )).to have_been_made.once + expect(post_to_inbox_with_reject).to have_been_made.once + expect(post_to_inbox_with_undo).to have_been_made.once + end - expect(a_request(:post, account.inbox_url).with( - body: hash_including({ - 'type' => 'Undo', - 'object' => hash_including({ - 'type' => 'Follow', - 'actor' => ActivityPub::TagManager.instance.uri_for(local_follower), - 'object' => account.uri, - }), - }) - )).to have_been_made.once + def post_to_inbox_with_undo + a_request(:post, account.inbox_url).with( + body: hash_including({ + 'type' => 'Undo', + 'object' => hash_including({ + 'type' => 'Follow', + 'actor' => ActivityPub::TagManager.instance.uri_for(local_follower), + 'object' => account.uri, + }), + }) + ) + end + + def post_to_inbox_with_reject + a_request(:post, account.inbox_url).with( + body: hash_including({ + 'type' => 'Reject', + 'object' => hash_including({ + 'type' => 'Follow', + 'actor' => account.uri, + 'object' => ActivityPub::TagManager.instance.uri_for(local_follower), + }), + }) + ) end end end From 1ee8d1e50e2e113af63348c6d16ee5cface22e33 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 15 Dec 2023 09:33:56 -0500 Subject: [PATCH 25/28] Assign a proc to `Rack::Request.ip_filter` instead of patching method (#28380) --- config/initializers/trusted_proxies.rb | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/config/initializers/trusted_proxies.rb b/config/initializers/trusted_proxies.rb index aa2f4510c..33bfddbdf 100644 --- a/config/initializers/trusted_proxies.rb +++ b/config/initializers/trusted_proxies.rb @@ -1,13 +1,8 @@ # frozen_string_literal: true -module Rack - class Request - def trusted_proxy?(ip) - if Rails.application.config.action_dispatch.trusted_proxies.nil? - super - else - Rails.application.config.action_dispatch.trusted_proxies.any? { |proxy| proxy === ip } - end - end - end +unless Rails.application.config.action_dispatch.trusted_proxies.nil? + # Rack is configured with a default collection of trusted proxies + # If Rails has been configured to use a specific list, configure + # Rack to use this Proc, which enforces the Rails-configured list. + Rack::Request.ip_filter = ->(ip) { Rails.application.config.action_dispatch.trusted_proxies.include?(ip) } end From e5717c9bc6cb5a1bea4c93048024f6247566f8ce Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 15 Dec 2023 09:34:24 -0500 Subject: [PATCH 26/28] Fix `Style/Lambda` cop (#28378) --- .rubocop_todo.yml | 8 -------- config/initializers/simple_form.rb | 2 +- config/routes.rb | 10 +++++----- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 03cc2e75d..c323aa877 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -386,14 +386,6 @@ Style/InverseMethods: - 'app/services/update_account_service.rb' - 'spec/controllers/activitypub/replies_controller_spec.rb' -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: line_count_dependent, lambda, literal -Style/Lambda: - Exclude: - - 'config/initializers/simple_form.rb' - - 'config/routes.rb' - # This cop supports unsafe autocorrection (--autocorrect-all). Style/MapToHash: Exclude: diff --git a/config/initializers/simple_form.rb b/config/initializers/simple_form.rb index 6d9d7b8ae..a8bc4b192 100644 --- a/config/initializers/simple_form.rb +++ b/config/initializers/simple_form.rb @@ -164,7 +164,7 @@ SimpleForm.setup do |config| # config.item_wrapper_class = nil # How the label text should be generated altogether with the required text. - config.label_text = lambda { |label, required, _explicit_label| "#{label} #{required}" } + config.label_text = ->(label, required, _explicit_label) { "#{label} #{required}" } # You can define the class to use on all labels. Default is nil. # config.label_class = nil diff --git a/config/routes.rb b/config/routes.rb index 150b26cf1..85c3b1855 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -51,7 +51,7 @@ Rails.application.routes.draw do get 'health', to: 'health#show' - authenticate :user, lambda { |u| u.role&.can?(:view_devops) } do + authenticate :user, ->(user) { user.role&.can?(:view_devops) } do mount Sidekiq::Web, at: 'sidekiq', as: :sidekiq mount PgHero::Engine, at: 'pghero', as: :pghero end @@ -105,10 +105,10 @@ Rails.application.routes.draw do } # rubocop:disable Style/FormatStringToken - those do not go through the usual formatting functions and are not safe to correct - get '/users/:username', to: redirect_with_vary('/@%{username}'), constraints: lambda { |req| req.format.nil? || req.format.html? } - get '/users/:username/following', to: redirect_with_vary('/@%{username}/following'), constraints: lambda { |req| req.format.nil? || req.format.html? } - get '/users/:username/followers', to: redirect_with_vary('/@%{username}/followers'), constraints: lambda { |req| req.format.nil? || req.format.html? } - get '/users/:username/statuses/:id', to: redirect_with_vary('/@%{username}/%{id}'), constraints: lambda { |req| req.format.nil? || req.format.html? } + get '/users/:username', to: redirect_with_vary('/@%{username}'), constraints: ->(req) { req.format.nil? || req.format.html? } + get '/users/:username/following', to: redirect_with_vary('/@%{username}/following'), constraints: ->(req) { req.format.nil? || req.format.html? } + get '/users/:username/followers', to: redirect_with_vary('/@%{username}/followers'), constraints: ->(req) { req.format.nil? || req.format.html? } + get '/users/:username/statuses/:id', to: redirect_with_vary('/@%{username}/%{id}'), constraints: ->(req) { req.format.nil? || req.format.html? } # rubocop:enable Style/FormatStringToken get '/authorize_follow', to: redirect { |_, request| "/authorize_interaction?#{request.params.to_query}" } From 3e336fe706a7b745c97efaca402e75a8ec5a7aeb Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 15 Dec 2023 09:38:12 -0500 Subject: [PATCH 27/28] Opt out of `Rails/SkipsModelValidations` cop in db/migrate (#28371) --- .rubocop.yml | 4 ++++ .rubocop_todo.yml | 16 ---------------- db/migrate/20230215074423_move_user_settings.rb | 2 +- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 68352e319..222160422 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -105,6 +105,10 @@ Rails/Exit: - 'config/boot.rb' - 'lib/mastodon/cli/*.rb' +Rails/SkipsModelValidations: + Exclude: + - 'db/*migrate/**/*' + # Reason: Some single letter camel case files shouldn't be split # https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecfilepath RSpec/FilePath: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index c323aa877..7d05090b3 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -181,22 +181,6 @@ Rails/SkipsModelValidations: - 'app/workers/move_worker.rb' - 'app/workers/scheduler/ip_cleanup_scheduler.rb' - 'app/workers/scheduler/scheduled_statuses_scheduler.rb' - - 'db/migrate/20161203164520_add_from_account_id_to_notifications.rb' - - 'db/migrate/20170105224407_add_shortcode_to_media_attachments.rb' - - 'db/migrate/20170209184350_add_reply_to_statuses.rb' - - 'db/migrate/20170304202101_add_type_to_media_attachments.rb' - - 'db/migrate/20180528141303_fix_accounts_unique_index.rb' - - 'db/migrate/20180609104432_migrate_web_push_subscriptions2.rb' - - 'db/migrate/20181207011115_downcase_custom_emoji_domains.rb' - - 'db/migrate/20190511134027_add_silenced_at_suspended_at_to_accounts.rb' - - 'db/migrate/20191007013357_update_pt_locales.rb' - - 'db/migrate/20220316233212_update_kurdish_locales.rb' - - 'db/post_migrate/20190511152737_remove_suspended_silenced_account_fields.rb' - - 'db/post_migrate/20200917193528_migrate_notifications_type.rb' - - 'db/post_migrate/20201017234926_fill_account_suspension_origin.rb' - - 'db/post_migrate/20220617202502_migrate_roles.rb' - - 'db/post_migrate/20221101190723_backfill_admin_action_logs.rb' - - 'db/post_migrate/20221206114142_backfill_admin_action_logs_again.rb' - 'lib/mastodon/cli/accounts.rb' - 'lib/mastodon/cli/maintenance.rb' - 'spec/lib/activitypub/activity/follow_spec.rb' diff --git a/db/migrate/20230215074423_move_user_settings.rb b/db/migrate/20230215074423_move_user_settings.rb index 27caac101..86231e49e 100644 --- a/db/migrate/20230215074423_move_user_settings.rb +++ b/db/migrate/20230215074423_move_user_settings.rb @@ -80,7 +80,7 @@ class MoveUserSettings < ActiveRecord::Migration[6.1] end end - user.update_column('settings', Oj.dump(user_settings)) # rubocop:disable Rails/SkipsModelValidations + user.update_column('settings', Oj.dump(user_settings)) end end end From b1dec09d203d535a3b0bc61e520e520ba7643878 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 15 Dec 2023 10:52:00 -0500 Subject: [PATCH 28/28] Fix `Style/InverseMethods` cop (#28377) --- .rubocop_todo.yml | 8 -------- app/models/custom_filter.rb | 2 +- app/services/update_account_service.rb | 2 +- spec/controllers/activitypub/replies_controller_spec.rb | 2 +- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 7d05090b3..d9b2ec814 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -362,14 +362,6 @@ Style/IfUnlessModifier: - 'config/initializers/devise.rb' - 'config/initializers/ffmpeg.rb' -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: InverseMethods, InverseBlocks. -Style/InverseMethods: - Exclude: - - 'app/models/custom_filter.rb' - - 'app/services/update_account_service.rb' - - 'spec/controllers/activitypub/replies_controller_spec.rb' - # This cop supports unsafe autocorrection (--autocorrect-all). Style/MapToHash: Exclude: diff --git a/app/models/custom_filter.rb b/app/models/custom_filter.rb index 0f4fd78cb..5a53e73ba 100644 --- a/app/models/custom_filter.rb +++ b/app/models/custom_filter.rb @@ -91,7 +91,7 @@ class CustomFilter < ApplicationRecord filters_hash.values.map { |cache| [cache.delete(:filter), cache] } end.to_a - active_filters.select { |custom_filter, _| !custom_filter.expired? } + active_filters.reject { |custom_filter, _| custom_filter.expired? } end def self.apply_cached_filters(cached_filters, status) diff --git a/app/services/update_account_service.rb b/app/services/update_account_service.rb index 1bbcfce3e..78a846e03 100644 --- a/app/services/update_account_service.rb +++ b/app/services/update_account_service.rb @@ -21,7 +21,7 @@ class UpdateAccountService < BaseService def authorize_all_follow_requests(account) follow_requests = FollowRequest.where(target_account: account) - follow_requests = follow_requests.preload(:account).select { |req| !req.account.silenced? } + follow_requests = follow_requests.preload(:account).reject { |req| req.account.silenced? } AuthorizeFollowWorker.push_bulk(follow_requests, limit: 1_000) do |req| [req.account_id, req.target_account_id] end diff --git a/spec/controllers/activitypub/replies_controller_spec.rb b/spec/controllers/activitypub/replies_controller_spec.rb index 7e6e0ffb0..5fc9698a3 100644 --- a/spec/controllers/activitypub/replies_controller_spec.rb +++ b/spec/controllers/activitypub/replies_controller_spec.rb @@ -123,7 +123,7 @@ RSpec.describe ActivityPub::RepliesController do end it 'uses ids for remote toots' do - remote_replies = page_json[:items].select { |x| !x.is_a?(Hash) } + remote_replies = page_json[:items].reject { |x| x.is_a?(Hash) } expect(remote_replies.all? { |item| item.is_a?(String) && !ActivityPub::TagManager.instance.local_uri?(item) }).to be true end