diff --git a/.eslintrc.js b/.eslintrc.js index e3afb1c9f..d11826282 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -20,10 +20,6 @@ module.exports = defineConfig({ es6: true, }, - globals: { - ATTACHMENT_HOST: false, - }, - parser: '@typescript-eslint/parser', plugins: [ @@ -79,7 +75,7 @@ module.exports = defineConfig({ ], }, ], - 'no-empty': 'off', + 'no-empty': ['error', { "allowEmptyCatch": true }], 'no-restricted-properties': [ 'error', { property: 'substring', message: 'Use .slice instead of .substring.' }, @@ -94,7 +90,6 @@ module.exports = defineConfig({ message: "Use '·' (middle dot) instead of '•' (bullet)", }, ], - 'no-self-assign': 'off', 'no-unused-expressions': 'error', 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': [ @@ -119,12 +114,10 @@ module.exports = defineConfig({ 'react/jsx-tag-spacing': 'error', 'react/jsx-uses-react': 'off', // not needed with new JSX transform 'react/jsx-wrap-multilines': 'error', - 'react/no-deprecated': 'off', 'react/react-in-jsx-scope': 'off', // not needed with new JSX transform 'react/self-closing-comp': 'error', // recommended values found in https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/v6.8.0/src/index.js#L46 - 'jsx-a11y/accessible-emoji': 'warn', 'jsx-a11y/click-events-have-key-events': 'off', 'jsx-a11y/label-has-associated-control': 'off', 'jsx-a11y/media-has-caption': 'off', @@ -139,23 +132,6 @@ module.exports = defineConfig({ // ], 'jsx-a11y/no-interactive-element-to-noninteractive-role': 'off', // recommended rule is: - // 'jsx-a11y/no-noninteractive-element-interactions': [ - // 'error', - // { - // body: ['onError', 'onLoad'], - // iframe: ['onError', 'onLoad'], - // img: ['onError', 'onLoad'], - // }, - // ], - 'jsx-a11y/no-noninteractive-element-interactions': [ - 'warn', - { - handlers: [ - 'onClick', - ], - }, - ], - // recommended rule is: // 'jsx-a11y/no-noninteractive-tabindex': [ // 'error', // { @@ -165,7 +141,6 @@ module.exports = defineConfig({ // }, // ], 'jsx-a11y/no-noninteractive-tabindex': 'off', - 'jsx-a11y/no-onchange': 'off', // recommended is full 'error' 'jsx-a11y/no-static-element-interactions': [ 'warn', diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 2cf7bec8e..03787dfac 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -14,6 +14,9 @@ // to `null` after any other rule set it to something. dependencyDashboardHeader: 'This issue lists Renovate updates and detected dependencies. Read the [Dependency Dashboard](https://docs.renovatebot.com/key-concepts/dashboard/) docs to learn more. Before approving any upgrade: read the description and comments in the [`renovate.json5` file](https://github.com/mastodon/mastodon/blob/main/.github/renovate.json5).', postUpdateOptions: ['yarnDedupeHighest'], + lockFileMaintenance: { + enabled: true, + }, packageRules: [ { // Require Dependency Dashboard Approval for major version bumps of these node packages diff --git a/.github/workflows/test-ruby.yml b/.github/workflows/test-ruby.yml index 513de2072..dd71fd253 100644 --- a/.github/workflows/test-ruby.yml +++ b/.github/workflows/test-ruby.yml @@ -285,9 +285,13 @@ jobs: - uses: actions/download-artifact@v4 with: - path: './public' + path: './' name: ${{ github.sha }} + - name: Expand archived asset artifacts + run: | + tar xvzf artifacts.tar.gz + - name: Set up Ruby environment uses: ./.github/actions/setup-ruby with: @@ -405,7 +409,7 @@ jobs: - uses: actions/download-artifact@v4 with: - path: './public' + path: './' name: ${{ github.sha }} - name: Set up Ruby environment diff --git a/.nvmrc b/.nvmrc index c61a3d77e..cecb93628 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -20.14 +20.15 diff --git a/.rubocop.yml b/.rubocop.yml index 6da1dc8cb..965f56f3e 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,7 +1,6 @@ --- AllCops: CacheRootDirectory: tmp - DisplayCopNames: true DisplayStyleGuide: true Exclude: - Vagrantfile @@ -10,7 +9,6 @@ AllCops: ExtraDetails: true NewCops: enable TargetRubyVersion: 3.1 # Oldest supported ruby version - UseCache: true inherit_from: - .rubocop/layout.yml diff --git a/.rubocop/rails.yml b/.rubocop/rails.yml index b83928dee..4e08f1ab9 100644 --- a/.rubocop/rails.yml +++ b/.rubocop/rails.yml @@ -5,10 +5,6 @@ Rails/FilePath: Rails/HttpStatus: EnforcedStyle: numeric -Rails/LexicallyScopedActionFilter: - Exclude: - - app/controllers/auth/* # Conflicts with `Lint/UselessMethodDefinition` for inherited controller actions - Rails/NegateInclude: Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 8a4e59803..b05d1bc6b 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by -# `rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp` -# using RuboCop version 1.63.5. +# `rubocop --auto-gen-config --auto-gen-only-exclude --no-offense-counts --no-auto-gen-timestamp` +# using RuboCop version 1.64.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -31,14 +31,6 @@ Rails/OutputSafety: Exclude: - 'config/initializers/simple_form.rb' -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: AllowedMethods, AllowedPatterns. -# AllowedMethods: ==, equal?, eql? -Style/ClassEqualityComparison: - Exclude: - - 'app/helpers/jsonld_helper.rb' - - 'app/serializers/activitypub/outbox_serializer.rb' - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowedVars. Style/FetchEnvVar: @@ -55,7 +47,6 @@ Style/FetchEnvVar: - 'config/initializers/vapid.rb' - 'lib/mastodon/redis_config.rb' - 'lib/tasks/repo.rake' - - 'spec/system/profile_spec.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, MaxUnannotatedPlaceholdersAllowed, AllowedMethods, AllowedPatterns. @@ -66,40 +57,10 @@ Style/FormatStringToken: - 'config/initializers/devise.rb' - 'lib/paperclip/color_extractor.rb' -# This cop supports unsafe autocorrection (--autocorrect-all). -Style/GlobalStdStream: - Exclude: - - 'config/environments/development.rb' - - 'config/environments/production.rb' - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. Style/GuardClause: - Exclude: - - 'app/lib/activitypub/activity/block.rb' - - 'app/lib/request.rb' - - 'app/lib/request_pool.rb' - - 'app/lib/webfinger.rb' - - 'app/lib/webfinger_resource.rb' - - 'app/models/concerns/account/counters.rb' - - 'app/models/concerns/user/ldap_authenticable.rb' - - 'app/models/tag.rb' - - 'app/models/user.rb' - - 'app/services/fan_out_on_write_service.rb' - - 'app/services/post_status_service.rb' - - 'app/services/process_hashtags_service.rb' - - 'app/workers/move_worker.rb' - - 'app/workers/redownload_avatar_worker.rb' - - 'app/workers/redownload_header_worker.rb' - - 'app/workers/redownload_media_worker.rb' - - 'app/workers/remote_account_refresh_worker.rb' - - 'config/initializers/devise.rb' - - 'lib/devise/strategies/two_factor_ldap_authenticatable.rb' - - 'lib/devise/strategies/two_factor_pam_authenticatable.rb' - - 'lib/mastodon/cli/accounts.rb' - - 'lib/mastodon/cli/maintenance.rb' - - 'lib/mastodon/cli/media.rb' - - 'lib/tasks/repo.rake' + Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). Style/HashTransformValues: @@ -121,16 +82,10 @@ Style/MutableConstant: - 'app/services/delete_account_service.rb' - 'lib/mastodon/migration_warning.rb' -# This cop supports safe autocorrection (--autocorrect). -Style/NilLambda: - Exclude: - - 'config/initializers/paperclip.rb' - # Configuration parameters: AllowedMethods. # AllowedMethods: respond_to_missing? Style/OptionalBooleanParameter: Exclude: - - 'app/helpers/admin/account_moderation_notes_helper.rb' - 'app/helpers/jsonld_helper.rb' - 'app/lib/admin/system_check/message.rb' - 'app/lib/request.rb' @@ -154,13 +109,6 @@ Style/RedundantConstantBase: - 'config/environments/production.rb' - 'config/initializers/sidekiq.rb' -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength. -# AllowedMethods: present?, blank?, presence, try, try! -Style/SafeNavigation: - Exclude: - - 'app/models/concerns/account/finder_concern.rb' - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: WordRegex. # SupportedStyles: percent, brackets diff --git a/Dockerfile b/Dockerfile index cd0c9218f..3a550f809 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,9 +19,9 @@ ARG NODE_MAJOR_VERSION="20" # Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"] ARG DEBIAN_VERSION="bookworm" # Node image to use for base image based on combined variables (ex: 20-bookworm-slim) -FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim as node +FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS node # Ruby image to use for base image based on combined variables (ex: 3.3.x-slim-bookworm) -FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} as ruby +FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby # Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA # Example: v4.3.0-nightly.2023.11.09+pr-123456 @@ -117,7 +117,7 @@ RUN \ ; # Create temporary build layer from base image -FROM ruby as build +FROM ruby AS build # Copy Node package configuration files into working directory COPY package.json yarn.lock .yarnrc.yml /opt/mastodon/ @@ -185,7 +185,7 @@ RUN \ corepack prepare --activate; # Create temporary libvips specific build layer from build layer -FROM build as libvips +FROM build AS libvips # libvips version to compile, change with [--build-arg VIPS_VERSION="8.15.2"] # renovate: datasource=github-releases depName=libvips packageName=libvips/libvips @@ -205,7 +205,7 @@ RUN \ ninja install; # Create temporary ffmpeg specific build layer from build layer -FROM build as ffmpeg +FROM build AS ffmpeg # ffmpeg version to compile, change with [--build-arg FFMPEG_VERSION="7.0.x"] # renovate: datasource=repology depName=ffmpeg packageName=openpkg_current/ffmpeg @@ -247,7 +247,7 @@ RUN \ make install; # Create temporary bundler specific build layer from build layer -FROM build as bundler +FROM build AS bundler ARG TARGETPLATFORM @@ -269,7 +269,7 @@ RUN \ bundle install -j"$(nproc)"; # Create temporary node specific build layer from build layer -FROM build as yarn +FROM build AS yarn ARG TARGETPLATFORM @@ -286,7 +286,7 @@ RUN \ yarn workspaces focus --production @mastodon/mastodon; # Create temporary assets build layer from build layer -FROM build as precompiler +FROM build AS precompiler # Copy Mastodon sources into precompiler layer COPY . /opt/mastodon/ @@ -310,7 +310,7 @@ RUN \ rm -fr /opt/mastodon/tmp; # Prep final Mastodon Ruby layer -FROM ruby as mastodon +FROM ruby AS mastodon ARG TARGETPLATFORM diff --git a/Gemfile b/Gemfile index ecd9088d3..f2d7d098d 100644 --- a/Gemfile +++ b/Gemfile @@ -69,7 +69,7 @@ gem 'oj', '~> 3.14' gem 'ox', '~> 2.14' gem 'parslet' gem 'premailer-rails' -gem 'public_suffix', '~> 5.0' +gem 'public_suffix', '~> 6.0' gem 'pundit', '~> 2.3' gem 'rack-attack', '~> 6.6' gem 'rack-cors', '~> 2.0', require: 'rack/cors' @@ -105,7 +105,7 @@ gem 'private_address_check', '~> 0.5' gem 'opentelemetry-api', '~> 1.2.5' group :opentelemetry do - gem 'opentelemetry-exporter-otlp', '~> 0.27.0', require: false + gem 'opentelemetry-exporter-otlp', '~> 0.28.0', require: false gem 'opentelemetry-instrumentation-active_job', '~> 0.7.1', require: false gem 'opentelemetry-instrumentation-active_model_serializers', '~> 0.20.1', require: false gem 'opentelemetry-instrumentation-concurrent_ruby', '~> 0.21.2', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 3a76cc50c..0fe1c03b2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -89,8 +89,8 @@ GEM minitest (>= 5.1) mutex_m tzinfo (~> 2.0) - addressable (2.8.6) - public_suffix (>= 2.0.2, < 6.0) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) aes_key_wrap (1.1.0) android_key_attestation (0.3.0) annotate (3.2.0) @@ -143,7 +143,7 @@ GEM brpoplpush-redis_script (0.1.3) concurrent-ruby (~> 1.0, >= 1.0.5) redis (>= 1.0, < 6) - builder (3.2.4) + builder (3.3.0) bundler-audit (0.9.1) bundler (>= 1.2.0, < 3) thor (~> 1.0) @@ -195,7 +195,7 @@ GEM railties (>= 4.1.0) responders warden (~> 1.2.3) - devise-two-factor (5.0.0) + devise-two-factor (5.1.0) activesupport (~> 7.0) devise (~> 4.0) railties (~> 7.0) @@ -226,7 +226,7 @@ GEM htmlentities (~> 4.3.3) launchy (~> 2.1) mail (~> 2.7) - erubi (1.12.0) + erubi (1.13.0) et-orbi (1.2.11) tzinfo excon (0.110.0) @@ -398,6 +398,7 @@ GEM llhttp-ffi (0.5.0) ffi-compiler (~> 1.0) rake (~> 13.0) + logger (1.6.0) lograge (0.14.0) actionpack (>= 4) activesupport (>= 4) @@ -489,8 +490,8 @@ GEM opentelemetry-api (1.2.5) opentelemetry-common (0.20.1) opentelemetry-api (~> 1.0) - opentelemetry-exporter-otlp (0.27.0) - google-protobuf (~> 3.14) + opentelemetry-exporter-otlp (0.28.0) + google-protobuf (>= 3.18) googleapis-common-protos-types (~> 1.3) opentelemetry-api (~> 1.1) opentelemetry-common (~> 0.20) @@ -528,32 +529,27 @@ GEM opentelemetry-instrumentation-concurrent_ruby (0.21.3) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-excon (0.22.1) + opentelemetry-instrumentation-excon (0.22.3) opentelemetry-api (~> 1.0) - opentelemetry-common (~> 0.20.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-faraday (0.24.2) + opentelemetry-instrumentation-faraday (0.24.4) opentelemetry-api (~> 1.0) - opentelemetry-common (~> 0.20.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-instrumentation-http (0.23.3) opentelemetry-api (~> 1.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-http_client (0.22.4) + opentelemetry-instrumentation-http_client (0.22.6) opentelemetry-api (~> 1.0) - opentelemetry-common (~> 0.20.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-net_http (0.22.4) + opentelemetry-instrumentation-net_http (0.22.6) opentelemetry-api (~> 1.0) - opentelemetry-common (~> 0.20.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-instrumentation-pg (0.27.3) opentelemetry-api (~> 1.0) opentelemetry-helpers-sql-obfuscation opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-rack (0.24.3) + opentelemetry-instrumentation-rack (0.24.5) opentelemetry-api (~> 1.0) - opentelemetry-common (~> 0.20.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-instrumentation-rails (0.30.2) opentelemetry-api (~> 1.0) @@ -564,13 +560,11 @@ GEM opentelemetry-instrumentation-active_record (~> 0.7.0) opentelemetry-instrumentation-active_support (~> 0.5.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-redis (0.25.4) + opentelemetry-instrumentation-redis (0.25.6) opentelemetry-api (~> 1.0) - opentelemetry-common (~> 0.20.0) opentelemetry-instrumentation-base (~> 0.22.1) - opentelemetry-instrumentation-sidekiq (0.25.3) + opentelemetry-instrumentation-sidekiq (0.25.5) opentelemetry-api (~> 1.0) - opentelemetry-common (~> 0.20.0) opentelemetry-instrumentation-base (~> 0.22.1) opentelemetry-registry (0.3.1) opentelemetry-api (~> 1.1) @@ -609,7 +603,7 @@ GEM railties (>= 7.0.0) psych (5.1.2) stringio - public_suffix (5.1.1) + public_suffix (6.0.0) puma (6.4.2) nio4r (~> 2.0) pundit (2.3.2) @@ -682,7 +676,7 @@ GEM link_header (~> 0.0, >= 0.0.8) rdf-normalize (0.7.0) rdf (~> 3.3) - rdoc (6.6.3.1) + rdoc (6.7.0) psych (>= 4.0.0) redcarpet (3.6.0) redis (4.8.1) @@ -709,7 +703,7 @@ GEM rqrcode_core (1.2.0) rspec-core (3.13.0) rspec-support (~> 3.13.0) - rspec-expectations (3.13.0) + rspec-expectations (3.13.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-github (2.4.0) @@ -717,7 +711,7 @@ GEM rspec-mocks (3.13.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-rails (6.1.2) + rspec-rails (6.1.3) actionpack (>= 6.1) activesupport (>= 6.1) railties (>= 6.1) @@ -778,8 +772,9 @@ GEM scenic (1.8.0) activerecord (>= 4.0.0) railties (>= 4.0.0) - selenium-webdriver (4.21.1) + selenium-webdriver (4.22.0) base64 (~> 0.2) + logger (~> 1.4) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) @@ -898,7 +893,7 @@ GEM xorcist (1.1.3) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.15) + zeitwerk (2.6.16) PLATFORMS ruby @@ -979,7 +974,7 @@ DEPENDENCIES omniauth-saml (~> 2.0) omniauth_openid_connect (~> 0.6.1) opentelemetry-api (~> 1.2.5) - opentelemetry-exporter-otlp (~> 0.27.0) + opentelemetry-exporter-otlp (~> 0.28.0) opentelemetry-instrumentation-active_job (~> 0.7.1) opentelemetry-instrumentation-active_model_serializers (~> 0.20.1) opentelemetry-instrumentation-concurrent_ruby (~> 0.21.2) @@ -1001,7 +996,7 @@ DEPENDENCIES premailer-rails private_address_check (~> 0.5) propshaft - public_suffix (~> 5.0) + public_suffix (~> 6.0) puma (~> 6.3) pundit (~> 2.3) rack (~> 2.2.7) diff --git a/app/controllers/api/v2_alpha/notifications_controller.rb b/app/controllers/api/v2_alpha/notifications_controller.rb index 19d3ac901..edba23ab4 100644 --- a/app/controllers/api/v2_alpha/notifications_controller.rb +++ b/app/controllers/api/v2_alpha/notifications_controller.rb @@ -15,7 +15,7 @@ class Api::V2Alpha::NotificationsController < Api::BaseController @relationships = StatusRelationshipsPresenter.new(target_statuses_from_notifications, current_user&.account_id) end - render json: @notifications.map { |notification| NotificationGroup.from_notification(notification) }, each_serializer: REST::NotificationGroupSerializer, relationships: @relationships, group_metadata: @group_metadata + render json: @notifications.map { |notification| NotificationGroup.from_notification(notification, max_id: @group_metadata.dig(notification.group_key, :max_id)) }, each_serializer: REST::NotificationGroupSerializer, relationships: @relationships, group_metadata: @group_metadata end def show diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index f858c0ad9..e5a2ac027 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -25,6 +25,14 @@ class Auth::RegistrationsController < Devise::RegistrationsController super(&:build_invite_request) end + def edit # rubocop:disable Lint/UselessMethodDefinition + super + end + + def create # rubocop:disable Lint/UselessMethodDefinition + super + end + def update super do |resource| resource.clear_other_sessions(current_session.session_id) if resource.saved_change_to_encrypted_password? diff --git a/app/helpers/jsonld_helper.rb b/app/helpers/jsonld_helper.rb index b0f2077db..932a3420d 100644 --- a/app/helpers/jsonld_helper.rb +++ b/app/helpers/jsonld_helper.rb @@ -141,7 +141,7 @@ module JsonLdHelper def safe_for_forwarding?(original, compacted) original.without('@context', 'signature').all? do |key, value| compacted_value = compacted[key] - return false unless value.class == compacted_value.class + return false unless value.instance_of?(compacted_value.class) if value.is_a?(Hash) safe_for_forwarding?(value, compacted_value) diff --git a/app/javascript/mastodon/actions/streaming.js b/app/javascript/mastodon/actions/streaming.js index 9daeb3c60..e7fe1c53e 100644 --- a/app/javascript/mastodon/actions/streaming.js +++ b/app/javascript/mastodon/actions/streaming.js @@ -77,7 +77,7 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti }, onDisconnect() { - dispatch(disconnectTimeline(timelineId)); + dispatch(disconnectTimeline({ timeline: timelineId })); if (options.fallback) { // @ts-expect-error diff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js index dc37cdf1f..4ca3c3a15 100644 --- a/app/javascript/mastodon/actions/timelines.js +++ b/app/javascript/mastodon/actions/timelines.js @@ -6,9 +6,11 @@ import { usePendingItems as preferPendingItems } from 'mastodon/initial_state'; import { importFetchedStatus, importFetchedStatuses } from './importer'; import { submitMarkers } from './markers'; +import {timelineDelete} from './timelines_typed'; + +export { disconnectTimeline } from './timelines_typed'; export const TIMELINE_UPDATE = 'TIMELINE_UPDATE'; -export const TIMELINE_DELETE = 'TIMELINE_DELETE'; export const TIMELINE_CLEAR = 'TIMELINE_CLEAR'; export const TIMELINE_EXPAND_REQUEST = 'TIMELINE_EXPAND_REQUEST'; @@ -17,7 +19,6 @@ export const TIMELINE_EXPAND_FAIL = 'TIMELINE_EXPAND_FAIL'; export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP'; export const TIMELINE_LOAD_PENDING = 'TIMELINE_LOAD_PENDING'; -export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT'; export const TIMELINE_CONNECT = 'TIMELINE_CONNECT'; export const TIMELINE_MARK_AS_PARTIAL = 'TIMELINE_MARK_AS_PARTIAL'; @@ -62,16 +63,10 @@ export function updateTimeline(timeline, status, accept) { export function deleteFromTimelines(id) { return (dispatch, getState) => { const accountId = getState().getIn(['statuses', id, 'account']); - const references = getState().get('statuses').filter(status => status.get('reblog') === id).map(status => status.get('id')); + const references = getState().get('statuses').filter(status => status.get('reblog') === id).map(status => status.get('id')).valueSeq().toJSON(); const reblogOf = getState().getIn(['statuses', id, 'reblog'], null); - dispatch({ - type: TIMELINE_DELETE, - id, - accountId, - references, - reblogOf, - }); + dispatch(timelineDelete({ statusId: id, accountId, references, reblogOf })); }; } @@ -225,12 +220,6 @@ export function connectTimeline(timeline) { }; } -export const disconnectTimeline = timeline => ({ - type: TIMELINE_DISCONNECT, - timeline, - usePendingItems: preferPendingItems, -}); - export const markAsPartial = timeline => ({ type: TIMELINE_MARK_AS_PARTIAL, timeline, diff --git a/app/javascript/mastodon/actions/timelines_typed.ts b/app/javascript/mastodon/actions/timelines_typed.ts new file mode 100644 index 000000000..07d82b2f0 --- /dev/null +++ b/app/javascript/mastodon/actions/timelines_typed.ts @@ -0,0 +1,20 @@ +import { createAction } from '@reduxjs/toolkit'; + +import { usePendingItems as preferPendingItems } from 'mastodon/initial_state'; + +export const disconnectTimeline = createAction( + 'timeline/disconnect', + ({ timeline }: { timeline: string }) => ({ + payload: { + timeline, + usePendingItems: preferPendingItems, + }, + }), +); + +export const timelineDelete = createAction<{ + statusId: string; + accountId: string; + references: string[]; + reblogOf: string | null; +}>('timelines/delete'); diff --git a/app/javascript/mastodon/features/account_timeline/index.jsx b/app/javascript/mastodon/features/account_timeline/index.jsx index 0478f7a1a..dc69f83e7 100644 --- a/app/javascript/mastodon/features/account_timeline/index.jsx +++ b/app/javascript/mastodon/features/account_timeline/index.jsx @@ -133,7 +133,7 @@ class AccountTimeline extends ImmutablePureComponent { } if (prevProps.accountId === me && accountId !== me) { - dispatch(disconnectTimeline(`account:${me}`)); + dispatch(disconnectTimeline({ timeline: `account:${me}` })); } } @@ -141,7 +141,7 @@ class AccountTimeline extends ImmutablePureComponent { const { dispatch, accountId } = this.props; if (accountId === me) { - dispatch(disconnectTimeline(`account:${me}`)); + dispatch(disconnectTimeline({ timeline: `account:${me}` })); } } diff --git a/app/javascript/mastodon/locales/hi.json b/app/javascript/mastodon/locales/hi.json index 5dc99dd76..a2da55da8 100644 --- a/app/javascript/mastodon/locales/hi.json +++ b/app/javascript/mastodon/locales/hi.json @@ -80,6 +80,7 @@ "admin.dashboard.retention.cohort_size": "नये उपयोगकर्ता", "admin.impact_report.instance_accounts": "ये अकाउंट प्रोफाइल मिटा देगा", "admin.impact_report.instance_followers": "हमारे यूजर्स इन फॉलोअर्स को खो देंगे", + "admin.impact_report.instance_follows": "उनके उपयोगकर्ता इतने फ़ॉलोअर खो देंगे", "admin.impact_report.title": "प्रभावकां सारांश", "alert.rate_limited.message": "कृप्या {retry_time, time, medium} के बाद दुबारा कोशिश करें", "alert.rate_limited.title": "सीमित दर", @@ -88,6 +89,7 @@ "announcement.announcement": "घोषणा", "attachments_list.unprocessed": "(असंसाधित)", "audio.hide": "हाईड ऑडियो", + "block_modal.remote_users_caveat": "हम {domain} को आपके निर्णय का सम्मान करने को कहेंगे।हालाकि इसकी आपूर्ति कि प्रत्याभूति नहीं हे। क्योंकि कुछ सर्वर ब्लॉक को अलग तरह से निभा सकते हे। अभी भी सार्वजानिक पोस्ट लोग- इन बगैर के उपयोगकर्ताओं को दिख सकती हैं।", "block_modal.show_less": "कम दिखाएं", "block_modal.show_more": "और दिखाएँ", "block_modal.they_cant_mention": "वे आपको मेंशन या फॉलो नहीं कर सकते", @@ -205,7 +207,12 @@ "dismissable_banner.dismiss": "डिसमिस", "dismissable_banner.explore_links": "इन समाचारों के बारे में लोगों द्वारा इस पर और डेसेंट्रलीसेड नेटवर्क के अन्य सर्वरों पर अभी बात की जा रही है।", "dismissable_banner.explore_tags": "ये हैशटैग अभी इस पर और डेसेंट्रलीसेड नेटवर्क के अन्य सर्वरों पर लोगों के बीच कर्षण प्राप्त कर रहे हैं।", + "dismissable_banner.public_timeline": "यह ताजा सार्वजनिक पोस्ट है जिसका सामाजिक वेब {domain} के लोगो द्वारा अनुसरण हो रहा हैं।", "domain_block_modal.block": "सर्वर ब्लॉक करें", + "domain_block_modal.block_account_instead": "इसकी जगह यह @{name} रखें", + "domain_block_modal.they_can_interact_with_old_posts": "इस सर्वर की लोग आपकी पूरानी पोस्ट्स का अनुसरण किया जा sakta है।", + "domain_block_modal.they_cant_follow": "इस सर्वर मेसे कोई भी आपका अनुसरण नहीं कर सकता।", + "domain_block_modal.they_wont_know": "उनको पता नहीं चलेगा कि वे अवरोधित किए गए है।", "domain_block_modal.title": "डोमेन ब्लॉक करें", "domain_pill.server": "सर्वर", "domain_pill.username": "यूज़रनेम", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index aa05887d6..c4c084d98 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -32,7 +32,7 @@ "account.featured_tags.last_status_never": "게시물 없음", "account.featured_tags.title": "{name} 님의 추천 해시태그", "account.follow": "팔로우", - "account.follow_back": "맞팔로우", + "account.follow_back": "맞팔로우 하기", "account.followers": "팔로워", "account.followers.empty": "아직 아무도 이 사용자를 팔로우하고 있지 않습니다.", "account.followers_counter": "{counter} 팔로워", @@ -53,7 +53,7 @@ "account.mute_notifications_short": "알림 뮤트", "account.mute_short": "뮤트", "account.muted": "뮤트됨", - "account.mutual": "상호 팔로우", + "account.mutual": "맞팔로우 중", "account.no_bio": "제공된 설명이 없습니다.", "account.open_original_page": "원본 페이지 열기", "account.posts": "게시물", diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js index 97218e9f7..9f66c0963 100644 --- a/app/javascript/mastodon/reducers/compose.js +++ b/app/javascript/mastodon/reducers/compose.js @@ -1,5 +1,7 @@ import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable'; +import { timelineDelete } from 'mastodon/actions/timelines_typed'; + import { COMPOSE_MOUNT, COMPOSE_UNMOUNT, @@ -51,7 +53,6 @@ import { } from '../actions/compose'; import { REDRAFT } from '../actions/statuses'; import { STORE_HYDRATE } from '../actions/store'; -import { TIMELINE_DELETE } from '../actions/timelines'; import { me } from '../initial_state'; import { unescapeHTML } from '../utils/html'; import { uuid } from '../uuid'; @@ -446,10 +447,10 @@ export default function compose(state = initialState, action) { return updateSuggestionTags(state, action.token); case COMPOSE_TAG_HISTORY_UPDATE: return state.set('tagHistory', fromJS(action.tags)); - case TIMELINE_DELETE: - if (action.id === state.get('in_reply_to')) { + case timelineDelete.type: + if (action.payload.statusId === state.get('in_reply_to')) { return state.set('in_reply_to', null); - } else if (action.id === state.get('id')) { + } else if (action.payload.statusId === state.get('id')) { return state.set('id', null); } else { return state; diff --git a/app/javascript/mastodon/reducers/contexts.js b/app/javascript/mastodon/reducers/contexts.js index f7d7419a4..b2c6f3f1a 100644 --- a/app/javascript/mastodon/reducers/contexts.js +++ b/app/javascript/mastodon/reducers/contexts.js @@ -1,11 +1,13 @@ import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; +import { timelineDelete } from 'mastodon/actions/timelines_typed'; + import { blockAccountSuccess, muteAccountSuccess, } from '../actions/accounts'; import { CONTEXT_FETCH_SUCCESS } from '../actions/statuses'; -import { TIMELINE_DELETE, TIMELINE_UPDATE } from '../actions/timelines'; +import { TIMELINE_UPDATE } from '../actions/timelines'; import { compareId } from '../compare_id'; const initialState = ImmutableMap({ @@ -97,8 +99,8 @@ export default function replies(state = initialState, action) { return filterContexts(state, action.payload.relationship, action.payload.statuses); case CONTEXT_FETCH_SUCCESS: return normalizeContext(state, action.id, action.ancestors, action.descendants); - case TIMELINE_DELETE: - return deleteFromContexts(state, [action.id]); + case timelineDelete.type: + return deleteFromContexts(state, [action.payload.statusId]); case TIMELINE_UPDATE: return updateContext(state, action.status); default: diff --git a/app/javascript/mastodon/reducers/modal.ts b/app/javascript/mastodon/reducers/modal.ts index 368f26542..ca85eb8c7 100644 --- a/app/javascript/mastodon/reducers/modal.ts +++ b/app/javascript/mastodon/reducers/modal.ts @@ -1,10 +1,11 @@ import type { Reducer } from '@reduxjs/toolkit'; import { Record as ImmutableRecord, Stack } from 'immutable'; +import { timelineDelete } from 'mastodon/actions/timelines_typed'; + import { COMPOSE_UPLOAD_CHANGE_SUCCESS } from '../actions/compose'; import type { ModalType } from '../actions/modal'; import { openModal, closeModal } from '../actions/modal'; -import { TIMELINE_DELETE } from '../actions/timelines'; export type ModalProps = Record; interface Modal { @@ -72,10 +73,10 @@ export const modalReducer: Reducer = (state = initialState, action) => { // TODO: type those actions else if (action.type === COMPOSE_UPLOAD_CHANGE_SUCCESS) return popModal(state, { modalType: 'FOCAL_POINT', ignoreFocus: false }); - else if (action.type === TIMELINE_DELETE) + else if (timelineDelete.match(action)) return state.update('stack', (stack) => stack.filterNot( - (modal) => modal.get('modalProps').statusId === action.id, + (modal) => modal.get('modalProps').statusId === action.payload.statusId, ), ); else return state; diff --git a/app/javascript/mastodon/reducers/notifications.js b/app/javascript/mastodon/reducers/notifications.js index 64cddcb66..79aa5651f 100644 --- a/app/javascript/mastodon/reducers/notifications.js +++ b/app/javascript/mastodon/reducers/notifications.js @@ -1,6 +1,7 @@ import { fromJS, Map as ImmutableMap, List as ImmutableList } from 'immutable'; import { blockDomainSuccess } from 'mastodon/actions/domain_blocks'; +import { timelineDelete } from 'mastodon/actions/timelines_typed'; import { authorizeFollowRequestSuccess, @@ -30,7 +31,7 @@ import { NOTIFICATIONS_SET_BROWSER_SUPPORT, NOTIFICATIONS_SET_BROWSER_PERMISSION, } from '../actions/notifications'; -import { TIMELINE_DELETE, TIMELINE_DISCONNECT } from '../actions/timelines'; +import { disconnectTimeline } from '../actions/timelines'; import { compareId } from '../compare_id'; const initialState = ImmutableMap({ @@ -291,11 +292,11 @@ export default function notifications(state = initialState, action) { return filterNotifications(state, [action.payload.id], 'follow_request'); case NOTIFICATIONS_CLEAR: return state.set('items', ImmutableList()).set('pendingItems', ImmutableList()).set('hasMore', false); - case TIMELINE_DELETE: - return deleteByStatus(state, action.id); - case TIMELINE_DISCONNECT: - return action.timeline === 'home' ? - state.update(action.usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(null) : items) : + case timelineDelete.type: + return deleteByStatus(state, action.payload.statusId); + case disconnectTimeline.type: + return action.payload.timeline === 'home' ? + state.update(action.payload.usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(null) : items) : state; case NOTIFICATIONS_MARK_AS_READ: const lastNotification = state.get('items').find(item => item !== null); diff --git a/app/javascript/mastodon/reducers/picture_in_picture.ts b/app/javascript/mastodon/reducers/picture_in_picture.ts index 0feddcb70..10d4f1fae 100644 --- a/app/javascript/mastodon/reducers/picture_in_picture.ts +++ b/app/javascript/mastodon/reducers/picture_in_picture.ts @@ -4,8 +4,7 @@ import { deployPictureInPictureAction, removePictureInPicture, } from 'mastodon/actions/picture_in_picture'; - -import { TIMELINE_DELETE } from '../actions/timelines'; +import { timelineDelete } from 'mastodon/actions/timelines_typed'; export interface PIPMediaProps { src: string; @@ -49,8 +48,9 @@ export const pictureInPictureReducer: Reducer = ( ...action.payload.props, }; else if (removePictureInPicture.match(action)) return initialState; - else if (action.type === TIMELINE_DELETE) - if (state.type && state.statusId === action.id) return initialState; + else if (timelineDelete.match(action)) + if (state.type && state.statusId === action.payload.statusId) + return initialState; return state; }; diff --git a/app/javascript/mastodon/reducers/statuses.js b/app/javascript/mastodon/reducers/statuses.js index ca766f73a..d92174f80 100644 --- a/app/javascript/mastodon/reducers/statuses.js +++ b/app/javascript/mastodon/reducers/statuses.js @@ -1,5 +1,7 @@ import { Map as ImmutableMap, fromJS } from 'immutable'; +import { timelineDelete } from 'mastodon/actions/timelines_typed'; + import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer'; import { normalizeStatusTranslation } from '../actions/importer/normalizer'; import { @@ -27,7 +29,6 @@ import { STATUS_FETCH_REQUEST, STATUS_FETCH_FAIL, } from '../actions/statuses'; -import { TIMELINE_DELETE } from '../actions/timelines'; const importStatus = (state, status) => state.set(status.id, fromJS(status)); @@ -114,8 +115,8 @@ export default function statuses(state = initialState, action) { }); case STATUS_COLLAPSE: return state.setIn([action.id, 'collapsed'], action.isCollapsed); - case TIMELINE_DELETE: - return deleteStatus(state, action.id, action.references); + case timelineDelete.type: + return deleteStatus(state, action.payload.statusId, action.payload.references); case STATUS_TRANSLATE_SUCCESS: return statusTranslateSuccess(state, action.id, action.translation); case STATUS_TRANSLATE_UNDO: diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js index 4c9ab98a8..b07281ab8 100644 --- a/app/javascript/mastodon/reducers/timelines.js +++ b/app/javascript/mastodon/reducers/timelines.js @@ -1,5 +1,7 @@ import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable'; +import { timelineDelete } from 'mastodon/actions/timelines_typed'; + import { blockAccountSuccess, muteAccountSuccess, @@ -7,19 +9,18 @@ import { } from '../actions/accounts'; import { TIMELINE_UPDATE, - TIMELINE_DELETE, TIMELINE_CLEAR, TIMELINE_EXPAND_SUCCESS, TIMELINE_EXPAND_REQUEST, TIMELINE_EXPAND_FAIL, TIMELINE_SCROLL_TOP, TIMELINE_CONNECT, - TIMELINE_DISCONNECT, TIMELINE_LOAD_PENDING, TIMELINE_MARK_AS_PARTIAL, TIMELINE_INSERT, TIMELINE_GAP, TIMELINE_SUGGESTIONS, + disconnectTimeline, } from '../actions/timelines'; import { compareId } from '../compare_id'; @@ -158,7 +159,7 @@ const filterTimelines = (state, relationship, statuses) => { return; } - references = statuses.filter(item => item.get('reblog') === status.get('id')).map(item => item.get('id')); + references = statuses.filter(item => item.get('reblog') === status.get('id')).map(item => item.get('id')).valueSeq().toJSON(); state = deleteStatus(state, status.get('id'), references, relationship.id); }); @@ -201,8 +202,8 @@ export default function timelines(state = initialState, action) { return expandNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial, action.isLoadingRecent, action.usePendingItems); case TIMELINE_UPDATE: return updateTimeline(state, action.timeline, fromJS(action.status), action.usePendingItems); - case TIMELINE_DELETE: - return deleteStatus(state, action.id, action.references, action.reblogOf); + case timelineDelete.type: + return deleteStatus(state, action.payload.statusId, action.payload.references, action.payload.reblogOf); case TIMELINE_CLEAR: return clearTimeline(state, action.timeline); case blockAccountSuccess.type: @@ -214,11 +215,11 @@ export default function timelines(state = initialState, action) { return updateTop(state, action.timeline, action.top); case TIMELINE_CONNECT: return state.update(action.timeline, initialTimeline, map => reconnectTimeline(map, action.usePendingItems)); - case TIMELINE_DISCONNECT: + case disconnectTimeline.type: return state.update( - action.timeline, + action.payload.timeline, initialTimeline, - map => map.set('online', false).update(action.usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(TIMELINE_GAP) : items), + map => map.set('online', false).update(action.payload.usePendingItems ? 'pendingItems' : 'items', items => items.first() ? items.unshift(TIMELINE_GAP) : items), ); case TIMELINE_MARK_AS_PARTIAL: return state.update( diff --git a/app/javascript/mastodon/store/typed_functions.ts b/app/javascript/mastodon/store/typed_functions.ts index dae37e622..e5820149d 100644 --- a/app/javascript/mastodon/store/typed_functions.ts +++ b/app/javascript/mastodon/store/typed_functions.ts @@ -82,13 +82,19 @@ export function createThunk( const discardLoadDataInPayload = Symbol('discardLoadDataInPayload'); type DiscardLoadData = typeof discardLoadDataInPayload; -type OnData = ( +type OnData = ( data: LoadDataResult, api: AppThunkApi & { + actionArg: ActionArg; discardLoadData: DiscardLoadData; }, ) => ReturnedData | DiscardLoadData | Promise; +type LoadData = ( + args: Args, + api: AppThunkApi, +) => Promise; + type ArgsType = Record | undefined; // Overload when there is no `onData` method, the payload is the `onData` result @@ -101,18 +107,18 @@ export function createDataLoadingThunk( // Overload when the `onData` method returns discardLoadDataInPayload, then the payload is empty export function createDataLoadingThunk( name: string, - loadData: (args: Args) => Promise, + loadData: LoadData, onDataOrThunkOptions?: | AppThunkOptions - | OnData, + | OnData, thunkOptions?: AppThunkOptions, ): ReturnType>; // Overload when the `onData` method returns nothing, then the mayload is the `onData` result export function createDataLoadingThunk( name: string, - loadData: (args: Args) => Promise, - onDataOrThunkOptions?: AppThunkOptions | OnData, + loadData: LoadData, + onDataOrThunkOptions?: AppThunkOptions | OnData, thunkOptions?: AppThunkOptions, ): ReturnType>; @@ -123,8 +129,10 @@ export function createDataLoadingThunk< Returned, >( name: string, - loadData: (args: Args) => Promise, - onDataOrThunkOptions?: AppThunkOptions | OnData, + loadData: LoadData, + onDataOrThunkOptions?: + | AppThunkOptions + | OnData, thunkOptions?: AppThunkOptions, ): ReturnType>; @@ -159,11 +167,13 @@ export function createDataLoadingThunk< Returned, >( name: string, - loadData: (args: Args) => Promise, - onDataOrThunkOptions?: AppThunkOptions | OnData, + loadData: LoadData, + onDataOrThunkOptions?: + | AppThunkOptions + | OnData, maybeThunkOptions?: AppThunkOptions, ) { - let onData: OnData | undefined; + let onData: OnData | undefined; let thunkOptions: AppThunkOptions | undefined; if (typeof onDataOrThunkOptions === 'function') onData = onDataOrThunkOptions; @@ -177,7 +187,10 @@ export function createDataLoadingThunk< return createThunk( name, async (arg, { getState, dispatch }) => { - const data = await loadData(arg); + const data = await loadData(arg, { + dispatch, + getState, + }); if (!onData) return data as Returned; @@ -185,6 +198,7 @@ export function createDataLoadingThunk< dispatch, getState, discardLoadData: discardLoadDataInPayload, + actionArg: arg, }); // if there is no return in `onData`, we return the `onData` result diff --git a/app/lib/admin/metrics/measure/active_users_measure.rb b/app/lib/admin/metrics/measure/active_users_measure.rb index e6f09d4bc..c085ced62 100644 --- a/app/lib/admin/metrics/measure/active_users_measure.rb +++ b/app/lib/admin/metrics/measure/active_users_measure.rb @@ -22,12 +22,4 @@ class Admin::Metrics::Measure::ActiveUsersMeasure < Admin::Metrics::Measure::Bas def activity_tracker @activity_tracker ||= ActivityTracker.new('activity:logins', :unique) end - - def time_period - (@start_at.to_date..@end_at.to_date) - end - - def previous_time_period - ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) - end end diff --git a/app/lib/admin/metrics/measure/base_measure.rb b/app/lib/admin/metrics/measure/base_measure.rb index e33a6c494..8b7fe39b5 100644 --- a/app/lib/admin/metrics/measure/base_measure.rb +++ b/app/lib/admin/metrics/measure/base_measure.rb @@ -86,11 +86,11 @@ class Admin::Metrics::Measure::BaseMeasure end def time_period - (@start_at..@end_at) + (@start_at.to_date..@end_at.to_date) end def previous_time_period - ((@start_at - length_of_period)..(@end_at - length_of_period)) + ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) end def length_of_period diff --git a/app/lib/admin/metrics/measure/instance_accounts_measure.rb b/app/lib/admin/metrics/measure/instance_accounts_measure.rb index 746780ee7..889a5e6f0 100644 --- a/app/lib/admin/metrics/measure/instance_accounts_measure.rb +++ b/app/lib/admin/metrics/measure/instance_accounts_measure.rb @@ -48,14 +48,6 @@ class Admin::Metrics::Measure::InstanceAccountsMeasure < Admin::Metrics::Measure SQL end - def time_period - (@start_at.to_date..@end_at.to_date) - end - - def previous_time_period - ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) - end - def params @params.permit(:domain, :include_subdomains) end diff --git a/app/lib/admin/metrics/measure/instance_followers_measure.rb b/app/lib/admin/metrics/measure/instance_followers_measure.rb index 0693d5a64..fa934c6b9 100644 --- a/app/lib/admin/metrics/measure/instance_followers_measure.rb +++ b/app/lib/admin/metrics/measure/instance_followers_measure.rb @@ -49,14 +49,6 @@ class Admin::Metrics::Measure::InstanceFollowersMeasure < Admin::Metrics::Measur SQL end - def time_period - (@start_at.to_date..@end_at.to_date) - end - - def previous_time_period - ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) - end - def params @params.permit(:domain, :include_subdomains) end diff --git a/app/lib/admin/metrics/measure/instance_follows_measure.rb b/app/lib/admin/metrics/measure/instance_follows_measure.rb index 90d381935..3f3ab73fc 100644 --- a/app/lib/admin/metrics/measure/instance_follows_measure.rb +++ b/app/lib/admin/metrics/measure/instance_follows_measure.rb @@ -49,14 +49,6 @@ class Admin::Metrics::Measure::InstanceFollowsMeasure < Admin::Metrics::Measure: SQL end - def time_period - (@start_at.to_date..@end_at.to_date) - end - - def previous_time_period - ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) - end - def params @params.permit(:domain, :include_subdomains) end diff --git a/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb b/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb index 89f8b4149..996ca52e0 100644 --- a/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb +++ b/app/lib/admin/metrics/measure/instance_media_attachments_measure.rb @@ -58,14 +58,6 @@ class Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure < Admin::Metrics: SQL end - def time_period - (@start_at.to_date..@end_at.to_date) - end - - def previous_time_period - ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) - end - def params @params.permit(:domain, :include_subdomains) end diff --git a/app/lib/admin/metrics/measure/instance_reports_measure.rb b/app/lib/admin/metrics/measure/instance_reports_measure.rb index 5f58387a6..ae1bb6e68 100644 --- a/app/lib/admin/metrics/measure/instance_reports_measure.rb +++ b/app/lib/admin/metrics/measure/instance_reports_measure.rb @@ -49,14 +49,6 @@ class Admin::Metrics::Measure::InstanceReportsMeasure < Admin::Metrics::Measure: SQL end - def time_period - (@start_at.to_date..@end_at.to_date) - end - - def previous_time_period - ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) - end - def params @params.permit(:domain, :include_subdomains) end diff --git a/app/lib/admin/metrics/measure/instance_statuses_measure.rb b/app/lib/admin/metrics/measure/instance_statuses_measure.rb index 5873c6e71..324d427b1 100644 --- a/app/lib/admin/metrics/measure/instance_statuses_measure.rb +++ b/app/lib/admin/metrics/measure/instance_statuses_measure.rb @@ -58,14 +58,6 @@ class Admin::Metrics::Measure::InstanceStatusesMeasure < Admin::Metrics::Measure Mastodon::Snowflake.id_at(@end_at.end_of_day, with_random: false) end - def time_period - (@start_at.to_date..@end_at.to_date) - end - - def previous_time_period - ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) - end - def params @params.permit(:domain, :include_subdomains) end diff --git a/app/lib/admin/metrics/measure/interactions_measure.rb b/app/lib/admin/metrics/measure/interactions_measure.rb index 7a2b7e0fa..f4b4836b4 100644 --- a/app/lib/admin/metrics/measure/interactions_measure.rb +++ b/app/lib/admin/metrics/measure/interactions_measure.rb @@ -22,12 +22,4 @@ class Admin::Metrics::Measure::InteractionsMeasure < Admin::Metrics::Measure::Ba def activity_tracker @activity_tracker ||= ActivityTracker.new('activity:interactions', :basic) end - - def time_period - (@start_at.to_date..@end_at.to_date) - end - - def previous_time_period - ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) - end end diff --git a/app/lib/admin/metrics/measure/tag_accounts_measure.rb b/app/lib/admin/metrics/measure/tag_accounts_measure.rb index 8f4512efe..906277b7d 100644 --- a/app/lib/admin/metrics/measure/tag_accounts_measure.rb +++ b/app/lib/admin/metrics/measure/tag_accounts_measure.rb @@ -27,14 +27,6 @@ class Admin::Metrics::Measure::TagAccountsMeasure < Admin::Metrics::Measure::Bas @tag ||= Tag.find(params[:id]) end - def time_period - (@start_at.to_date..@end_at.to_date) - end - - def previous_time_period - ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) - end - def params @params.permit(:id) end diff --git a/app/lib/admin/metrics/measure/tag_uses_measure.rb b/app/lib/admin/metrics/measure/tag_uses_measure.rb index bce86b89f..2be96a02b 100644 --- a/app/lib/admin/metrics/measure/tag_uses_measure.rb +++ b/app/lib/admin/metrics/measure/tag_uses_measure.rb @@ -27,14 +27,6 @@ class Admin::Metrics::Measure::TagUsesMeasure < Admin::Metrics::Measure::BaseMea @tag ||= Tag.find(params[:id]) end - def time_period - (@start_at.to_date..@end_at.to_date) - end - - def previous_time_period - ((@start_at.to_date - length_of_period)..(@end_at.to_date - length_of_period)) - end - def params @params.permit(:id) end diff --git a/app/lib/cache_buster.rb b/app/lib/cache_buster.rb index 554f2ba95..d3395f8f0 100644 --- a/app/lib/cache_buster.rb +++ b/app/lib/cache_buster.rb @@ -2,13 +2,8 @@ class CacheBuster def initialize(options = {}) - Rails.application.deprecators[:mastodon].warn('Default values for the cache buster secret header name and values will be removed in Mastodon 4.3. Please set them explicitely if you rely on those.') unless options[:http_method] || (options[:secret] && options[:secret_header]) - - @secret_header = options[:secret_header] || - (options[:http_method] ? nil : 'Secret-Header') - @secret = options[:secret] || - (options[:http_method] ? nil : 'True') - + @secret_header = options[:secret_header] + @secret = options[:secret] @http_method = options[:http_method] || 'GET' end diff --git a/app/lib/link_details_extractor.rb b/app/lib/link_details_extractor.rb index 2e49d3fb4..dbfdd33fc 100644 --- a/app/lib/link_details_extractor.rb +++ b/app/lib/link_details_extractor.rb @@ -269,16 +269,21 @@ class LinkDetailsExtractor end def document - @document ||= Nokogiri::HTML(@html, nil, encoding) + @document ||= detect_encoding_and_parse_document end - def encoding - @encoding ||= begin - guess = detector.detect(@html, @html_charset) - guess&.fetch(:confidence, 0).to_i > 60 ? guess&.fetch(:encoding, nil) : nil + def detect_encoding_and_parse_document + [detect_encoding, nil, @html_charset, 'UTF-8'].uniq.each do |encoding| + document = Nokogiri::HTML(@html, nil, encoding) + return document if document.to_s.valid_encoding? end end + def detect_encoding + guess = detector.detect(@html, @html_charset) + guess&.fetch(:confidence, 0).to_i > 60 ? guess&.fetch(:encoding, nil) : nil + end + def detector @detector ||= CharlockHolmes::EncodingDetector.new.tap do |detector| detector.strip_tags = true diff --git a/app/models/notification_group.rb b/app/models/notification_group.rb index 43612d49b..b1cbd7c19 100644 --- a/app/models/notification_group.rb +++ b/app/models/notification_group.rb @@ -3,13 +3,16 @@ class NotificationGroup < ActiveModelSerializers::Model attributes :group_key, :sample_accounts, :notifications_count, :notification, :most_recent_notification_id - def self.from_notification(notification) + def self.from_notification(notification, max_id: nil) if notification.group_key.present? # TODO: caching and preloading - most_recent_notifications = notification.account.notifications.where(group_key: notification.group_key).order(id: :desc).take(3) + scope = notification.account.notifications.where(group_key: notification.group_key) + scope = scope.where(id: ..max_id) if max_id.present? + + most_recent_notifications = scope.order(id: :desc).take(3) most_recent_id = most_recent_notifications.first.id sample_accounts = most_recent_notifications.map(&:from_account) - notifications_count = notification.account.notifications.where(group_key: notification.group_key).count + notifications_count = scope.count else most_recent_id = notification.id sample_accounts = [notification.from_account] @@ -29,5 +32,6 @@ class NotificationGroup < ActiveModelSerializers::Model :target_status, :report, :account_relationship_severance_event, + :account_warning, to: :notification, prefix: false end diff --git a/app/serializers/activitypub/outbox_serializer.rb b/app/serializers/activitypub/outbox_serializer.rb index 4f4f950a5..4d3d9706d 100644 --- a/app/serializers/activitypub/outbox_serializer.rb +++ b/app/serializers/activitypub/outbox_serializer.rb @@ -2,7 +2,7 @@ class ActivityPub::OutboxSerializer < ActivityPub::CollectionSerializer def self.serializer_for(model, options) - if model.class.name == 'ActivityPub::ActivityPresenter' + if model.instance_of?(::ActivityPub::ActivityPresenter) ActivityPub::ActivitySerializer else super diff --git a/app/serializers/rest/notification_serializer.rb b/app/serializers/rest/notification_serializer.rb index 417245d19..966819585 100644 --- a/app/serializers/rest/notification_serializer.rb +++ b/app/serializers/rest/notification_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class REST::NotificationSerializer < ActiveModel::Serializer - attributes :id, :type, :created_at + attributes :id, :type, :created_at, :group_key belongs_to :from_account, key: :account, serializer: REST::AccountSerializer belongs_to :target_status, key: :status, if: :status_type?, serializer: REST::StatusSerializer @@ -13,6 +13,10 @@ class REST::NotificationSerializer < ActiveModel::Serializer object.id.to_s end + def group_key + object.group_key || "ungrouped-#{object.id}" + end + def status_type? [:favourite, :reblog, :status, :mention, :poll, :update].include?(object.type) end diff --git a/config/application.rb b/config/application.rb index 65407da05..5aca74fd1 100644 --- a/config/application.rb +++ b/config/application.rb @@ -49,6 +49,7 @@ require_relative '../lib/webpacker/manifest_extensions' require_relative '../lib/webpacker/helper_extensions' require_relative '../lib/rails/engine_extensions' require_relative '../lib/action_dispatch/remote_ip_extensions' +require_relative '../lib/stoplight/redis_data_store_extensions' require_relative '../lib/active_record/database_tasks_extensions' require_relative '../lib/active_record/batches' require_relative '../lib/active_record/with_recursive' diff --git a/config/locales/sv.yml b/config/locales/sv.yml index a3d31547c..91b1720b5 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -293,6 +293,7 @@ sv: filter_by_action: Filtrera efter åtgärd filter_by_user: Filtrera efter användare title: Revisionslogg + unavailable_instance: "(domännamn inte tillgängligt)" announcements: destroyed_msg: Kungörelsen raderades! edit: diff --git a/db/migrate/20160227230233_add_attachment_avatar_to_accounts.rb b/db/migrate/20160227230233_add_attachment_avatar_to_accounts.rb index 534df25ee..cfe4c23de 100644 --- a/db/migrate/20160227230233_add_attachment_avatar_to_accounts.rb +++ b/db/migrate/20160227230233_add_attachment_avatar_to_accounts.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class AddAttachmentAvatarToAccounts < ActiveRecord::Migration[4.2] - def self.up + def up change_table :accounts do |t| # The following corresponds to `t.attachment :avatar` in an older version of Paperclip t.string :avatar_file_name @@ -11,7 +11,7 @@ class AddAttachmentAvatarToAccounts < ActiveRecord::Migration[4.2] end end - def self.down + def down remove_attachment :accounts, :avatar end end diff --git a/db/migrate/20160305115639_add_devise_to_users.rb b/db/migrate/20160305115639_add_devise_to_users.rb index 64ad78dbc..22697b238 100644 --- a/db/migrate/20160305115639_add_devise_to_users.rb +++ b/db/migrate/20160305115639_add_devise_to_users.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class AddDeviseToUsers < ActiveRecord::Migration[4.2] - def self.up + def up change_table(:users, bulk: true) do |t| ## Database authenticatable t.string :encrypted_password, null: false, default: '' @@ -24,7 +24,7 @@ class AddDeviseToUsers < ActiveRecord::Migration[4.2] add_index :users, :reset_password_token, unique: true end - def self.down + def down remove_index :users, :reset_password_token remove_column :users, :encrypted_password diff --git a/db/migrate/20160312193225_add_attachment_header_to_accounts.rb b/db/migrate/20160312193225_add_attachment_header_to_accounts.rb index b481fc529..45dc65236 100644 --- a/db/migrate/20160312193225_add_attachment_header_to_accounts.rb +++ b/db/migrate/20160312193225_add_attachment_header_to_accounts.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class AddAttachmentHeaderToAccounts < ActiveRecord::Migration[4.2] - def self.up + def up change_table :accounts do |t| # The following corresponds to `t.attachment :header` in an older version of Paperclip t.string :header_file_name @@ -11,7 +11,7 @@ class AddAttachmentHeaderToAccounts < ActiveRecord::Migration[4.2] end end - def self.down + def down remove_attachment :accounts, :header end end diff --git a/db/migrate/20161006213403_rails_settings_migration.rb b/db/migrate/20161006213403_rails_settings_migration.rb index 9764196fa..d08ad2efd 100644 --- a/db/migrate/20161006213403_rails_settings_migration.rb +++ b/db/migrate/20161006213403_rails_settings_migration.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class RailsSettingsMigration < ActiveRecord::Migration[5.0] - def self.up + def up create_table :settings do |t| t.string :var, null: false t.text :value @@ -11,7 +11,7 @@ class RailsSettingsMigration < ActiveRecord::Migration[5.0] add_index :settings, [:target_type, :target_id, :var], unique: true end - def self.down + def down drop_table :settings end end diff --git a/db/migrate/20170330164118_add_attachment_data_to_imports.rb b/db/migrate/20170330164118_add_attachment_data_to_imports.rb index 0daaa9d02..afacfa86d 100644 --- a/db/migrate/20170330164118_add_attachment_data_to_imports.rb +++ b/db/migrate/20170330164118_add_attachment_data_to_imports.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class AddAttachmentDataToImports < ActiveRecord::Migration[4.2] - def self.up + def up change_table :imports do |t| # The following corresponds to `t.attachment :data` in an older version of Paperclip t.string :data_file_name @@ -11,7 +11,7 @@ class AddAttachmentDataToImports < ActiveRecord::Migration[4.2] end end - def self.down + def down remove_attachment :imports, :data end end diff --git a/lib/stoplight/redis_data_store_extensions.rb b/lib/stoplight/redis_data_store_extensions.rb new file mode 100644 index 000000000..900748784 --- /dev/null +++ b/lib/stoplight/redis_data_store_extensions.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +# Restore compatibility with Redis < 6.2 + +module Stoplight + module DataStore + module RedisExtensions + def query_failures(light, transaction: @redis) + window_start = Time.now.to_i - light.window_size + + transaction.zrevrangebyscore(failures_key(light), Float::INFINITY, window_start) + end + end + end +end + +Stoplight::DataStore::Redis.prepend(Stoplight::DataStore::RedisExtensions) diff --git a/package.json b/package.json index d52f0ea1c..729482f85 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@mastodon/mastodon", "license": "AGPL-3.0-or-later", - "packageManager": "yarn@4.3.0", + "packageManager": "yarn@4.3.1", "engines": { "node": ">=18" }, diff --git a/spec/fixtures/requests/low_confidence_latin1.txt b/spec/fixtures/requests/low_confidence_latin1.txt new file mode 100644 index 000000000..39c3e23d6 --- /dev/null +++ b/spec/fixtures/requests/low_confidence_latin1.txt @@ -0,0 +1,17 @@ +HTTP/1.1 200 OK +server: nginx +date: Thu, 13 Jun 2024 14:33:13 GMT +content-type: text/html; charset=ISO-8859-1 +content-length: 158 +accept-ranges: bytes + + + + + + Tofu l'orange + + +

Tofu l'orange

+ + diff --git a/spec/lib/cache_buster_spec.rb b/spec/lib/cache_buster_spec.rb index 78ca18349..84085608e 100644 --- a/spec/lib/cache_buster_spec.rb +++ b/spec/lib/cache_buster_spec.rb @@ -28,14 +28,6 @@ describe CacheBuster do end context 'when using default options' do - around do |example| - # Disables the CacheBuster.new deprecation warning about default arguments. - # Remove this `silence` block when default arg support is removed from CacheBuster - Rails.application.deprecators[:mastodon].silence do - example.run - end - end - include_examples 'makes_request' end diff --git a/spec/services/fetch_link_card_service_spec.rb b/spec/services/fetch_link_card_service_spec.rb index 63ebc3b97..239f84fde 100644 --- a/spec/services/fetch_link_card_service_spec.rb +++ b/spec/services/fetch_link_card_service_spec.rb @@ -26,6 +26,7 @@ RSpec.describe FetchLinkCardService do stub_request(:get, 'http://example.com/sjis_with_wrong_charset').to_return(request_fixture('sjis_with_wrong_charset.txt')) stub_request(:get, 'http://example.com/koi8-r').to_return(request_fixture('koi8-r.txt')) stub_request(:get, 'http://example.com/windows-1251').to_return(request_fixture('windows-1251.txt')) + stub_request(:get, 'http://example.com/low_confidence_latin1').to_return(request_fixture('low_confidence_latin1.txt')) Rails.cache.write('oembed_endpoint:example.com', oembed_cache) if oembed_cache @@ -148,6 +149,14 @@ RSpec.describe FetchLinkCardService do end end + context 'with a URL of a page in ISO-8859-1 encoding, that charlock_holmes cannot detect' do + let(:status) { Fabricate(:status, text: 'Check out http://example.com/low_confidence_latin1') } + + it 'decodes the HTML' do + expect(status.preview_card.title).to eq("Tofu á l'orange") + end + end + context 'with a Japanese path URL' do let(:status) { Fabricate(:status, text: 'テストhttp://example.com/日本語') } diff --git a/spec/support/matchers/json/match_json_schema.rb b/spec/support/matchers/json/match_json_schema.rb index 3a275199e..b4ced8add 100644 --- a/spec/support/matchers/json/match_json_schema.rb +++ b/spec/support/matchers/json/match_json_schema.rb @@ -6,3 +6,14 @@ RSpec::Matchers.define :match_json_schema do |schema| JSON::Validator.validate(schema_path, input_json, validate_schema: true) end end + +RSpec::Matchers.define :match_json_values do |values| + match do |string| + expect(json_str_to_hash(string)) + .to include(values) + end + + failure_message do |value| + "expected that #{value} would have the same values as #{values}." + end +end diff --git a/spec/support/streaming_server_manager.rb b/spec/support/streaming_server_manager.rb index 3facf16b8..376d6b872 100644 --- a/spec/support/streaming_server_manager.rb +++ b/spec/support/streaming_server_manager.rb @@ -80,9 +80,6 @@ end RSpec.configure do |config| config.before :suite do if streaming_examples_present? - # Compile assets - Webpacker.compile - # Start the node streaming server streaming_server_manager.start(port: STREAMING_PORT) end diff --git a/spec/workers/activitypub/distribute_poll_update_worker_spec.rb b/spec/workers/activitypub/distribute_poll_update_worker_spec.rb index afe2b291f..4427cfdf9 100644 --- a/spec/workers/activitypub/distribute_poll_update_worker_spec.rb +++ b/spec/workers/activitypub/distribute_poll_update_worker_spec.rb @@ -16,7 +16,7 @@ describe ActivityPub::DistributePollUpdateWorker do end it 'delivers to followers' do - expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[kind_of(String), account.id, 'http://example.com']]) do + expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(type: 'Update'), account.id, 'http://example.com']]) do subject.perform(status.id) end end diff --git a/spec/workers/activitypub/distribution_worker_spec.rb b/spec/workers/activitypub/distribution_worker_spec.rb index 2706967fc..0eb622785 100644 --- a/spec/workers/activitypub/distribution_worker_spec.rb +++ b/spec/workers/activitypub/distribution_worker_spec.rb @@ -19,7 +19,7 @@ describe ActivityPub::DistributionWorker do end it 'delivers to followers' do - expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[kind_of(String), status.account.id, 'http://example.com', anything]]) do + expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(type: 'Create'), status.account.id, 'http://example.com', anything]]) do subject.perform(status.id) end end @@ -31,7 +31,7 @@ describe ActivityPub::DistributionWorker do end it 'delivers to followers' do - expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[kind_of(String), status.account.id, 'http://example.com', anything]]) do + expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(type: 'Create'), status.account.id, 'http://example.com', anything]]) do subject.perform(status.id) end end @@ -46,7 +46,7 @@ describe ActivityPub::DistributionWorker do end it 'delivers to mentioned accounts' do - expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[kind_of(String), status.account.id, 'https://foo.bar/inbox', anything]]) do + expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(type: 'Create'), status.account.id, 'https://foo.bar/inbox', anything]]) do subject.perform(status.id) end end diff --git a/spec/workers/activitypub/move_distribution_worker_spec.rb b/spec/workers/activitypub/move_distribution_worker_spec.rb index 75ca21733..c810b33c2 100644 --- a/spec/workers/activitypub/move_distribution_worker_spec.rb +++ b/spec/workers/activitypub/move_distribution_worker_spec.rb @@ -16,12 +16,16 @@ describe ActivityPub::MoveDistributionWorker do end it 'delivers to followers and known blockers' do - expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [ - [kind_of(String), migration.account.id, 'http://example.com'], - [kind_of(String), migration.account.id, 'http://example2.com'], - ]) do + expect_push_bulk_to_match(ActivityPub::DeliveryWorker, expected_migration_deliveries) do subject.perform(migration.id) end end + + def expected_migration_deliveries + [ + [match_json_values(type: 'Move'), migration.account.id, 'http://example.com'], + [match_json_values(type: 'Move'), migration.account.id, 'http://example2.com'], + ] + end end end diff --git a/spec/workers/activitypub/status_update_distribution_worker_spec.rb b/spec/workers/activitypub/status_update_distribution_worker_spec.rb index a4fd246e5..66e52c4f2 100644 --- a/spec/workers/activitypub/status_update_distribution_worker_spec.rb +++ b/spec/workers/activitypub/status_update_distribution_worker_spec.rb @@ -25,7 +25,7 @@ describe ActivityPub::StatusUpdateDistributionWorker do end it 'delivers to followers' do - expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[kind_of(String), status.account.id, 'http://example.com', anything]]) do + expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(type: 'Update'), status.account.id, 'http://example.com', anything]]) do subject.perform(status.id) end end @@ -37,7 +37,7 @@ describe ActivityPub::StatusUpdateDistributionWorker do end it 'delivers to followers' do - expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[kind_of(String), status.account.id, 'http://example.com', anything]]) do + expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(type: 'Update'), status.account.id, 'http://example.com', anything]]) do subject.perform(status.id) end end diff --git a/spec/workers/activitypub/update_distribution_worker_spec.rb b/spec/workers/activitypub/update_distribution_worker_spec.rb index 4a0ed050b..b183a58df 100644 --- a/spec/workers/activitypub/update_distribution_worker_spec.rb +++ b/spec/workers/activitypub/update_distribution_worker_spec.rb @@ -14,7 +14,7 @@ describe ActivityPub::UpdateDistributionWorker do end it 'delivers to followers' do - expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[kind_of(String), account.id, 'http://example.com', anything]]) do + expect_push_bulk_to_match(ActivityPub::DeliveryWorker, [[match_json_values(type: 'Update'), account.id, 'http://example.com', anything]]) do subject.perform(account.id) end end diff --git a/streaming/Dockerfile b/streaming/Dockerfile index aee1f76ad..319d5b7fd 100644 --- a/streaming/Dockerfile +++ b/streaming/Dockerfile @@ -13,7 +13,14 @@ ARG NODE_MAJOR_VERSION="20" # Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"] ARG DEBIAN_VERSION="bookworm" # Node image to use for base image based on combined variables (ex: 20-bookworm-slim) -FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim as streaming +FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS streaming + +# Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA +# Example: v4.3.0-nightly.2023.11.09+pr-123456 +# Overwrite existence of 'alpha.X' in version.rb [--build-arg MASTODON_VERSION_PRERELEASE="nightly.2023.11.09"] +ARG MASTODON_VERSION_PRERELEASE="" +# Append build metadata or fork information to version.rb [--build-arg MASTODON_VERSION_METADATA="pr-123456"] +ARG MASTODON_VERSION_METADATA="" # Timezone used by the Docker container and runtime, change with [--build-arg TZ=Europe/Berlin] ARG TZ="Etc/UTC" diff --git a/streaming/package.json b/streaming/package.json index ba024fe7a..1ee738c33 100644 --- a/streaming/package.json +++ b/streaming/package.json @@ -1,7 +1,7 @@ { "name": "@mastodon/streaming", "license": "AGPL-3.0-or-later", - "packageManager": "yarn@4.3.0", + "packageManager": "yarn@4.3.1", "engines": { "node": ">=18" }, @@ -34,7 +34,7 @@ "@types/cors": "^2.8.16", "@types/express": "^4.17.17", "@types/pg": "^8.6.6", - "@types/uuid": "^9.0.0", + "@types/uuid": "^10.0.0", "@types/ws": "^8.5.9", "eslint-define-config": "^2.0.0", "pino-pretty": "^11.0.0", diff --git a/yarn.lock b/yarn.lock index 1be5eb422..ff4e1110d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2925,7 +2925,7 @@ __metadata: "@types/cors": "npm:^2.8.16" "@types/express": "npm:^4.17.17" "@types/pg": "npm:^8.6.6" - "@types/uuid": "npm:^9.0.0" + "@types/uuid": "npm:^10.0.0" "@types/ws": "npm:^8.5.9" bufferutil: "npm:^4.0.7" cors: "npm:^2.8.5" @@ -4045,10 +4045,10 @@ __metadata: languageName: node linkType: hard -"@types/uuid@npm:^9.0.0": - version: 9.0.8 - resolution: "@types/uuid@npm:9.0.8" - checksum: 10c0/b411b93054cb1d4361919579ef3508a1f12bf15b5fdd97337d3d351bece6c921b52b6daeef89b62340fd73fd60da407878432a1af777f40648cbe53a01723489 +"@types/uuid@npm:^10.0.0": + version: 10.0.0 + resolution: "@types/uuid@npm:10.0.0" + checksum: 10c0/9a1404bf287164481cb9b97f6bb638f78f955be57c40c6513b7655160beb29df6f84c915aaf4089a1559c216557dc4d2f79b48d978742d3ae10b937420ddac60 languageName: node linkType: hard @@ -5643,17 +5643,17 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.0.0, browserslist@npm:^4.22.2, browserslist@npm:^4.22.3, browserslist@npm:^4.23.0": - version: 4.23.0 - resolution: "browserslist@npm:4.23.0" +"browserslist@npm:^4.0.0, browserslist@npm:^4.22.2, browserslist@npm:^4.22.3, browserslist@npm:^4.23.0, browserslist@npm:^4.23.1": + version: 4.23.1 + resolution: "browserslist@npm:4.23.1" dependencies: - caniuse-lite: "npm:^1.0.30001587" - electron-to-chromium: "npm:^1.4.668" + caniuse-lite: "npm:^1.0.30001629" + electron-to-chromium: "npm:^1.4.796" node-releases: "npm:^2.0.14" - update-browserslist-db: "npm:^1.0.13" + update-browserslist-db: "npm:^1.0.16" bin: browserslist: cli.js - checksum: 10c0/8e9cc154529062128d02a7af4d8adeead83ca1df8cd9ee65a88e2161039f3d68a4d40fea7353cab6bae4c16182dec2fdd9a1cf7dc2a2935498cee1af0e998943 + checksum: 10c0/eb47c7ab9d60db25ce2faca70efeb278faa7282a2f62b7f2fa2f92e5f5251cf65144244566c86559419ff4f6d78f59ea50e39911321ad91f3b27788901f1f5e9 languageName: node linkType: hard @@ -5855,10 +5855,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001587, caniuse-lite@npm:^1.0.30001599": - version: 1.0.30001599 - resolution: "caniuse-lite@npm:1.0.30001599" - checksum: 10c0/8b3b9610b5be88533a3c8d0770d6896f7b1a9fee3dbeb7339e4ee119a514c81e5e07a628a5a289a6541ca291ac78a9402f5a99cf6012139e91f379083488a8eb +"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001599, caniuse-lite@npm:^1.0.30001629": + version: 1.0.30001636 + resolution: "caniuse-lite@npm:1.0.30001636" + checksum: 10c0/e5f965b4da7bae1531fd9f93477d015729ff9e3fa12670ead39a9e6cdc4c43e62c272d47857c5cc332e7b02d697cb3f2f965a1030870ac7476da60c2fc81ee94 languageName: node linkType: hard @@ -6723,43 +6723,43 @@ __metadata: languageName: node linkType: hard -"cssnano-preset-default@npm:^7.0.2": - version: 7.0.2 - resolution: "cssnano-preset-default@npm:7.0.2" +"cssnano-preset-default@npm:^7.0.3": + version: 7.0.3 + resolution: "cssnano-preset-default@npm:7.0.3" dependencies: - browserslist: "npm:^4.23.0" + browserslist: "npm:^4.23.1" css-declaration-sorter: "npm:^7.2.0" cssnano-utils: "npm:^5.0.0" postcss-calc: "npm:^10.0.0" - postcss-colormin: "npm:^7.0.0" - postcss-convert-values: "npm:^7.0.0" - postcss-discard-comments: "npm:^7.0.0" + postcss-colormin: "npm:^7.0.1" + postcss-convert-values: "npm:^7.0.1" + postcss-discard-comments: "npm:^7.0.1" postcss-discard-duplicates: "npm:^7.0.0" postcss-discard-empty: "npm:^7.0.0" postcss-discard-overridden: "npm:^7.0.0" - postcss-merge-longhand: "npm:^7.0.1" - postcss-merge-rules: "npm:^7.0.1" + postcss-merge-longhand: "npm:^7.0.2" + postcss-merge-rules: "npm:^7.0.2" postcss-minify-font-values: "npm:^7.0.0" postcss-minify-gradients: "npm:^7.0.0" - postcss-minify-params: "npm:^7.0.0" - postcss-minify-selectors: "npm:^7.0.1" + postcss-minify-params: "npm:^7.0.1" + postcss-minify-selectors: "npm:^7.0.2" postcss-normalize-charset: "npm:^7.0.0" postcss-normalize-display-values: "npm:^7.0.0" postcss-normalize-positions: "npm:^7.0.0" postcss-normalize-repeat-style: "npm:^7.0.0" postcss-normalize-string: "npm:^7.0.0" postcss-normalize-timing-functions: "npm:^7.0.0" - postcss-normalize-unicode: "npm:^7.0.0" + postcss-normalize-unicode: "npm:^7.0.1" postcss-normalize-url: "npm:^7.0.0" postcss-normalize-whitespace: "npm:^7.0.0" - postcss-ordered-values: "npm:^7.0.0" - postcss-reduce-initial: "npm:^7.0.0" + postcss-ordered-values: "npm:^7.0.1" + postcss-reduce-initial: "npm:^7.0.1" postcss-reduce-transforms: "npm:^7.0.0" postcss-svgo: "npm:^7.0.1" postcss-unique-selectors: "npm:^7.0.1" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/7c66240594c1d7a0cc761e755236228b17251455aa57abc45be0631f7de0fde070c23b0e41ffa200d39cd8351718514217d8c7a8cc4f06b54289dc1d555dfeb2 + checksum: 10c0/ab3e51003efed6542a12d43c10ca693ab26138a1d035697b9be8f07e084e37a78617cbb8028b0a7e7841302ec151f4ecf35cbd763efe291846b62c35ea4c0bb4 languageName: node linkType: hard @@ -6773,14 +6773,14 @@ __metadata: linkType: hard "cssnano@npm:^7.0.0": - version: 7.0.2 - resolution: "cssnano@npm:7.0.2" + version: 7.0.3 + resolution: "cssnano@npm:7.0.3" dependencies: - cssnano-preset-default: "npm:^7.0.2" - lilconfig: "npm:^3.1.1" + cssnano-preset-default: "npm:^7.0.3" + lilconfig: "npm:^3.1.2" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/ad43d8c2e96fa1022fc5103064e4f08da3fdc5501a946d455edf0b81981b58cd06ad2d3f0c68d666e2b687c10c02ffbb383252aa34da0ddc3bd4d075f4a922c7 + checksum: 10c0/4cbcd1e0ebe0bd83196cc5b16b3a60d3ebc98326c79b2f71df597bb73c8e3ee1f42b89159d7a038acc398251184d648d9dd516f4194e46746f3af6fa74b4aec7 languageName: node linkType: hard @@ -7395,10 +7395,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.668": - version: 1.4.681 - resolution: "electron-to-chromium@npm:1.4.681" - checksum: 10c0/5b2558dfb8bb82c20fb5fa1d9bbe06a3add47431dc3e1e4815e997be6ad387787047d9e534ed96839a9e7012520a5281c865158b09db41d10c029af003f05f94 +"electron-to-chromium@npm:^1.4.796": + version: 1.4.806 + resolution: "electron-to-chromium@npm:1.4.806" + checksum: 10c0/44f925ba64bb623d0482cd2f14fcfb27017cec1f11ee642e0d49cb128cd714ba5e074c2cd8756dfc18010aa66d3c64039cdea891905f7c17160a8963db574fab languageName: node linkType: hard @@ -7714,10 +7714,10 @@ __metadata: languageName: node linkType: hard -"escalade@npm:^3.1.1": - version: 3.1.1 - resolution: "escalade@npm:3.1.1" - checksum: 10c0/afd02e6ca91ffa813e1108b5e7756566173d6bc0d1eb951cb44d6b21702ec17c1cf116cfe75d4a2b02e05acb0b808a7a9387d0d1ca5cf9c04ad03a8445c3e46d +"escalade@npm:^3.1.1, escalade@npm:^3.1.2": + version: 3.1.2 + resolution: "escalade@npm:3.1.2" + checksum: 10c0/6b4adafecd0682f3aa1cd1106b8fff30e492c7015b178bc81b2d2f75106dabea6c6d6e8508fc491bd58e597c74abb0e8e2368f943ecb9393d4162e3c2f3cf287 languageName: node linkType: hard @@ -8924,17 +8924,18 @@ __metadata: linkType: hard "glob@npm:^10.2.2, glob@npm:^10.2.6, glob@npm:^10.3.10": - version: 10.4.1 - resolution: "glob@npm:10.4.1" + version: 10.4.2 + resolution: "glob@npm:10.4.2" dependencies: foreground-child: "npm:^3.1.0" jackspeak: "npm:^3.1.2" minimatch: "npm:^9.0.4" minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" path-scurry: "npm:^1.11.1" bin: glob: dist/esm/bin.mjs - checksum: 10c0/77f2900ed98b9cc2a0e1901ee5e476d664dae3cd0f1b662b8bfd4ccf00d0edc31a11595807706a274ca10e1e251411bbf2e8e976c82bed0d879a9b89343ed379 + checksum: 10c0/2c7296695fa75a935f3ad17dc62e4e170a8bb8752cf64d328be8992dd6ad40777939003754e10e9741ff8fbe43aa52fba32d6930d0ffa0e3b74bc3fb5eebaa2f languageName: node linkType: hard @@ -11267,10 +11268,10 @@ __metadata: languageName: node linkType: hard -"lilconfig@npm:^3.1.1, lilconfig@npm:~3.1.1": - version: 3.1.1 - resolution: "lilconfig@npm:3.1.1" - checksum: 10c0/311b559794546894e3fe176663427326026c1c644145be9e8041c58e268aa9328799b8dfe7e4dd8c6a4ae305feae95a1c9e007db3569f35b42b6e1bc8274754c +"lilconfig@npm:^3.1.2, lilconfig@npm:~3.1.1": + version: 3.1.2 + resolution: "lilconfig@npm:3.1.2" + checksum: 10c0/f059630b1a9bddaeba83059db00c672b64dc14074e9f232adce32b38ca1b5686ab737eb665c5ba3c32f147f0002b4bee7311ad0386a9b98547b5623e87071fbe languageName: node linkType: hard @@ -12668,6 +12669,13 @@ __metadata: languageName: node linkType: hard +"package-json-from-dist@npm:^1.0.0": + version: 1.0.0 + resolution: "package-json-from-dist@npm:1.0.0" + checksum: 10c0/e3ffaf6ac1040ab6082a658230c041ad14e72fabe99076a2081bb1d5d41210f11872403fc09082daf4387fc0baa6577f96c9c0e94c90c394fd57794b66aa4033 + languageName: node + linkType: hard + "pako@npm:~1.0.5": version: 1.0.11 resolution: "pako@npm:1.0.11" @@ -13236,29 +13244,29 @@ __metadata: languageName: node linkType: hard -"postcss-colormin@npm:^7.0.0": - version: 7.0.0 - resolution: "postcss-colormin@npm:7.0.0" +"postcss-colormin@npm:^7.0.1": + version: 7.0.1 + resolution: "postcss-colormin@npm:7.0.1" dependencies: - browserslist: "npm:^4.23.0" + browserslist: "npm:^4.23.1" caniuse-api: "npm:^3.0.0" colord: "npm:^2.9.3" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/d365a5365e0a94748309d32c7208cd06249bc53eb82cc32c771de4073b109fa8552e58d60dbe84d7e69e68081ed8a01fbf645d38a650e90cb2e13b21043cd796 + checksum: 10c0/e01e9e129ce39320cf10bb09ee2a3ab5b44b77805d3f7827eea07297644838b85c33b78996eeae0a1aba327ffd72a6ab1d24949ebc831523e310e916d5500371 languageName: node linkType: hard -"postcss-convert-values@npm:^7.0.0": - version: 7.0.0 - resolution: "postcss-convert-values@npm:7.0.0" +"postcss-convert-values@npm:^7.0.1": + version: 7.0.1 + resolution: "postcss-convert-values@npm:7.0.1" dependencies: - browserslist: "npm:^4.23.0" + browserslist: "npm:^4.23.1" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/5d7cfa06f307e024574a1842016f006691e0c1932352f53a99ce8f2f9930c64c3c1ae17518e9e4e5176630b99f1beaab37bc339bc779fb07dc543670ae66bb21 + checksum: 10c0/612f025f179f0f2ad7365db8c0b423614dcb8e1e4061875a4691a39dede0bca758d1a8f9f5c8b08e12af053e9e884f65ca5626ccc723d5b3f420650d67fe3046 languageName: node linkType: hard @@ -13316,12 +13324,14 @@ __metadata: languageName: node linkType: hard -"postcss-discard-comments@npm:^7.0.0": - version: 7.0.0 - resolution: "postcss-discard-comments@npm:7.0.0" +"postcss-discard-comments@npm:^7.0.1": + version: 7.0.1 + resolution: "postcss-discard-comments@npm:7.0.1" + dependencies: + postcss-selector-parser: "npm:^6.1.0" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/7fef7deea85c1e68161f69057be19a3aedd54d23c9b464c9b1531faa7a115f0c96a4f0ee3a560ce300578599dbc8114fe0fb744208b20b9d2fd8df1b4b39c58a + checksum: 10c0/64de3fced7e0e49dfea6aede8a5ca495b81dcd01c3c47734a5fbc86a3cb2b1ae39e1958e34e9bea64ecabd5fb4d8c287ec1d6189cf175c2434c6b6582da79948 languageName: node linkType: hard @@ -13466,29 +13476,29 @@ __metadata: languageName: node linkType: hard -"postcss-merge-longhand@npm:^7.0.1": - version: 7.0.1 - resolution: "postcss-merge-longhand@npm:7.0.1" +"postcss-merge-longhand@npm:^7.0.2": + version: 7.0.2 + resolution: "postcss-merge-longhand@npm:7.0.2" dependencies: postcss-value-parser: "npm:^4.2.0" - stylehacks: "npm:^7.0.1" + stylehacks: "npm:^7.0.2" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/e3d20502e65c82c9c4ba2e400bd093ee6b9c1b0019618ccd50eb40ef0e496206dd518c7e655a6986d780d5a52576e32e8f310d00484b15f67c77664a148df6eb + checksum: 10c0/71d22418e5850e134bfcf2038acb1c91eeb48d9b6f9e4c0252fee757e11dc4ae351097a855c327fbc38dc7658fa6edc7cc7f458c08bb4044b82c6005dc565fcb languageName: node linkType: hard -"postcss-merge-rules@npm:^7.0.1": - version: 7.0.1 - resolution: "postcss-merge-rules@npm:7.0.1" +"postcss-merge-rules@npm:^7.0.2": + version: 7.0.2 + resolution: "postcss-merge-rules@npm:7.0.2" dependencies: - browserslist: "npm:^4.23.0" + browserslist: "npm:^4.23.1" caniuse-api: "npm:^3.0.0" cssnano-utils: "npm:^5.0.0" postcss-selector-parser: "npm:^6.1.0" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/d380c162327e7aad59efb55cfddc5ec4e3bf51d18b07b832fdd876505279bac3cb44511ada8e1e1992428dcec4f64c7ec457b6ff9109063c5a61abf4b59b7176 + checksum: 10c0/fbad20382ca45f1b3b5ff704c075f899cc9ba8418ae6effbdeb9e7c1f9b5c24996d1941ad36cd0936d60cbf127a72f235b2cbb0c44d9239a8a61042406d95b4a languageName: node linkType: hard @@ -13516,27 +13526,28 @@ __metadata: languageName: node linkType: hard -"postcss-minify-params@npm:^7.0.0": - version: 7.0.0 - resolution: "postcss-minify-params@npm:7.0.0" +"postcss-minify-params@npm:^7.0.1": + version: 7.0.1 + resolution: "postcss-minify-params@npm:7.0.1" dependencies: - browserslist: "npm:^4.23.0" + browserslist: "npm:^4.23.1" cssnano-utils: "npm:^5.0.0" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/28a7ae313a197aeaff8b3fa1e695a6443b11a74258374a05adee6a1b05f5849ef52037b7a5069d6910614b03b4610acdaf4a76f38b89cb42e813a8cb5ec2fc01 + checksum: 10c0/84e1c4de5af47178c1f48e10ce16341560f32bb2becf5ec9b014103f6c706174bc70885e2e13ced4de9b4f1959fb970193261cbd4751c8b87d5159e859e8c5ec languageName: node linkType: hard -"postcss-minify-selectors@npm:^7.0.1": - version: 7.0.1 - resolution: "postcss-minify-selectors@npm:7.0.1" +"postcss-minify-selectors@npm:^7.0.2": + version: 7.0.2 + resolution: "postcss-minify-selectors@npm:7.0.2" dependencies: + cssesc: "npm:^3.0.0" postcss-selector-parser: "npm:^6.1.0" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/a8ff69657fb1808d8f0f105b13a416426902d6f498a4b7ebb3b96b4b9149e97ee2e2ad6cd98108e2f0b8f781701724e6c51e120e215cee3e40c2d7a2afac755a + checksum: 10c0/87e0c21a0135b6c61b58d62c4c1e0cbd3cfb516ff8105db714c6a33a5edc477846ae220399d368e4ef6518529c711aa2dee9ff49e9befd93e83d5c939f3084a1 languageName: node linkType: hard @@ -13661,15 +13672,15 @@ __metadata: languageName: node linkType: hard -"postcss-normalize-unicode@npm:^7.0.0": - version: 7.0.0 - resolution: "postcss-normalize-unicode@npm:7.0.0" +"postcss-normalize-unicode@npm:^7.0.1": + version: 7.0.1 + resolution: "postcss-normalize-unicode@npm:7.0.1" dependencies: - browserslist: "npm:^4.23.0" + browserslist: "npm:^4.23.1" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/f2d6ab0076c006dcf3ed33ba30686f2d29e81a408c66acced22e2c942df6d613697ea786137833dd258aafab5fda4d3eb27df13a82df830357dbad9b79154881 + checksum: 10c0/fcabac738765f608cb211ac01a19f9a7d784f99d223ef6f31352f37b9bcf008e0ca7849414c9e77116be8660d78b01dba6fc4a87cee7c9a977d3c2741d6a222d languageName: node linkType: hard @@ -13704,15 +13715,15 @@ __metadata: languageName: node linkType: hard -"postcss-ordered-values@npm:^7.0.0": - version: 7.0.0 - resolution: "postcss-ordered-values@npm:7.0.0" +"postcss-ordered-values@npm:^7.0.1": + version: 7.0.1 + resolution: "postcss-ordered-values@npm:7.0.1" dependencies: cssnano-utils: "npm:^5.0.0" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/42b14f9518b573318594c2aeb2f13fd1fbe44936d14f1b28a438e7a82644ace9a2946699bebfe7a2d383534dc24e7203c35308d749f3c585a86daa238ad920a4 + checksum: 10c0/9fc62e9039c7d4fa417d165678b065fc577a7232aa41a94a4e9208ad7db2268e1ce003aaad7c6a569afdf890a43416b0bf21047461505b4e3a16eec311a6eb63 languageName: node linkType: hard @@ -13828,15 +13839,15 @@ __metadata: languageName: node linkType: hard -"postcss-reduce-initial@npm:^7.0.0": - version: 7.0.0 - resolution: "postcss-reduce-initial@npm:7.0.0" +"postcss-reduce-initial@npm:^7.0.1": + version: 7.0.1 + resolution: "postcss-reduce-initial@npm:7.0.1" dependencies: - browserslist: "npm:^4.23.0" + browserslist: "npm:^4.23.1" caniuse-api: "npm:^3.0.0" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/ed50cd680ce258df953b82ce9b3fb52564d08548724577810800e236d017d80430cbccb4b1ad38b0f4d521663598e44ab93136b20064231181ef49e1e113ae10 + checksum: 10c0/3e7c6c1d0cc4ace38f44971f02d0dd98131af678cf114aa05cfa0c066420019d5329c221ef8507644b8a79d0e76534303f747c97860ac777fe17f57110edefe1 languageName: node linkType: hard @@ -16407,15 +16418,15 @@ __metadata: languageName: node linkType: hard -"stylehacks@npm:^7.0.1": - version: 7.0.1 - resolution: "stylehacks@npm:7.0.1" +"stylehacks@npm:^7.0.2": + version: 7.0.2 + resolution: "stylehacks@npm:7.0.2" dependencies: - browserslist: "npm:^4.23.0" + browserslist: "npm:^4.23.1" postcss-selector-parser: "npm:^6.1.0" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/538d5d9c6d84906efad3706f0873b85b67fa224f17759b122bad3d60f2928c31204fd658dd16ec952bf54858a3aeaef4643e040c04030459285ce1b13c4cae91 + checksum: 10c0/552299e869ac430e1076c025ace6c80bdfd5b672632435625eb1bd45ff5611aad7f3ee810e72edc04dc0fc3761e08dec40d27b72c50b95690eea2de43238b8d8 languageName: node linkType: hard @@ -17334,17 +17345,17 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.0.13": - version: 1.0.13 - resolution: "update-browserslist-db@npm:1.0.13" +"update-browserslist-db@npm:^1.0.16": + version: 1.0.16 + resolution: "update-browserslist-db@npm:1.0.16" dependencies: - escalade: "npm:^3.1.1" - picocolors: "npm:^1.0.0" + escalade: "npm:^3.1.2" + picocolors: "npm:^1.0.1" peerDependencies: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: 10c0/e52b8b521c78ce1e0c775f356cd16a9c22c70d25f3e01180839c407a5dc787fb05a13f67560cbaf316770d26fa99f78f1acd711b1b54a4f35d4820d4ea7136e6 + checksum: 10c0/5995399fc202adbb51567e4810e146cdf7af630a92cc969365a099150cb00597e425cc14987ca7080b09a4d0cfd2a3de53fbe72eebff171aed7f9bb81f9bf405 languageName: node linkType: hard