diff --git a/.env.production.sample b/.env.production.sample index 0bf01bdc36..0b458a1aa9 100644 --- a/.env.production.sample +++ b/.env.production.sample @@ -1,5 +1,5 @@ # This is a sample configuration file. You can generate your configuration -# with the `rake mastodon:setup` interactive setup wizard, but to customize +# with the `bundle exec rails mastodon:setup` interactive setup wizard, but to customize # your setup even further, you'll need to edit it manually. This sample does # not demonstrate all available configuration options. Please look at # https://docs.joinmastodon.org/admin/config/ for the full documentation. @@ -40,14 +40,14 @@ ES_PASS=password # Secrets # ------- -# Make sure to use `rake secret` to generate secrets +# Make sure to use `bundle exec rails secret` to generate secrets # ------- SECRET_KEY_BASE= OTP_SECRET= # Web Push # -------- -# Generate with `rake mastodon:webpush:generate_vapid_key` +# Generate with `bundle exec rails mastodon:webpush:generate_vapid_key` # -------- VAPID_PRIVATE_KEY= VAPID_PUBLIC_KEY= diff --git a/.github/workflows/bundler-audit.yml b/.github/workflows/bundler-audit.yml index e3e2da0c78..2341d6e67f 100644 --- a/.github/workflows/bundler-audit.yml +++ b/.github/workflows/bundler-audit.yml @@ -1,8 +1,10 @@ name: Bundler Audit on: + merge_group: push: - branches-ignore: - - 'dependabot/**' + branches: + - 'main' + - 'stable-*' paths: - 'Gemfile*' - '.ruby-version' diff --git a/.github/workflows/check-i18n.yml b/.github/workflows/check-i18n.yml index ceb385933b..5a1c051966 100644 --- a/.github/workflows/check-i18n.yml +++ b/.github/workflows/check-i18n.yml @@ -2,9 +2,13 @@ name: Check i18n on: push: - branches: [main] + branches: + - 'main' + - 'stable-*' pull_request: - branches: [main] + branches: + - 'main' + - 'stable-*' env: RAILS_ENV: test diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 6fb93b7fef..8690e9ed6d 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,11 +1,15 @@ name: 'CodeQL' on: + merge_group: push: - branches: ['main'] + branches: + - 'main' + - 'stable-*' pull_request: - # The branches below must be a subset of the branches above - branches: ['main'] + branches: + - 'main' + - 'stable-*' schedule: - cron: '22 6 * * 1' diff --git a/.github/workflows/format-check.yml b/.github/workflows/format-check.yml index 2d483b5022..c10f350a02 100644 --- a/.github/workflows/format-check.yml +++ b/.github/workflows/format-check.yml @@ -1,6 +1,10 @@ name: Check formatting on: + merge_group: push: + branches: + - 'main' + - 'stable-*' pull_request: jobs: diff --git a/.github/workflows/lint-css.yml b/.github/workflows/lint-css.yml index d3b8035cd8..95fcd56942 100644 --- a/.github/workflows/lint-css.yml +++ b/.github/workflows/lint-css.yml @@ -1,9 +1,10 @@ name: CSS Linting on: + merge_group: push: - branches-ignore: - - 'dependabot/**' - - 'renovate/**' + branches: + - 'main' + - 'stable-*' paths: - 'package.json' - 'yarn.lock' diff --git a/.github/workflows/lint-haml.yml b/.github/workflows/lint-haml.yml index ca4b0c80bf..a1a9e99c90 100644 --- a/.github/workflows/lint-haml.yml +++ b/.github/workflows/lint-haml.yml @@ -1,9 +1,10 @@ name: Haml Linting on: + merge_group: push: - branches-ignore: - - 'dependabot/**' - - 'renovate/**' + branches: + - 'main' + - 'stable-*' paths: - '.github/workflows/haml-lint-problem-matcher.json' - '.github/workflows/lint-haml.yml' diff --git a/.github/workflows/lint-js.yml b/.github/workflows/lint-js.yml index 1c1ecc2b22..7d31a5e20e 100644 --- a/.github/workflows/lint-js.yml +++ b/.github/workflows/lint-js.yml @@ -1,9 +1,10 @@ name: JavaScript Linting on: + merge_group: push: - branches-ignore: - - 'dependabot/**' - - 'renovate/**' + branches: + - 'main' + - 'stable-*' paths: - 'package.json' - 'yarn.lock' diff --git a/.github/workflows/lint-ruby.yml b/.github/workflows/lint-ruby.yml index b3a89c3caf..277e456146 100644 --- a/.github/workflows/lint-ruby.yml +++ b/.github/workflows/lint-ruby.yml @@ -1,9 +1,10 @@ name: Ruby Linting on: + merge_group: push: - branches-ignore: - - 'dependabot/**' - - 'renovate/**' + branches: + - 'main' + - 'stable-*' paths: - 'Gemfile*' - '.rubocop*.yml' diff --git a/.github/workflows/test-js.yml b/.github/workflows/test-js.yml index 481afdba30..e9e43ac9e8 100644 --- a/.github/workflows/test-js.yml +++ b/.github/workflows/test-js.yml @@ -1,9 +1,10 @@ name: JavaScript Testing on: + merge_group: push: - branches-ignore: - - 'dependabot/**' - - 'renovate/**' + branches: + - 'main' + - 'stable-*' paths: - 'package.json' - 'yarn.lock' diff --git a/.github/workflows/test-migrations.yml b/.github/workflows/test-migrations.yml index 3eaf2c2d74..6a0e67c58e 100644 --- a/.github/workflows/test-migrations.yml +++ b/.github/workflows/test-migrations.yml @@ -1,29 +1,29 @@ name: Historical data migration test on: + merge_group: push: - branches-ignore: - - 'dependabot/**' - - 'renovate/**' + branches: + - 'main' + - 'stable-*' + paths: + - 'Gemfile*' + - '.ruby-version' + - '**/*.rb' + - '.github/workflows/test-migrations.yml' + - 'lib/tasks/tests.rake' + pull_request: + paths: + - 'Gemfile*' + - '.ruby-version' + - '**/*.rb' + - '.github/workflows/test-migrations.yml' + - 'lib/tasks/tests.rake' jobs: - pre_job: - runs-on: ubuntu-latest - - outputs: - should_skip: ${{ steps.skip_check.outputs.should_skip }} - - steps: - - id: skip_check - uses: fkirc/skip-duplicate-actions@v5 - with: - paths: '["Gemfile*", ".ruby-version", "**/*.rb", ".github/workflows/test-migrations.yml", "lib/tasks/tests.rake"]' - test: runs-on: ubuntu-latest - needs: pre_job - if: needs.pre_job.outputs.should_skip != 'true' strategy: fail-fast: false diff --git a/.github/workflows/test-ruby.yml b/.github/workflows/test-ruby.yml index f2ff188188..163ae0c8f6 100644 --- a/.github/workflows/test-ruby.yml +++ b/.github/workflows/test-ruby.yml @@ -1,10 +1,11 @@ name: Ruby Testing on: + merge_group: push: - branches-ignore: - - 'dependabot/**' - - 'renovate/**' + branches: + - 'main' + - 'stable-*' pull_request: env: @@ -224,7 +225,7 @@ jobs: - name: Load database schema run: './bin/rails db:create db:schema:load db:seed' - - run: bin/rspec --tag paperclip_processing + - run: bin/rspec --tag attachment_processing - name: Upload coverage reports to Codecov if: matrix.ruby-version == '.ruby-version' diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 40330af583..d0e855a333 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-offense-counts --no-auto-gen-timestamp` -# using RuboCop version 1.64.1. +# using RuboCop version 1.65.0. # 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 @@ -14,7 +14,7 @@ Lint/NonLocalExitFromIterator: Metrics/AbcSize: Max: 82 -# Configuration parameters: CountBlocks, Max. +# Configuration parameters: CountBlocks, CountModifierForms, Max. Metrics/BlockNesting: Exclude: - 'lib/tasks/mastodon.rake' diff --git a/.ruby-version b/.ruby-version index 619b537668..a0891f563f 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.3.3 +3.3.4 diff --git a/Dockerfile b/Dockerfile index 7f7eca06da..758db9bcc9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ ARG BUILDPLATFORM=${BUILDPLATFORM} # Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.3.x"] # renovate: datasource=docker depName=docker.io/ruby -ARG RUBY_VERSION="3.3.3" +ARG RUBY_VERSION="3.3.4" # # Node version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"] # renovate: datasource=node-version depName=node ARG NODE_MAJOR_VERSION="20" @@ -67,7 +67,9 @@ ENV \ # Optimize jemalloc 5.x performance MALLOC_CONF="narenas:2,background_thread:true,thp:never,dirty_decay_ms:1000,muzzy_decay_ms:0" \ # Enable libvips, should not be changed - MASTODON_USE_LIBVIPS=true + MASTODON_USE_LIBVIPS=true \ +# Sidekiq will touch tmp/sidekiq_process_has_started_and_will_begin_processing_jobs to indicate it is ready. This can be used for a readiness check in Kubernetes + MASTODON_SIDEKIQ_READY_FILENAME=sidekiq_process_has_started_and_will_begin_processing_jobs # Set default shell used for running commands SHELL ["/bin/bash", "-o", "pipefail", "-o", "errexit", "-c"] diff --git a/Gemfile.lock b/Gemfile.lock index eb6720e454..98a3571731 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -159,7 +159,7 @@ GEM case_transform (0.2) activesupport cbor (0.5.9.8) - charlock_holmes (0.7.8) + charlock_holmes (0.7.9) chewy (7.6.0) activesupport (>= 5.2) elasticsearch (>= 7.14.0, < 8) @@ -180,7 +180,7 @@ GEM css_parser (1.17.1) addressable csv (3.3.0) - database_cleaner-active_record (2.1.0) + database_cleaner-active_record (2.2.0) activerecord (>= 5.a) database_cleaner-core (~> 2.0.0) database_cleaner-core (2.0.1) @@ -346,7 +346,7 @@ GEM activesupport (>= 3.0) nokogiri (>= 1.6) io-console (0.7.2) - irb (1.13.2) + irb (1.14.0) rdoc (>= 4.0.0) reline (>= 0.4.2) jmespath (1.6.2) @@ -583,15 +583,15 @@ GEM orm_adapter (0.5.0) ox (2.14.18) parallel (1.25.1) - parser (3.3.3.0) + parser (3.3.4.0) ast (~> 2.4.1) racc parslet (2.0.0) pastel (0.8.0) tty-color (~> 0.5) pg (1.5.6) - pghero (3.5.0) - activerecord (>= 6) + pghero (3.6.0) + activerecord (>= 6.1) premailer (1.23.0) addressable css_parser (>= 1.12.0) @@ -733,13 +733,13 @@ GEM rspec-mocks (~> 3.0) sidekiq (>= 5, < 8) rspec-support (3.13.1) - rubocop (1.64.1) + rubocop (1.65.0) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) + regexp_parser (>= 2.4, < 3.0) rexml (>= 3.2.5, < 4.0) rubocop-ast (>= 1.31.1, < 2.0) ruby-progressbar (~> 1.7) @@ -756,7 +756,7 @@ GEM rack (>= 1.1) rubocop (>= 1.33.0, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rspec (3.0.2) + rubocop-rspec (3.0.3) rubocop (~> 1.61) rubocop-rspec_rails (2.30.0) rubocop (~> 1.61) @@ -793,10 +793,10 @@ GEM redis (>= 4.5.0, < 5) sidekiq-bulk (0.2.0) sidekiq - sidekiq-scheduler (5.0.3) + sidekiq-scheduler (5.0.5) rufus-scheduler (~> 3.2) sidekiq (>= 6, < 8) - tilt (>= 1.4.0) + tilt (>= 1.4.0, < 3) sidekiq-unique-jobs (7.1.33) brpoplpush-redis_script (> 0.1.1, <= 2.0.0) concurrent-ruby (~> 1.0, >= 1.0.5) diff --git a/app/controllers/api/v1/notifications/requests_controller.rb b/app/controllers/api/v1/notifications/requests_controller.rb index 0e58379a38..9ae80c28ed 100644 --- a/app/controllers/api/v1/notifications/requests_controller.rb +++ b/app/controllers/api/v1/notifications/requests_controller.rb @@ -28,14 +28,14 @@ class Api::V1::Notifications::RequestsController < Api::BaseController end def dismiss - @request.update!(dismissed: true) + @request.destroy! render_empty end private def load_requests - requests = NotificationRequest.where(account: current_account).where(dismissed: truthy_param?(:dismissed) || false).includes(:last_status, from_account: [:account_stat, :user]).to_a_paginated_by_id( + requests = NotificationRequest.where(account: current_account).includes(:last_status, from_account: [:account_stat, :user]).to_a_paginated_by_id( limit_param(DEFAULT_ACCOUNTS_LIMIT), params_slice(:max_id, :since_id, :min_id) ) @@ -68,8 +68,4 @@ class Api::V1::Notifications::RequestsController < Api::BaseController def pagination_since_id @requests.first.id end - - def pagination_params(core_params) - params.slice(:dismissed).permit(:dismissed).merge(core_params) - end end diff --git a/app/controllers/api/v1/polls/votes_controller.rb b/app/controllers/api/v1/polls/votes_controller.rb index 513b937ef2..ad1b82cb52 100644 --- a/app/controllers/api/v1/polls/votes_controller.rb +++ b/app/controllers/api/v1/polls/votes_controller.rb @@ -8,7 +8,7 @@ class Api::V1::Polls::VotesController < Api::BaseController before_action :set_poll def create - VoteService.new.call(current_account, @poll, vote_params[:choices]) + VoteService.new.call(current_account, @poll, vote_params) render json: @poll, serializer: REST::PollSerializer end @@ -22,6 +22,6 @@ class Api::V1::Polls::VotesController < Api::BaseController end def vote_params - params.permit(choices: []) + params.require(:choices) end end diff --git a/app/helpers/theme_helper.rb b/app/helpers/theme_helper.rb index d15259851c..fab899a533 100644 --- a/app/helpers/theme_helper.rb +++ b/app/helpers/theme_helper.rb @@ -3,8 +3,10 @@ module ThemeHelper def theme_style_tags(theme) if theme == 'system' - stylesheet_pack_tag('mastodon-light', media: 'not all and (prefers-color-scheme: dark)', crossorigin: 'anonymous') + - stylesheet_pack_tag('default', media: '(prefers-color-scheme: dark)', crossorigin: 'anonymous') + ''.html_safe.tap do |tags| + tags << stylesheet_pack_tag('mastodon-light', media: 'not all and (prefers-color-scheme: dark)', crossorigin: 'anonymous') + tags << stylesheet_pack_tag('default', media: '(prefers-color-scheme: dark)', crossorigin: 'anonymous') + end else stylesheet_pack_tag theme, media: 'all', crossorigin: 'anonymous' end @@ -12,8 +14,10 @@ module ThemeHelper def theme_color_tags(theme) if theme == 'system' - tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:dark], media: '(prefers-color-scheme: dark)') + - tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:light], media: '(prefers-color-scheme: light)') + ''.html_safe.tap do |tags| + tags << tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:dark], media: '(prefers-color-scheme: dark)') + tags << tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:light], media: '(prefers-color-scheme: light)') + end else tag.meta name: 'theme-color', content: theme_color_for(theme) end diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js index 7bba41ee97..218cf3977c 100644 --- a/app/javascript/mastodon/actions/compose.js +++ b/app/javascript/mastodon/actions/compose.js @@ -305,7 +305,7 @@ export function submitComposeFail(error) { export function uploadCompose(files) { return function (dispatch, getState) { - const uploadLimit = 4; + const uploadLimit = getState().getIn(['server', 'server', 'configuration', 'statuses', 'max_media_attachments']); const media = getState().getIn(['compose', 'media_attachments']); const pending = getState().getIn(['compose', 'pending_media_attachments']); const defaultSensitive = getState().getIn(['compose', 'default_sensitive']); @@ -322,7 +322,7 @@ export function uploadCompose(files) { dispatch(uploadComposeRequest()); for (const [i, file] of Array.from(files).entries()) { - if (media.size + i >= 4) break; + if (media.size + i > (uploadLimit - 1)) break; const data = new FormData(); data.append('file', file); diff --git a/app/javascript/mastodon/components/account.jsx b/app/javascript/mastodon/components/account.jsx index 46f2317ac4..8f5d9c1507 100644 --- a/app/javascript/mastodon/components/account.jsx +++ b/app/javascript/mastodon/components/account.jsx @@ -131,7 +131,7 @@ const Account = ({ size = 46, account, onFollow, onBlock, onMute, onMuteNotifica return (
- +
diff --git a/app/javascript/mastodon/components/hover_card_controller.tsx b/app/javascript/mastodon/components/hover_card_controller.tsx index 0e02a6a5d4..94c6d372ca 100644 --- a/app/javascript/mastodon/components/hover_card_controller.tsx +++ b/app/javascript/mastodon/components/hover_card_controller.tsx @@ -43,6 +43,7 @@ export const HoverCardController: React.FC = () => { useEffect(() => { let isScrolling = false; let currentAnchor: HTMLElement | null = null; + let currentTitle: string | null = null; const open = (target: HTMLElement) => { target.setAttribute('aria-describedby', 'hover-card'); @@ -75,6 +76,9 @@ export const HoverCardController: React.FC = () => { currentAnchor?.removeAttribute('aria-describedby'); currentAnchor = target; + currentTitle = target.getAttribute('title'); + target.removeAttribute('title'); + setEnterTimeout(() => { open(target); }, enterDelay); @@ -90,11 +94,20 @@ export const HoverCardController: React.FC = () => { }; const handleMouseLeave = (e: MouseEvent) => { + const { target } = e; + if (!currentAnchor) { return; } - if (e.target === currentAnchor || e.target === cardRef.current) { + if ( + currentTitle && + target instanceof HTMLElement && + target === currentAnchor + ) + target.setAttribute('title', currentTitle); + + if (target === currentAnchor || target === cardRef.current) { cancelEnterTimeout(); setLeaveTimeout(() => { diff --git a/app/javascript/mastodon/components/media_gallery.jsx b/app/javascript/mastodon/components/media_gallery.jsx index d3b5b284b8..f102ab0f26 100644 --- a/app/javascript/mastodon/components/media_gallery.jsx +++ b/app/javascript/mastodon/components/media_gallery.jsx @@ -13,7 +13,7 @@ import { debounce } from 'lodash'; import VisibilityOffIcon from '@/material-icons/400-24px/visibility_off.svg?react'; import { Blurhash } from 'mastodon/components/blurhash'; -import { autoPlayGif, displayMedia, displayMediaExpand, useBlurhash } from '../initial_state'; +import { autoPlayGif, displayMedia, useBlurhash } from '../initial_state'; import { IconButton } from './icon_button'; @@ -322,15 +322,13 @@ class MediaGallery extends PureComponent { style.aspectRatio = '3 / 2'; } - const maxSize = displayMediaExpand ? 16 : 4; - - const size = media.take(maxSize).size; + const size = media.size; const uncached = media.every(attachment => attachment.get('type') === 'unknown'); if (this.isFullSizeEligible()) { children = ; } else { - children = media.take(maxSize).map((attachment, i) => ); + children = media.map((attachment, i) => ); } if (uncached) { diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index cf9024fe29..3f2e612e7f 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -641,7 +641,7 @@ class Status extends ImmutablePureComponent { {status.get('edited_at') && *} - +
{statusAvatar}
diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx index 21c8bd2e47..18ff62f79d 100644 --- a/app/javascript/mastodon/components/status_content.jsx +++ b/app/javascript/mastodon/components/status_content.jsx @@ -116,7 +116,7 @@ class StatusContent extends PureComponent { if (mention) { link.addEventListener('click', this.onMentionClick.bind(this, mention), false); - link.removeAttribute('title'); + link.setAttribute('title', `@${mention.get('acct')}`); link.setAttribute('href', `/@${mention.get('acct')}`); link.setAttribute('data-hover-card-account', mention.get('id')); } else if (link.textContent[0] === '#' || (link.previousSibling && link.previousSibling.textContent && link.previousSibling.textContent[link.previousSibling.textContent.length - 1] === '#')) { diff --git a/app/javascript/mastodon/features/compose/containers/upload_button_container.js b/app/javascript/mastodon/features/compose/containers/upload_button_container.js index 8901a0e54c..08adf130b4 100644 --- a/app/javascript/mastodon/features/compose/containers/upload_button_container.js +++ b/app/javascript/mastodon/features/compose/containers/upload_button_container.js @@ -8,7 +8,7 @@ const mapStateToProps = state => { const readyAttachmentsSize = state.getIn(['compose', 'media_attachments']).size ?? 0; const pendingAttachmentsSize = state.getIn(['compose', 'pending_media_attachments']).size ?? 0; const attachmentsSize = readyAttachmentsSize + pendingAttachmentsSize; - const isOverLimit = attachmentsSize > 3; + const isOverLimit = attachmentsSize > state.getIn(['server', 'server', 'configuration', 'statuses', 'max_media_attachments'])-1; const hasVideoOrAudio = state.getIn(['compose', 'media_attachments']).some(m => ['video', 'audio'].includes(m.get('type'))); return { diff --git a/app/javascript/mastodon/features/notifications/components/notification.jsx b/app/javascript/mastodon/features/notifications/components/notification.jsx index ec4a2df8c9..13d4a85974 100644 --- a/app/javascript/mastodon/features/notifications/components/notification.jsx +++ b/app/javascript/mastodon/features/notifications/components/notification.jsx @@ -548,7 +548,7 @@ class Notification extends ImmutablePureComponent { const targetAccount = report.get('target_account'); const targetDisplayNameHtml = { __html: targetAccount.get('display_name_html') }; - const targetLink = ; + const targetLink = ; return ( @@ -571,7 +571,7 @@ class Notification extends ImmutablePureComponent { const { notification } = this.props; const account = notification.get('account'); const displayNameHtml = { __html: account.get('display_name_html') }; - const link = ; + const link = ; switch(notification.get('type')) { case 'follow': diff --git a/app/javascript/mastodon/features/notifications/index.jsx b/app/javascript/mastodon/features/notifications/index.jsx index d45f517152..54883096ef 100644 --- a/app/javascript/mastodon/features/notifications/index.jsx +++ b/app/javascript/mastodon/features/notifications/index.jsx @@ -223,6 +223,13 @@ class Notifications extends PureComponent { let scrollContainer; + const prepend = ( + <> + {needsNotificationPermission && } + + + ); + if (signedIn) { scrollContainer = ( } + prepend={prepend} alwaysPrepend emptyMessage={emptyMessage} onLoadMore={this.handleLoadOlder} @@ -282,8 +289,6 @@ class Notifications extends PureComponent { {filterBarContainer} - - {scrollContainer} diff --git a/app/javascript/mastodon/features/status/components/card.jsx b/app/javascript/mastodon/features/status/components/card.jsx index f0ae40cbc4..ee1fbe0f8f 100644 --- a/app/javascript/mastodon/features/status/components/card.jsx +++ b/app/javascript/mastodon/features/status/components/card.jsx @@ -141,7 +141,7 @@ export default class Card extends PureComponent { const showAuthor = !!card.getIn(['authors', 0, 'accountId']); const description = ( -
+
{provider} {card.get('published_at') && <> · } diff --git a/app/javascript/mastodon/features/ui/index.jsx b/app/javascript/mastodon/features/ui/index.jsx index 82e08830b3..6da280ac67 100644 --- a/app/javascript/mastodon/features/ui/index.jsx +++ b/app/javascript/mastodon/features/ui/index.jsx @@ -25,7 +25,7 @@ import { clearHeight } from '../../actions/height_cache'; import { expandNotifications } from '../../actions/notifications'; import { fetchServer, fetchServerTranslationLanguages } from '../../actions/server'; import { expandHomeTimeline } from '../../actions/timelines'; -import initialState, { me, owner, singleUserMode, trendsEnabled, trendsAsLanding } from '../../initial_state'; +import initialState, { me, owner, singleUserMode, trendsEnabled, trendsAsLanding, disableHoverCards } from '../../initial_state'; import BundleColumnError from './components/bundle_column_error'; import Header from './components/header'; @@ -623,7 +623,7 @@ class UI extends PureComponent { {layout !== 'mobile' && } - + {!disableHoverCards && } diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js index dc04c5449d..ecb99f38d7 100644 --- a/app/javascript/mastodon/initial_state.js +++ b/app/javascript/mastodon/initial_state.js @@ -31,10 +31,10 @@ * @property {boolean=} boost_modal * @property {boolean=} delete_modal * @property {boolean=} disable_swiping + * @property {boolean=} disable_hover_cards * @property {string=} disabled_account_id * @property {string[]} enabled_visibilities * @property {string} display_media - * @property {boolean} display_media_expand * @property {string} domain * @property {string} dtl_tag * @property {boolean} enable_emoji_reaction @@ -128,10 +128,10 @@ export const bookmarkCategoryNeeded = getMeta('bookmark_category_needed'); export const boostModal = getMeta('boost_modal'); export const deleteModal = getMeta('delete_modal'); export const disableSwiping = getMeta('disable_swiping'); +export const disableHoverCards = getMeta('disable_hover_cards'); export const disabledAccountId = getMeta('disabled_account_id'); export const enabledVisibilites = getMeta('enabled_visibilities'); export const displayMedia = getMeta('display_media'); -export const displayMediaExpand = getMeta('display_media_expand'); export const domain = getMeta('domain'); export const dtlTag = getMeta('dtl_tag'); export const enableEmojiReaction = getMeta('enable_emoji_reaction'); diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index a9e1bdb270..5509769e04 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -4,7 +4,7 @@ "about.disclaimer": "ماستدون برنامج حر ومفتوح المصدر وعلامة تجارية لـ Mastodon GmbH.", "about.domain_blocks.no_reason_available": "السبب غير متوفر", "about.domain_blocks.preamble": "يسمح لك ماستدون عموماً بعرض المحتوى من المستخدمين من أي خادم آخر في الفدرالية والتفاعل معهم. وهذه هي الاستثناءات التي وضعت على هذا الخادم بالذات.", - "about.domain_blocks.silenced.explanation": "عموماً، لن ترى ملفات التعريف والمحتوى من هذا الخادم، إلا إذا كنت تبحث عنه بشكل صريح أو تختار أن تتابعه.", + "about.domain_blocks.silenced.explanation": "لن تظهر لك ملفات التعريف الشخصية والمحتوى من هذا الخادوم، إلا إن بحثت عنه عمدًا أو تابعته.", "about.domain_blocks.silenced.title": "محدود", "about.domain_blocks.suspended.explanation": "لن يتم معالجة أي بيانات من هذا الخادم أو تخزينها أو تبادلها، مما يجعل أي تفاعل أو اتصال مع المستخدمين من هذا الخادم مستحيلا.", "about.domain_blocks.suspended.title": "مُعلّق", @@ -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": "اسم النِّطاق محظور", @@ -32,9 +32,10 @@ "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": "{count, plural, zero {}one {{counter} متابع} two {{counter} متابعين} few {{counter} متابعين} many {{counter} متابعين} other {{counter} متابعين}}", "account.following": "الاشتراكات", "account.follows.empty": "لا يُتابع هذا المُستخدمُ أيَّ أحدٍ حتى الآن.", "account.go_to_profile": "اذهب إلى الملف الشخصي", @@ -51,7 +52,7 @@ "account.mute_notifications_short": "كتم الإشعارات", "account.mute_short": "اكتم", "account.muted": "مَكتوم", - "account.mutual": "متبادل", + "account.mutual": "متبادلة", "account.no_bio": "لم يتم تقديم وصف.", "account.open_original_page": "افتح الصفحة الأصلية", "account.posts": "منشورات", @@ -70,8 +71,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": "المستخدمون الجدد", @@ -87,12 +88,12 @@ "attachments_list.unprocessed": "(غير معالَج)", "audio.hide": "إخفاء المقطع الصوتي", "block_modal.remote_users_caveat": "سوف نطلب من الخادم {domain} أن يحترم قرارك، لكن الالتزام غير مضمون لأن بعض الخواديم قد تتعامل مع نصوص الكتل بشكل مختلف. قد تظل المنشورات العامة مرئية للمستخدمين غير المسجلين الدخول.", - "block_modal.show_less": "أظهر الأقل", - "block_modal.show_more": "أظهر المزيد", + "block_modal.show_less": "تفاصيل أقلّ", + "block_modal.show_more": "تفاصيل أكثر", "block_modal.they_cant_mention": "لن يستطيع ذِكرك أو متابعتك.", - "block_modal.they_cant_see_posts": "لن يستطيع رؤية منشوراتك ولن ترى منشوراته.", - "block_modal.they_will_know": "يمكنه أن يرى أنه قد تم حظره.", - "block_modal.title": "أتريد حظر المستخدم؟", + "block_modal.they_cant_see_posts": "لن يستطيع مطالعة منشوراتك ولن تطالع منشوراته.", + "block_modal.they_will_know": "سيعلم أنه قد حُظِر.", + "block_modal.title": "أتريد حظر هذا المستخدم؟", "block_modal.you_wont_see_mentions": "لن تر المنشورات التي يُشار فيهم إليه.", "boost_modal.combo": "يُمكنك الضّغط على {combo} لتخطي هذا في المرة المُقبلة", "bundle_column_error.copy_stacktrace": "انسخ تقرير الخطأ", @@ -156,7 +157,7 @@ "compose_form.poll.single": "اختر واحدا", "compose_form.poll.switch_to_multiple": "تغيِير الاستطلاع للسماح باِخيارات مُتعدِّدة", "compose_form.poll.switch_to_single": "تغيِير الاستطلاع للسماح باِخيار واحد فقط", - "compose_form.poll.type": "الأسلوب", + "compose_form.poll.type": "الطراز", "compose_form.publish": "نشر", "compose_form.publish_form": "منشور جديد", "compose_form.reply": "ردّ", diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json index 643725270c..df29fbd418 100644 --- a/app/javascript/mastodon/locales/be.json +++ b/app/javascript/mastodon/locales/be.json @@ -35,7 +35,9 @@ "account.follow_back": "Падпісацца ў адказ", "account.followers": "Падпісчыкі", "account.followers.empty": "Ніхто пакуль не падпісаны на гэтага карыстальніка.", + "account.followers_counter": "{count, plural, one {{counter} падпісчык} few {{counter} падпісчыкі} many {{counter} падпісчыкаў} other {{counter} падпісчыка}}", "account.following": "Падпіскі", + "account.following_counter": "{count, plural, one {{counter} падпіска} few {{counter} падпіскі} many {{counter} падпісак} other {{counter} падпіскі}}", "account.follows.empty": "Карыстальнік ні на каго не падпісаны.", "account.go_to_profile": "Перайсці да профілю", "account.hide_reblogs": "Схаваць пашырэнні ад @{name}", @@ -61,6 +63,7 @@ "account.requested_follow": "{name} адправіў запыт на падпіску", "account.share": "Абагуліць профіль @{name}", "account.show_reblogs": "Паказаць падштурхоўванні ад @{name}", + "account.statuses_counter": "{count, plural, one {{counter} допіс} few {{counter} допісы} many {{counter} допісаў} other {{counter} допісу}}", "account.unblock": "Разблакіраваць @{name}", "account.unblock_domain": "Разблакіраваць дамен {domain}", "account.unblock_short": "Разблакіраваць", @@ -412,6 +415,7 @@ "limited_account_hint.title": "Гэты профіль быў схаваны мадэратарамі", "link_preview.author": "Ад {name}", "link_preview.more_from_author": "Больш ад {name}", + "link_preview.shares": "{count, plural, one {{counter} допіс} few {{counter} допісы} many {{counter} допісаў} other {{counter} допісу}}", "lists.account.add": "Дадаць да спісу", "lists.account.remove": "Выдаліць са спісу", "lists.delete": "Выдаліць спіс", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 323890ba2e..98e84c45d7 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -35,7 +35,9 @@ "account.follow_back": "Последване взаимно", "account.followers": "Последователи", "account.followers.empty": "Още никой не следва потребителя.", + "account.followers_counter": "{count, plural, one {{counter} последовател} other {{counter} последователи}}", "account.following": "Последвано", + "account.following_counter": "{count, plural, one {{counter} последван} other {{counter} последвани}}", "account.follows.empty": "Потребителят още никого не следва.", "account.go_to_profile": "Към профила", "account.hide_reblogs": "Скриване на подсилвания от @{name}", @@ -61,6 +63,7 @@ "account.requested_follow": "{name} поиска да ви последва", "account.share": "Споделяне на профила на @{name}", "account.show_reblogs": "Показване на подсилвания от @{name}", + "account.statuses_counter": "{count, plural, one {{counter} публикация} other {{counter} публикации}}", "account.unblock": "Отблокиране на @{name}", "account.unblock_domain": "Отблокиране на домейн {domain}", "account.unblock_short": "Отблокиране", diff --git a/app/javascript/mastodon/locales/cs.json b/app/javascript/mastodon/locales/cs.json index e96e283970..12de5d5ecd 100644 --- a/app/javascript/mastodon/locales/cs.json +++ b/app/javascript/mastodon/locales/cs.json @@ -197,7 +197,7 @@ "copy_icon_button.copied": "Zkopírováno do schránky", "copypaste.copied": "Zkopírováno", "copypaste.copy_to_clipboard": "Zkopírovat do schránky", - "directory.federated": "Ze známého fedivesmíru", + "directory.federated": "Ze známého fediversu", "directory.local": "Pouze z {domain}", "directory.new_arrivals": "Nově příchozí", "directory.recently_active": "Nedávno aktivní", @@ -213,7 +213,7 @@ "domain_block_modal.block_account_instead": "Raději blokovat @{name}", "domain_block_modal.they_can_interact_with_old_posts": "Lidé z tohoto serveru mohou interagovat s vašimi starými příspěvky.", "domain_block_modal.they_cant_follow": "Nikdo z tohoto serveru vás nemůže sledovat.", - "domain_block_modal.they_wont_know": "Nebude vědět, že je zablokován.", + "domain_block_modal.they_wont_know": "Nebude vědět, že je zablokován*a.", "domain_block_modal.title": "Blokovat doménu?", "domain_block_modal.you_will_lose_followers": "Všichni vaši sledující z tohoto serveru budou odstraněni.", "domain_block_modal.you_wont_see_posts": "Neuvidíte příspěvky ani upozornění od uživatelů z tohoto serveru.", @@ -341,7 +341,7 @@ "hashtag.column_settings.tag_mode.any": "Jakýkoliv z těchto", "hashtag.column_settings.tag_mode.none": "Žádný z těchto", "hashtag.column_settings.tag_toggle": "Zahrnout v tomto sloupci další štítky", - "hashtag.counter_by_accounts": "{count, plural, one {{counter} účastník} few {{counter} účastníci} other {{counter} účastníků}}", + "hashtag.counter_by_accounts": "{count, plural, one {{counter} účastník*ice} few {{counter} účastníci} other {{counter} účastníků}}", "hashtag.counter_by_uses": "{count, plural, one {{counter} příspěvek} few {{counter} příspěvky} other {{counter} příspěvků}}", "hashtag.counter_by_uses_today": "Dnes {count, plural, one {{counter} příspěvek} few {{counter} příspěvky} other {{counter} příspěvků}}", "hashtag.follow": "Sledovat hashtag", @@ -440,7 +440,7 @@ "mute_modal.show_options": "Zobrazit možnosti", "mute_modal.they_can_mention_and_follow": "Mohou vás zmínit a sledovat, ale neuvidíte je.", "mute_modal.they_wont_know": "Nebudou vědět, že byli skryti.", - "mute_modal.title": "Ztlumit uživatele?", + "mute_modal.title": "Ztlumit uživatele*ku?", "mute_modal.you_wont_see_mentions": "Neuvidíte příspěvky, které je zmiňují.", "mute_modal.you_wont_see_posts": "Stále budou moci vidět vaše příspěvky, ale vy jejich neuvidíte.", "navigation_bar.about": "O aplikaci", @@ -566,8 +566,8 @@ "onboarding.share.message": "Jsem {username} na #Mastodonu! Pojď mě sledovat na {url}", "onboarding.share.next_steps": "Možné další kroky:", "onboarding.share.title": "Sdílejte svůj profil", - "onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:", - "onboarding.start.skip": "Want to skip right ahead?", + "onboarding.start.lead": "Nyní jste součástí Mastodonu, unikátní sociální sítě, kde vy - ne algoritmus - vytváří vaše vlastní prožitky. Začněte na této nové sociální platformě:", + "onboarding.start.skip": "Nepotřebujete pomoci začít?", "onboarding.start.title": "Dokázali jste to!", "onboarding.steps.follow_people.body": "Mastodon je o sledování zajimavých lidí.", "onboarding.steps.follow_people.title": "Přispůsobit vlastní domovský kanál", @@ -581,7 +581,7 @@ "onboarding.tips.accounts_from_other_servers": "Víte, že? Protože je Mastodon decentralizovaný, některé profily, na které narazíte, budou hostovány na jiných serverech, než je ten váš. A přesto s nimi můžete bezproblémově komunikovat! Jejich server se nachází v druhé polovině uživatelského jména!", "onboarding.tips.migration": "Víte, že? Pokud máte pocit, že {domain} pro vás v budoucnu není vhodnou volbou, můžete se přesunout na jiný Mastodon server, aniž byste přišli o své sledující. Můžete dokonce hostovat svůj vlastní server!", "onboarding.tips.verification": "Víte, že? Svůj účet můžete ověřit tak, že na své webové stránky umístíte odkaz na váš Mastodon profil a odkaz na stránku přidáte do svého profilu. Nejsou k tomu potřeba žádné poplatky ani dokumenty!", - "password_confirmation.exceeds_maxlength": "Potvrzení hesla překračuje maximální délku hesla", + "password_confirmation.exceeds_maxlength": "Potvrzení hesla překračuje maximální povolenou délku hesla", "password_confirmation.mismatching": "Zadaná hesla se neshodují", "picture_in_picture.restore": "Vrátit zpět", "poll.closed": "Uzavřeno", @@ -665,7 +665,7 @@ "report.unfollow": "Přestat sledovat @{name}", "report.unfollow_explanation": "Tento účet sledujete. Abyste už neviděli jeho příspěvky ve své domovské časové ose, přestaňte jej sledovat.", "report_notification.attached_statuses": "{count, plural, one {{count} připojený příspěvek} few {{count} připojené příspěvky} many {{count} připojených příspěvků} other {{count} připojených příspěvků}}", - "report_notification.categories.legal": "Zákonné", + "report_notification.categories.legal": "Právní ustanovení", "report_notification.categories.other": "Ostatní", "report_notification.categories.spam": "Spam", "report_notification.categories.violation": "Porušení pravidla", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index 86438757a3..0f3b3c91a9 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -205,10 +205,10 @@ "disabled_account_banner.text": "Dein Konto {disabledAccount} ist derzeit deaktiviert.", "dismissable_banner.community_timeline": "Das sind die neuesten öffentlichen Beiträge von Profilen, deren Konten von {domain} verwaltet werden.", "dismissable_banner.dismiss": "Ablehnen", - "dismissable_banner.explore_links": "Diese Nachrichten werden heute am häufigsten im sozialen Netzwerk geteilt. Neuere Nachrichten, die von vielen verschiedenen Profilen veröffentlicht wurden, werden höher eingestuft.", - "dismissable_banner.explore_statuses": "Diese Beiträge stammen aus dem gesamten sozialen Netzwerk und gewinnen derzeit an Reichweite. Neuere Beiträge, die häufiger geteilt und favorisiert wurden, werden höher eingestuft.", - "dismissable_banner.explore_tags": "Das sind Hashtags, die derzeit an Reichweite gewinnen. Hashtags, die von vielen verschiedenen Profilen verwendet werden, werden höher eingestuft.", - "dismissable_banner.public_timeline": "Das sind die neuesten öffentlichen Beiträge von Profilen im sozialen Netzwerk, denen Leute auf {domain} folgen.", + "dismissable_banner.explore_links": "Diese Nachrichten werden heute am häufigsten im Social Web geteilt. Neuere Nachrichten, die von vielen verschiedenen Profilen geteilt wurden, erscheinen weiter oben.", + "dismissable_banner.explore_statuses": "Diese Beiträge sind heute im Social Web sehr beliebt. Neuere Beiträge, die häufiger geteilt und favorisiert wurden, erscheinen weiter oben.", + "dismissable_banner.explore_tags": "Diese Hashtags sind heute im Social Web sehr beliebt. Hashtags, die von vielen verschiedenen Profilen verwendet werden, erscheinen weiter oben.", + "dismissable_banner.public_timeline": "Das sind die neuesten öffentlichen Beiträge von Profilen im Social Web, denen Leute auf {domain} folgen.", "domain_block_modal.block": "Server blockieren", "domain_block_modal.block_account_instead": "Stattdessen @{name} blockieren", "domain_block_modal.they_can_interact_with_old_posts": "Profile von diesem Server werden mit deinen älteren Beiträgen interagieren können.", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index 21eaeab0e6..794360fc64 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -45,7 +45,9 @@ "account.follow_back": "フォローバック", "account.followers": "フォロワー", "account.followers.empty": "まだ誰もフォローしていません。", + "account.followers_counter": "{count, plural, other {{counter} フォロワー}}", "account.following": "フォロー中", + "account.following_counter": "{count, plural, other {{counter} フォロー}}", "account.follows.empty": "まだ誰もフォローしていません。", "account.go_to_profile": "プロフィールページへ", "account.hide_reblogs": "@{name}さんからのブーストを非表示", @@ -71,6 +73,7 @@ "account.requested_follow": "{name}さんがあなたにフォローリクエストしました", "account.share": "@{name}さんのプロフィールを共有する", "account.show_reblogs": "@{name}さんからのブーストを表示", + "account.statuses_counter": "{count, plural, other {{counter} 投稿}}", "account.unblock": "@{name}さんのブロックを解除", "account.unblock_domain": "{domain}のブロックを解除", "account.unblock_short": "ブロック解除", @@ -506,6 +509,8 @@ "limited_account_hint.action": "構わず表示する", "limited_account_hint.title": "このプロフィールは{domain}のモデレーターによって非表示にされています。", "link_preview.author": "{name}", + "link_preview.more_from_author": "{name}さんの投稿をもっと読む", + "link_preview.shares": "{count, plural, other {{counter}件の投稿}}", "lists.account.add": "リストに追加", "lists.account.remove": "リストから外す", "lists.antennas": "関連付けられたアンテナ", @@ -830,8 +835,11 @@ "server_banner.about_active_users": "過去30日間にこのサーバーを使用している人 (月間アクティブユーザー)", "server_banner.active_users": "人のアクティブユーザー", "server_banner.administered_by": "管理者", + "server_banner.is_one_of_many": "{domain} は、数々の独立したMastodonサーバーのうちのひとつです。サーバーに登録してFediverseのコミュニティに加わってみませんか。", "server_banner.server_stats": "サーバーの情報", "sign_in_banner.create_account": "アカウント作成", + "sign_in_banner.follow_anyone": "連合内の誰でもフォローして投稿を時系列で見ることができます。アルゴリズム、広告、クリックベイトはありません。", + "sign_in_banner.mastodon_is": "Mastodonに参加して、世界で起きていることを見つけよう。", "sign_in_banner.sign_in": "ログイン", "sign_in_banner.sso_redirect": "ログインまたは登録", "status.admin_account": "@{name}さんのモデレーション画面を開く", diff --git a/app/javascript/mastodon/locales/kab.json b/app/javascript/mastodon/locales/kab.json index de866cc1bc..868edbc8c0 100644 --- a/app/javascript/mastodon/locales/kab.json +++ b/app/javascript/mastodon/locales/kab.json @@ -1,6 +1,10 @@ { + "about.blocks": "Ulac agbur", "about.contact": "Anermis:", "about.disclaimer": "Mastodon d aseɣẓan ilelli, d aseɣẓan n uɣbalu yeldin, d tnezzut n Mastodon gGmbH.", + "about.domain_blocks.preamble": "Maṣṭudun s umata yeḍmen-ak ad teẓreḍ agbur, ad tesdemreḍ akked yimseqdacen-nniḍen seg yal aqeddac deg fedivers. Ha-tent-an ɣur-k tsuraf i yellan deg uqeddac-agi.", + "about.domain_blocks.silenced.title": "Ɣur-s talast", + "about.domain_blocks.suspended.title": "Yeḥbes", "about.not_available": "Talɣut-a ur tettwabder ara deg uqeddac-a.", "about.powered_by": "Azeṭṭa inmetti yettwasɣelsen sɣur {mastodon}", "about.rules": "Ilugan n uqeddac", @@ -24,9 +28,12 @@ "account.featured_tags.last_status_at": "Tasuffeɣt taneggarut ass n {date}", "account.featured_tags.last_status_never": "Ulac tisuffaɣ", "account.follow": "Ḍfer", + "account.follow_back": "Ḍfer-it ula d kečč·m", "account.followers": "Imeḍfaren", "account.followers.empty": "Ar tura, ulac yiwen i yeṭṭafaṛen amseqdac-agi.", + "account.followers_counter": "{count, plural, one {{counter} n umḍfar} other {{counter} n yimeḍfaren}}", "account.following": "Yeṭṭafaṛ", + "account.following_counter": "{count, plural, one {{counter} yettwaḍfaren} other {{counter} yettwaḍfaren}}", "account.follows.empty": "Ar tura, amseqdac-agi ur yeṭṭafaṛ yiwen.", "account.go_to_profile": "Ddu ɣer umaɣnu", "account.hide_reblogs": "Ffer ayen i ibeṭṭu @{name}", @@ -49,6 +56,7 @@ "account.requested_follow": "{name} yessuter ad k·m-yeḍfer", "account.share": "Bḍu amaɣnu n @{name}", "account.show_reblogs": "Ssken-d inebḍa n @{name}", + "account.statuses_counter": "{count, plural, one {{counter} n tsuffeɣt} other {{counter} n tsuffaɣ}}", "account.unblock": "Serreḥ i @{name}", "account.unblock_domain": "Ssken-d {domain}", "account.unblock_short": "Serreḥ", @@ -166,6 +174,7 @@ "dismissable_banner.explore_tags": "D wiyi i d ihacṭagen i d-yettawin tamyigawt deg web anmetti ass-a. Ihacṭagen i sseqdacen ugar n medden, εlayit d imezwura.", "domain_block_modal.block": "Sewḥel aqeddac", "domain_block_modal.they_cant_follow": "Yiwen ur yezmir ad k·m-id-yeḍfer seg uqeddac-a.", + "domain_block_modal.title": "Sewḥel taɣult?", "domain_pill.activitypub_like_language": "ActivityPub am tutlayt yettmeslay Mastodon d izeḍwan inmettiyen nniḍen.", "domain_pill.server": "Aqeddac", "domain_pill.username": "Isem n useqdac", @@ -214,6 +223,7 @@ "filter_modal.added.review_and_configure_title": "Iɣewwaṛen n imzizdig", "filter_modal.added.settings_link": "asebter n yiɣewwaṛen", "filter_modal.added.short_explanation": "Tasuffeɣt-a tettwarna ɣer taggayt-a n yimsizdegen: {title}.", + "filter_modal.added.title": "Yettwarna umsizdeg!", "filter_modal.select_filter.expired": "yemmut", "filter_modal.select_filter.prompt_new": "Taggayt tamaynutt : {name}", "filter_modal.select_filter.search": "Nadi neɣ snulfu-d", @@ -224,9 +234,9 @@ "firehose.remote": "Iqeddacen nniḍen", "follow_request.authorize": "Ssireg", "follow_request.reject": "Agi", - "follow_suggestions.dismiss": "Ur ttɛawad ara ad t-id-sekneṭ", + "follow_suggestions.dismiss": "Dayen ur t-id-skan ara", "follow_suggestions.view_all": "Wali-ten akk", - "follow_suggestions.who_to_follow": "Menhu ara ḍefṛeḍ", + "follow_suggestions.who_to_follow": "Ad tḍefreḍ?", "followed_tags": "Ihacṭagen yettwaḍfaren", "footer.about": "Ɣef", "footer.directory": "Akaram n imeɣna", @@ -235,6 +245,7 @@ "footer.keyboard_shortcuts": "Inegzumen n unasiw", "footer.privacy_policy": "Tasertit tabaḍnit", "footer.source_code": "Wali tangalt taɣbalut", + "footer.status": "N tsuffeɣt", "generic.saved": "Yettwasekles", "getting_started.heading": "Bdu", "hashtag.column_header.tag_mode.all": "d {additional}", @@ -313,11 +324,14 @@ "lightbox.previous": "Ɣer deffir", "limited_account_hint.action": "Wali amaɣnu akken yebɣu yili", "link_preview.author": "S-ɣur {name}", + "link_preview.more_from_author": "Ugar sɣur {name}", + "link_preview.shares": "{count, plural, one {{counter} post} other {{counter} posts}}", "lists.account.add": "Rnu ɣer tebdart", "lists.account.remove": "Kkes seg tebdart", "lists.delete": "Kkes tabdart", "lists.edit": "Ẓreg tabdart", "lists.edit.submit": "Beddel azwel", + "lists.exclusive": "Ffer tisuffaɣ-a seg ugejdan", "lists.new.create": "Rnu tabdart", "lists.new.title_placeholder": "Azwel amaynut n tebdart", "lists.replies_policy.followed": "Kra n useqdac i yettwaḍefren", @@ -338,6 +352,7 @@ "navigation_bar.bookmarks": "Ticraḍ", "navigation_bar.community_timeline": "Tasuddemt tadigant", "navigation_bar.compose": "Aru tajewwiqt tamaynut", + "navigation_bar.direct": "Tibdarin tusligin", "navigation_bar.discover": "Ẓer", "navigation_bar.domain_blocks": "Tiɣula yeffren", "navigation_bar.explore": "Snirem", @@ -357,9 +372,14 @@ "navigation_bar.search": "Nadi", "navigation_bar.security": "Taɣellist", "not_signed_in_indicator.not_signed_in": "You need to sign in to access this resource.", + "notification.admin.report": "Yemla-t-id {name} {target}", + "notification.admin.sign_up": "Ijerred {name}", + "notification.favourite": "{name} yesmenyaf addad-ik·im", "notification.follow": "iṭṭafar-ik·em-id {name}", "notification.follow_request": "{name} yessuter-d ad k·m-yeḍfeṛ", "notification.mention": "{name} yebder-ik-id", + "notification.moderation-warning.learn_more": "Issin ugar", + "notification.moderation_warning.action_suspend": "Yettwaseḥbes umiḍan-ik.", "notification.own_poll": "Tafrant-ik·im tfuk", "notification.poll": "Tfukk tefrant ideg tettekkaḍ", "notification.reblog": "{name} yebḍa tajewwiqt-ik i tikelt-nniḍen", @@ -370,6 +390,7 @@ "notification_requests.notifications_from": "Ilɣa sɣur {name}", "notifications.clear": "Sfeḍ tilɣa", "notifications.clear_confirmation": "Tebɣiḍ s tidet ad tekkseḍ akk tilɣa-inek·em i lebda?", + "notifications.column_settings.admin.report": "Ineqqisen imaynuten:", "notifications.column_settings.alert": "Tilɣa n tnarit", "notifications.column_settings.favourite": "Imenyafen:", "notifications.column_settings.filter_bar.advanced": "Sken-d akk taggayin", @@ -384,6 +405,7 @@ "notifications.column_settings.sound": "Rmed imesli", "notifications.column_settings.status": "Tisuffaɣ timaynutin :", "notifications.column_settings.unread_notifications.category": "Ilɣa ur nettwaɣra", + "notifications.column_settings.update": "Iẓreg:", "notifications.filter.all": "Akk", "notifications.filter.boosts": "Seǧhed", "notifications.filter.favourites": "Imenyafen", @@ -413,6 +435,7 @@ "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", "onboarding.follows.title": "Ttwassnen deg Mastodon", "onboarding.profile.display_name": "Isem ara d-yettwaskanen", + "onboarding.profile.display_name_hint": "Isem-ik·im ummid neɣ isem-ik·im n uqeṣṣer…", "onboarding.profile.note": "Tameddurt", "onboarding.profile.note_hint": "Tzemreḍ ad d-@tbedreḍ imdanen niḍen neɣ #ihacṭagen …", "onboarding.profile.save_and_continue": "Sekles, tkemmleḍ", @@ -441,6 +464,7 @@ "poll.total_votes": "{count, plural, one {# n udɣaṛ} other {# n yedɣaṛen}}", "poll.vote": "Dɣeṛ", "poll.voted": "Tdeɣṛeḍ ɣef tririt-ayi", + "poll.votes": "{votes, plural, one {# n udɣaṛ} other {# n yedɣaṛen}}", "poll_button.add_poll": "Rnu asenqed", "poll_button.remove_poll": "Kkes asenqed", "privacy.change": "Seggem tabaḍnit n yizen", @@ -465,9 +489,12 @@ "relative_time.seconds": "{number}tas", "relative_time.today": "assa", "reply_indicator.cancel": "Sefsex", + "reply_indicator.poll": "Afmiḍi", "report.block": "Sewḥel", + "report.categories.legal": "Azerfan", "report.categories.other": "Tiyyaḍ", "report.categories.spam": "Aspam", + "report.category.subtitle": "Fren amṣada akk ufrin", "report.category.title_account": "ameɣnu", "report.category.title_status": "tasuffeɣt", "report.close": "Immed", @@ -476,13 +503,25 @@ "report.next": "Uḍfiṛ", "report.placeholder": "Iwenniten-nniḍen", "report.reasons.dislike": "Ur t-ḥemmleɣ ara", + "report.reasons.dislike_description": "D ayen akk ur bɣiɣ ara ad waliɣ", "report.reasons.other": "D ayen nniḍen", + "report.reasons.other_description": "Ugur ur yemṣada ara akk d taggayin-nniḍen", "report.reasons.spam": "D aspam", + "report.reasons.spam_description": "Yir iseɣwan, yir agman d tririyin i d-yettuɣalen", + "report.reasons.violation": "Truẓi n yilugan n uqeddac", + "report.reasons.violation_description": "Teẓriḍ y·tettruẓu kra n yilugan", + "report.rules.subtitle": "Fren ayen akk yemṣadan", + "report.rules.title": "Acu n yilugan i yettwarẓan?", + "report.statuses.subtitle": "Fren ayen akk yemṣadan", + "report.statuses.title": "Llant tsuffaɣ ara isdemren aneqqis-a?", "report.submit": "Azen", "report.target": "Mmel {target}", + "report.thanks.take_action_actionable": "Ideg nekkni nessenqad tuttra-inek•inem, tzemreḍ ad tḥadreḍ mgal @{name}:", "report.thanks.title": "Ur tebɣiḍ ara ad twaliḍ aya?", + "report.thanks.title_actionable": "Tanemmirt ɣef uneqqis, ad nwali deg waya.", "report.unfollow": "Seḥbes aḍfar n @{name}", "report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached", + "report_notification.categories.legal": "Azerfan", "report_notification.categories.other": "Ayen nniḍen", "report_notification.categories.spam": "Aspam", "report_notification.open": "Ldi aneqqis", @@ -497,6 +536,7 @@ "search_popout.full_text_search_disabled_message": "Ur yelli ara deg {domain}.", "search_popout.language_code": "Tangalt ISO n tutlayt", "search_popout.options": "Iwellihen n unadi", + "search_popout.quick_actions": "Tigawin tiruradin", "search_popout.recent": "Inadiyen ineggura", "search_popout.user": "amseqdac", "search_results.accounts": "Imeɣna", @@ -505,7 +545,9 @@ "search_results.see_all": "Wali-ten akk", "search_results.statuses": "Tisuffaɣ", "search_results.title": "Anadi ɣef {q}", + "server_banner.active_users": "iseqdacen urmiden", "server_banner.administered_by": "Yettwadbel sɣur :", + "server_banner.server_stats": "Tidaddanin n uqeddac:", "sign_in_banner.create_account": "Snulfu-d amiḍan", "sign_in_banner.sign_in": "Qqen", "sign_in_banner.sso_redirect": "Qqen neɣ jerred", @@ -516,13 +558,21 @@ "status.cannot_reblog": "Tasuffeɣt-a ur tezmir ara ad tettwabḍu tikelt-nniḍen", "status.copy": "Nɣel assaɣ ɣer tasuffeɣt", "status.delete": "Kkes", + "status.direct": "Bder-d @{name} weḥd-s", + "status.direct_indicator": "Abdar uslig", "status.edit": "Ẓreg", "status.edited_x_times": "Tettwaẓreg {count, plural, one {{count} n tikkelt} other {{count} n tikkal}}", "status.embed": "Seddu", + "status.favourite": "Amenyaf", + "status.favourites": "{count, plural, one {n usmenyaf} other {n ismenyafen}}", "status.filter": "Sizdeg tassufeɣt-a", "status.filtered": "Yettwasizdeg", "status.hide": "Ffer tasuffeɣt", + "status.history.created": "Yerna-t {name} {date}", + "status.history.edited": "Ibeddel-it {name} {date}", "status.load_more": "Sali ugar", + "status.media.open": "Sit i ulday", + "status.media.show": "Sit i uskan", "status.media_hidden": "Amidya yettwaffer", "status.mention": "Bder-d @{name}", "status.more": "Ugar", @@ -534,6 +584,7 @@ "status.read_more": "Issin ugar", "status.reblog": "Bḍu", "status.reblogged_by": "Yebḍa-tt {name}", + "status.reblogs": "{count, plural, one {n usnerni} other {n yisnernuyen}}", "status.reblogs.empty": "Ula yiwen ur yebḍi tajewwiqt-agi ar tura. Ticki yebḍa-tt yiwen, ad d-iban da.", "status.redraft": "Kkes tɛiwdeḍ tira", "status.remove_bookmark": "Kkes tacreḍt", @@ -548,6 +599,7 @@ "status.show_less_all": "Semẓi akk tisuffɣin", "status.show_more": "Ssken-d ugar", "status.show_more_all": "Ẓerr ugar lebda", + "status.show_original": "Sken aɣbalu", "status.title.with_attachments": "{user} posted {attachmentCount, plural, one {an attachment} other {# attachments}}", "status.translate": "Suqel", "status.translated_from_with": "Yettwasuqel seg {lang} s {provider}", @@ -582,6 +634,7 @@ "upload_form.video_description": "Glem-d i yemdanen i yesɛan ugur deg tmesliwt neɣ deg yiẓri", "upload_modal.analyzing_picture": "Tasleḍt n tugna tetteddu…", "upload_modal.apply": "Snes", + "upload_modal.applying": "Asnas…", "upload_modal.choose_image": "Fren tugna", "upload_modal.description_placeholder": "Aberraɣ arurad ineggez nnig n uqjun amuṭṭis", "upload_modal.detect_text": "Sefru-d aḍris seg tugna", @@ -589,6 +642,7 @@ "upload_modal.preparing_ocr": "Aheyyi n OCR…", "upload_modal.preview_label": "Taskant ({ratio})", "upload_progress.label": "Asali iteddu...", + "upload_progress.processing": "Asesfer…", "username.taken": "Yettwaṭṭef yisem-a n useqdac. Ɛreḍ wayeḍ", "video.close": "Mdel tabidyutt", "video.download": "Sidered afaylu", diff --git a/app/javascript/mastodon/locales/lv.json b/app/javascript/mastodon/locales/lv.json index 041072c6ad..701569fa05 100644 --- a/app/javascript/mastodon/locales/lv.json +++ b/app/javascript/mastodon/locales/lv.json @@ -35,6 +35,7 @@ "account.follow_back": "Sekot atpakaļ", "account.followers": "Sekotāji", "account.followers.empty": "Šim lietotājam vēl nav sekotāju.", + "account.followers_counter": "{count, plural, zero {{count} sekotāju} one {{count} sekotājs} other {{count} sekotāji}}", "account.following": "Seko", "account.follows.empty": "Šis lietotājs pagaidām nevienam neseko.", "account.go_to_profile": "Doties uz profilu", @@ -312,9 +313,9 @@ "home.column_settings.show_reblogs": "Rādīt pastiprinātos ierakstus", "home.column_settings.show_replies": "Rādīt atbildes", "home.hide_announcements": "Slēpt paziņojumus", - "home.pending_critical_update.body": "Lūdzu, pēc iespējas ātrāk atjaunini savu Mastodon serveri!", + "home.pending_critical_update.body": "Lūgums pēc iespējas drīzāk atjaunināt savu Mastodon serveri.", "home.pending_critical_update.link": "Skatīt jauninājumus", - "home.pending_critical_update.title": "Pieejams kritisks drošības jauninājums!", + "home.pending_critical_update.title": "Ir pieejams būtisks drošības atjauninājums.", "home.show_announcements": "Rādīt paziņojumus", "interaction_modal.description.favourite": "Ar Mastodon kontu tu vari pievienot šo ziņu izlasei, lai informētu autoru, ka to novērtē, un saglabātu to vēlākai lasīšanai.", "interaction_modal.description.follow": "Ar Mastodon kontu Tu vari sekot {name}, lai saņemtu lietotāja ierakstus savā mājas plūsmā.", diff --git a/app/javascript/mastodon/locales/ry.json b/app/javascript/mastodon/locales/ry.json index 67aad91005..4f2e2410ef 100644 --- a/app/javascript/mastodon/locales/ry.json +++ b/app/javascript/mastodon/locales/ry.json @@ -3,6 +3,8 @@ "about.contact": "Контакт:", "about.disclaimer": "Mastodon є задарьнов проґрамов из удпертым кодом тай торговов значков Mastodon gGmbH.", "about.domain_blocks.no_reason_available": "Причины не ясні", + "about.domain_blocks.preamble": "Майбульш Mastodon поволят вам позирати контент тай комуніковати из хосновачами из другых федерованых серверув. Туй лиш уняткы учинені про сись конкретный сервер.", + "about.domain_blocks.silenced.explanation": "Вы майбульш не будете видіти профілі тай контент из сього сервера, кидь не будете го самі глядати авадь пудпишете ся на нього.", "about.domain_blocks.silenced.title": "Обмежено", "about.domain_blocks.suspended.explanation": "Ниякі податкы из сього сервера не будут уброблені, усокочені ци поміняні, што чинит невозможнов хоть-яку інтеракцію ци зязок из хосновачами из сього сервера.", "about.domain_blocks.suspended.title": "Заблоковано", @@ -20,6 +22,7 @@ "account.browse_more_on_origin_server": "Позирайте бульше на ориґіналнум профілю", "account.cancel_follow_request": "Удмінити пудписку", "account.copy": "Зкопіровати удкликованя на профіл", + "account.direct": "Пошептати @{name}", "account.disable_notifications": "Бульше не сповіщати ми коли {name} пише", "account.domain_blocked": "Домен заблокованый", "account.edit_profile": "Управити профіл", @@ -39,8 +42,10 @@ "account.joined_short": "Датум прикапчованя", "account.languages": "Поміняти убрані языкы", "account.link_verified_on": "Властность сього удкликованя было звірено {date}", + "account.locked_info": "Сись профіл є замкнутый. Ґазда акаунта буде ручно провіряти тко го може зафоловити.", "account.media": "Медіа", - "account.moved_to": "Хосновач {name} указав, ож новый профіл йим є:", + "account.mention": "Спомянути @{name}", + "account.moved_to": "Хосновач {name} указав, ож новый профіл му є:", "account.mute": "Стишити {name}", "account.mute_notifications_short": "Стишити голошіня", "account.mute_short": "Стишити", @@ -60,9 +65,12 @@ "account.unblock_short": "Розблоковати", "account.unendorse": "Не указовати на профілови", "account.unfollow": "Удписати ся", + "account.unmute": "Указовати {name}", "account.unmute_notifications_short": "Указовати голошіня", "account.unmute_short": "Указовати", "account_note.placeholder": "Клопкніт обы додати примітку", + "admin.dashboard.retention.average": "Середньоє", + "admin.dashboard.retention.cohort": "Місяць прикапчованя", "admin.dashboard.retention.cohort_size": "Нові хосновачі", "admin.impact_report.instance_accounts": "Профілі из акаунтув, котрі ся удалят", "admin.impact_report.instance_followers": "Пудписникы, котрых стратят наші хосновачі", @@ -70,11 +78,77 @@ "admin.impact_report.title": "Вплыв цілком", "alert.rate_limited.message": "Попробуйте зась по {retry_time, time, medium}.", "alert.rate_limited.title": "Частота обмежена", + "alert.unexpected.message": "Стала ся нечекана хыба.", + "alert.unexpected.title": "Ийой!", + "announcement.announcement": "Голошіня", + "audio.hide": "Зпрятати звук", + "block_modal.remote_users_caveat": "Попросиме ґазду сервера {domain} честовати вашоє рішеня. Айбо не ґарантуєме повный соглас, бо даякі серверы можут брати блокованя по-инчакому. Публичні дописы годно быти видко незалоґованым хосновачам.", + "block_modal.show_less": "Указати менше", + "block_modal.show_more": "Указати бульше", + "block_modal.they_cant_mention": "Они не можут вас споминати авадь слідовати.", + "block_modal.they_cant_see_posts": "Они не можут видіти ваші публикації, тай наспак — вы йихні.", + "block_modal.they_will_know": "Они видят, ож сут заблоковані.", + "block_modal.title": "Заблоковати хосновача?", + "block_modal.you_wont_see_mentions": "Не будете видіти публикації тай споминкы сього хосновача.", + "boost_modal.combo": "Можете клынцнути {combo} другый раз обы сесе пропустити", + "bundle_column_error.copy_stacktrace": "Укопіровати звіт за хыбу", + "bundle_column_error.error.body": "Не годни сьме указати зажадану сторунку. Годно быти спозад хыбы у нашум сістемі, авадь проблемы зумісности бравзера.", + "bundle_column_error.error.title": "Ийой!", + "bundle_column_error.network.body": "Стала ся хыба як сьме пробовали напаровати сторунку. Годно ся йсе было стати спозад слабого споєня вашого інтернета, авадь сервера.", + "bundle_column_error.network.title": "Хыба споєня", + "bundle_column_error.retry": "Попробуйте зась", "bundle_column_error.return": "Вернути ся на головну", "bundle_column_error.routing.body": "Не можеме найти сяку сторунку. Бизувні сьте, ож URL у адресному шорикови є добрый?", "bundle_column_error.routing.title": "404", "bundle_modal_error.close": "Заперти", "bundle_modal_error.message": "Штось ся показило, закидь сьме ладовали сись компонент.", "bundle_modal_error.retry": "Попробовати зась", - "closed_registrations.other_server_instructions": "Mastodon є децентралізованов платформов, можете си учинити профіл и на другому серверови тай комуніковати из сим." + "closed_registrations.other_server_instructions": "Mastodon є децентралізованов платформов, можете си учинити профіл и на другому серверови тай комуніковати из сим.", + "closed_registrations_modal.description": "Раз не мож учинити профіл на {domain}, айбо не мусите мати профіл ипен на серверови {domain} обы хосновати Mastodon.", + "closed_registrations_modal.find_another_server": "Найти другый сервер", + "column.about": "За сайт", + "column.blocks": "Заблоковані хосновачі", + "column.bookmarks": "Усокоченоє", + "column.direct": "Шептаня", + "column.directory": "Никати профілі", + "column.domain_blocks": "Заблоковані домены", + "column.favourites": "Убраноє", + "column.follow_requests": "Запросы на пудписку", + "column.lists": "Исписы", + "column.mutes": "Стишені хосновачі", + "column.notifications": "Убвіщеня", + "column.pins": "Закріплені публикації", + "column_back_button.label": "Назад", + "column_header.hide_settings": "Спрятати штімованя", + "column_header.moveLeft_settings": "Посунути колонку до ліва", + "column_header.moveRight_settings": "Посунути колонку до права", + "column_header.pin": "Закріпити", + "column_header.show_settings": "Указати штімованя", + "column_header.unpin": "Удкріпити", + "column_subheading.settings": "Штімованя", + "compose.language.change": "Поміняти язык", + "compose.language.search": "Глядати языкы...", + "compose.published.body": "Пост опубликованый.", + "compose.saved.body": "Пост усокоченый.", + "compose_form.direct_message_warning_learn_more": "Читайте бульше", + "compose_form.encryption_warning": "Публикації на Mastodon не шіфрувут ся. Не шырьте чутливу інформацію через Mastodon.", + "compose_form.hashtag_warning": "Сись пост не буде ся появляти у исписови по гештеґови, бо вун не є публичный. Лишек публичні посты буде видко за гештеґом.", + "compose_form.lock_disclaimer": "Ваш профіл є {locked}. Хоть-тко може ся на вас пудписати, обы видїти ваші ексклузівні посты.", + "compose_form.lock_disclaimer.lock": "замкнено", + "compose_form.placeholder": "Што нового?", + "compose_form.poll.duration": "Трывалость убзвідованя", + "compose_form.poll.multiple": "Дакулько варіантув", + "compose_form.poll.option_placeholder": "Варіант {number}", + "compose_form.poll.single": "Уберіт єден", + "compose_form.poll.switch_to_multiple": "Змінити убзвідованя обы поволити дакулько варіантув", + "compose_form.poll.switch_to_single": "Змінити убзвідованя обы поволити лишек єден варіант", + "compose_form.poll.type": "Стіл", + "compose_form.publish": "Публикація", + "compose_form.publish_form": "Нова публикація", + "compose_form.reply": "Удповідь", + "copypaste.copy_to_clipboard": "Копіровати у памнять", + "directory.recently_active": "Недавно актівні", + "disabled_account_banner.account_settings": "Штімованя акаунта", + "disabled_account_banner.text": "Ваш акаунт {disabledAccount} раз є неактівный.", + "dismissable_banner.community_timeline": "Туй сут недавні публикації уд профілув на серверови {domain}." } diff --git a/app/javascript/mastodon/locales/si.json b/app/javascript/mastodon/locales/si.json index fbfdfaa659..3a67beed52 100644 --- a/app/javascript/mastodon/locales/si.json +++ b/app/javascript/mastodon/locales/si.json @@ -33,6 +33,7 @@ "account.mute": "@{name} නිහඬ කරන්න", "account.mute_short": "නිහඬ", "account.muted": "නිහඬ කළා", + "account.open_original_page": "මුල් පිටුව අරින්න", "account.posts": "ලිපි", "account.posts_with_replies": "ලිපි සහ පිළිතුරු", "account.report": "@{name} වාර්තා කරන්න", @@ -51,6 +52,10 @@ "alert.unexpected.title": "අපොයි!", "announcement.announcement": "නිවේදනය", "audio.hide": "හඬපටය සඟවන්න", + "block_modal.show_less": "අඩුවෙන් පෙන්වන්න", + "block_modal.show_more": "තව පෙන්වන්න", + "block_modal.they_will_know": "අවහිර කළ බව දකිනු ඇත.", + "block_modal.title": "අවහිර කරන්නද?", "boost_modal.combo": "ඊළඟ වතාවේ මෙය මඟ හැරීමට {combo} එබීමට හැකිය", "bundle_column_error.copy_stacktrace": "දෝෂ වාර්තාවේ පිටපතක්", "bundle_column_error.error.title": "අපොයි!", @@ -100,10 +105,13 @@ "compose_form.lock_disclaimer.lock": "අගුළු දමා ඇත", "compose_form.placeholder": "ඔබගේ සිතුවිලි මොනවාද?", "compose_form.poll.duration": "මත විමසීමේ කාලය", + "compose_form.poll.option_placeholder": "විකල්පය {number}", "compose_form.poll.switch_to_multiple": "තේරීම් කිහිපයකට මත විමසුම වෙනස් කරන්න", "compose_form.poll.switch_to_single": "තනි තේරීමකට මත විමසුම වෙනස් කරන්න", + "compose_form.poll.type": "ශෛලිය", "compose_form.publish": "ප්‍රකාශනය", "compose_form.publish_form": "නව ලිපිය", + "compose_form.reply": "පිළිතුරු", "compose_form.spoiler.marked": "අන්තර්ගත අවවාදය ඉවත් කරන්න", "compose_form.spoiler.unmarked": "අන්තර්ගත අවවාදයක් එක් කරන්න", "confirmation_modal.cancel": "අවලංගු", @@ -123,6 +131,7 @@ "conversation.mark_as_read": "කියවූ බව යොදන්න", "conversation.open": "සංවාදය බලන්න", "conversation.with": "{names} සමඟ", + "copy_icon_button.copied": "පසුරුපුවරුවට පිටපත් විය", "copypaste.copied": "පිටපත් විය", "copypaste.copy_to_clipboard": "පසුරුපුවරුවට පිටපතක්", "directory.federated": "දන්නා ෆෙඩිවර්ස් වෙතින්", @@ -130,6 +139,9 @@ "directory.new_arrivals": "නව පැමිණීම්", "directory.recently_active": "මෑත දී සක්‍රියයි", "disabled_account_banner.account_settings": "ගිණුමේ සැකසුම්", + "dismissable_banner.dismiss": "ඉවතලන්න", + "domain_pill.server": "සේවාදායකය", + "domain_pill.username": "පරිශ්‍රීලක නාමය", "embed.instructions": "පහත කේතය පිටපත් කිරීමෙන් මෙම ලිපිය ඔබගේ අඩවියට කාවද්දන්න.", "embed.preview": "මෙන්න එය පෙනෙන අන්දම:", "emoji_button.activity": "ක්‍රියාකාරකම", @@ -178,9 +190,13 @@ "filter_modal.select_filter.search": "සොයන්න හෝ සාදන්න", "filter_modal.select_filter.title": "මෙම ලිපිය පෙරන්න", "filter_modal.title.status": "ලිපියක් පෙරන්න", + "filtered_notifications_banner.title": "පෙරූ දැනුම්දීම්", + "firehose.all": "සියල්ල", "firehose.local": "මෙම සේවාදායකය", "firehose.remote": "වෙනත් සේවාදායක", "follow_request.reject": "ප්‍රතික්‍ෂේප", + "follow_suggestions.dismiss": "නැවත පෙන්වන්න එපා", + "follow_suggestions.view_all": "සියල්ල බලන්න", "footer.about": "පිළිබඳව", "footer.directory": "පැතිකඩ නාමාවලිය", "footer.get_app": "යෙදුම ගන්න", @@ -202,6 +218,7 @@ "home.pending_critical_update.link": "යාවත්කාල බලන්න", "home.show_announcements": "නිවේදන පෙන්වන්න", "interaction_modal.login.action": "මුලට ගෙනයන්න", + "interaction_modal.on_another_server": "වෙනත් සේවාදායකයක", "interaction_modal.on_this_server": "මෙම සේවාදායකයෙහි", "interaction_modal.title.favourite": "{name}ගේ ලිපිය ප්‍රිය කරන්න", "interaction_modal.title.follow": "{name} අනුගමනය", diff --git a/app/javascript/mastodon/locales/tok.json b/app/javascript/mastodon/locales/tok.json index 80d412a20b..fcdef5f32c 100644 --- a/app/javascript/mastodon/locales/tok.json +++ b/app/javascript/mastodon/locales/tok.json @@ -170,6 +170,8 @@ "domain_block_modal.block": "o weka e ma", "domain_block_modal.you_will_lose_followers": "ma ni la jan alasa ale sina li weka", "domain_block_modal.you_wont_see_posts": "sina ken ala lukin e toki tan jan pi ma ni", + "domain_pill.server": "ma", + "domain_pill.username": "nimi jan", "embed.preview": "ni li jo e sitelen ni:", "emoji_button.activity": "musi", "emoji_button.flags": "len ma", @@ -274,6 +276,7 @@ "load_pending": "{count, plural, other {ijo sin #}}", "loading_indicator.label": "ni li kama…", "media_gallery.toggle_visible": "{number, plural, other {o len e sitelen}}", + "mute_modal.title": "sina wile ala wile kute e jan ni?", "navigation_bar.about": "sona", "navigation_bar.blocks": "jan weka", "navigation_bar.compose": "o pali e toki sin", @@ -290,24 +293,33 @@ "notification.follow": " {name} li kute e sina", "notification.follow_request": "{name} li wile kute e sina", "notification.mention": "jan {name} li toki e sina", + "notification.moderation-warning.learn_more": "o kama sona e ijo ante", "notification.poll": "sina pana lon pana la pana ni li pini", "notification.reblog": "{name} li wawa e toki sina", "notification.status": "{name} li toki", "notification.update": "{name} li ante e toki", + "notification_requests.dismiss": "o weka", "notifications.column_settings.favourite": "ijo pona:", "notifications.column_settings.follow": "jan kute sin", "notifications.column_settings.poll": "pana lon pana ni:", "notifications.column_settings.reblog": "wawa:", + "notifications.column_settings.status": "toki sin:", "notifications.column_settings.update": "ante toki:", "notifications.filter.all": "ale", + "notifications.filter.boosts": "wawa", "notifications.filter.favourites": "ijo pona", + "notifications.filter.mentions": "toki pi toki sina", "notifications.filter.polls": "pana lon pana ni", + "onboarding.action.back": "o tawa monsi", + "onboarding.actions.back": "o tawa monsi", "onboarding.compose.template": "toki a, #Mastodon o!", "onboarding.profile.display_name": "nimi tawa jan ante", + "onboarding.profile.note": "sona sina", "onboarding.share.lead": "o toki lon nasin Masoton pi alasa sina tawa jan", "onboarding.share.message": "ilo #Mastodon la mi jan {username} a! o kute e mi lon ni: {url}", "onboarding.start.title": "sina o kama pona a!", "onboarding.tips.migration": "sina sona ala sona e ni? tenpo kama la sina pilin ike tawa ma {domain} la, sina ken tawa ma ante lon ilo Masoton. jan li kute e sina la jan ni li awen kute e sina. kin la sina ken lawa e ma pi sina taso a!", + "poll.closed": "ona li pini", "poll.total_people": "{count, plural, other {jan #}}", "poll.total_votes": "{count, plural, other {pana #}}", "poll.vote": "o pana", @@ -315,9 +327,15 @@ "poll.votes": "{votes, plural, other {pana #}}", "privacy.direct.long": "jan ale lon toki", "privacy.public.short": "tawa ale", + "regeneration_indicator.label": "ni li kama…", + "relative_time.days": "{number}d", "relative_time.full.just_now": "tenpo ni", + "relative_time.hours": "{number}h", "relative_time.just_now": "tenpo ni", + "relative_time.minutes": "{number}m", + "relative_time.seconds": "{number}s", "relative_time.today": "tenpo suno ni", + "reply_indicator.cancel": "o ala", "report.block": "o weka e jan", "report.block_explanation": "sina kama lukin ala e toki ona. ona li kama ala ken lukin e toki sina li kama ala ken kute e sina. ona li ken sona e kama ni.", "report.categories.other": "ante", @@ -336,6 +354,7 @@ "report.thanks.title": "sina wile ala lukin e ni anu seme?", "report.unfollow": "o pini kute e {name}", "report_notification.categories.legal": "ike tawa nasin lawa", + "report_notification.categories.other": "ante", "search.placeholder": "o alasa", "search.quick_action.go_to_account": "o tawa lipu jan {x}", "search_popout.language_code": "nimi toki kepeken nasin ISO", @@ -343,6 +362,7 @@ "search_results.see_all": "ale", "search_results.statuses": "toki", "search_results.title": "o alasa e {q}", + "server_banner.administered_by": "jan lawa:", "status.block": "o weka e @{name}", "status.cancel_reblog_private": "o pini e pana", "status.delete": "o weka", @@ -356,12 +376,14 @@ "status.media.open": "o open", "status.media.show": "o lukin", "status.media_hidden": "sitelen li len", + "status.more": "kin", "status.mute": "o len e @{name}", "status.mute_conversation": "o kute ala e ijo pi toki ni", "status.pin": "o sewi lon lipu sina", "status.pinned": "toki sewi", "status.reblog": "o wawa", "status.share": "o pana tawa ante", + "status.show_filter_reason": "o lukin", "status.show_less": "o lili e ni", "status.show_less_all": "o lili e ale", "status.show_more": "o suli e ni", @@ -378,7 +400,9 @@ "timeline_hint.resources.follows": "jan lukin", "timeline_hint.resources.statuses": "ijo pi tenpo suli", "trends.trending_now": "jan mute li toki", + "units.short.billion": "{count}B", "units.short.million": "{count}AAA", + "units.short.thousand": "{count}K", "upload_button.label": "o pana e sitelen anu kalama", "upload_error.limit": "ilo li ken ala e suli pi ijo ni.", "upload_form.audio_description": "o toki e ijo kute tawa jan pi kute ala, tawa jan pi kute lili", @@ -386,6 +410,7 @@ "upload_form.edit": "o ante", "upload_form.thumbnail": "o ante e sitelen lili", "upload_form.video_description": "o toki e ijo kute tawa jan pi kute ala, tawa jan pi kute lili, e ijo lukin tawa jan pi lukin ala, tawa jan pi lukin lili", + "upload_modal.analyzing_picture": "ilo li lukin e sitelen...", "upload_modal.choose_image": "o wile e sitelen", "upload_modal.description_placeholder": "mi pu jaki tan soweli", "upload_modal.detect_text": "ilo o alasa e nimi tan sitelen", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index 150b808f89..67ebb031ae 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.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": "{count, plural, one {{counter} підписник} few {{counter} підписники} many {{counter} підписників} other {{counter} підписники}}", @@ -217,18 +217,18 @@ "domain_block_modal.title": "Заблокувати домен?", "domain_block_modal.you_will_lose_followers": "Усіх ваших підписників з цього сервера буде вилучено.", "domain_block_modal.you_wont_see_posts": "Ви не бачитимете дописів і сповіщень від користувачів на цьому сервері.", - "domain_pill.activitypub_lets_connect": "Це дозволяє вам спілкуватися та взаємодіяти з людьми не лише на Mastodon, але й у різних соціальних додатках.", - "domain_pill.activitypub_like_language": "ActivityPub - це як мова, якою Мастодонт розмовляє з іншими соціальними мережами.", + "domain_pill.activitypub_lets_connect": "Це дозволяє вам спілкуватися та взаємодіяти з людьми не лише на Mastodon, але й у різних соціальних застосунках.", + "domain_pill.activitypub_like_language": "ActivityPub - це як мова, якою Mastodon розмовляє з іншими соціальними мережами.", "domain_pill.server": "Сервер", "domain_pill.their_handle": "Їхня адреса:", - "domain_pill.their_server": "Їхній цифровий дім, де живуть усі їхні пости.", + "domain_pill.their_server": "Їхній цифровий дім, де живуть усі їхні дописи.", "domain_pill.their_username": "Їхній унікальний ідентифікатор на їхньому сервері. Ви можете знайти користувачів з однаковими іменами на різних серверах.", "domain_pill.username": "Ім'я користувача", "domain_pill.whats_in_a_handle": "Що є в адресі?", "domain_pill.who_they_are": "Оскільки дескриптори вказують, хто це і де він знаходиться, ви можете взаємодіяти з людьми через соціальну мережу платформ на основі .", "domain_pill.who_you_are": "Оскільки ваш нікнейм вказує, хто ви та де ви, люди можуть взаємодіяти з вами через соціальну мережу платформ на основі .", "domain_pill.your_handle": "Ваша адреса:", - "domain_pill.your_server": "Ваш цифровий дім, де живуть усі ваші публікації. Не подобається цей? Перенесіть сервери в будь-який час і залучайте своїх підписників.", + "domain_pill.your_server": "Ваш цифровий дім, де живуть усі ваші дописи. Не подобається цей? Перенесіть сервери в будь-який час і залучайте своїх підписників.", "domain_pill.your_username": "Ваш унікальний ідентифікатор на цьому сервері. Ви можете знайти користувачів з однаковими іменами на різних серверах.", "embed.instructions": "Вбудуйте цей допис до вашого вебсайту, скопіювавши код нижче.", "embed.preview": "Ось який вигляд це матиме:", @@ -489,9 +489,9 @@ "notification.reblog": "{name} поширює ваш допис", "notification.relationships_severance_event": "Втрачено з'єднання з {name}", "notification.relationships_severance_event.account_suspension": "Адміністратор з {from} призупинив {target}, що означає, що ви більше не можете отримувати оновлення від них або взаємодіяти з ними.", - "notification.relationships_severance_event.domain_block": "Адміністратор з {from} заблокував {target}, включаючи {followersCount} ваших підписників і {{followingCount, plural, one {# account} other {# accounts}}, на які ви підписані.", - "notification.relationships_severance_event.learn_more": "Дізнатися більше", - "notification.relationships_severance_event.user_domain_block": "Ви заблокували {target}, видаливши {followersCount} ваших підписників і {followingCount, plural, one {# account} other {# accounts}}, за якими ви стежите.", + "notification.relationships_severance_event.domain_block": "Адміністратор з {from} заблокував {target}, включаючи {followersCount} ваших підписників і {followingCount , plural, one {# обліковий запис} few {# облікові записи} many {# облікових записів} other {# обліковий запис}}, на які ви підписані.", + "notification.relationships_severance_event.learn_more": "Докладніше", + "notification.relationships_severance_event.user_domain_block": "Ви заблокували {target}, видаливши {followersCount} ваших підписників і {followingCount, plural, one {# обліковий запис} few {# облікові записи} many {# облікових записів} other {# обліковий запис}}, за якими ви стежите.", "notification.status": "{name} щойно дописує", "notification.update": "{name} змінює допис", "notification_requests.accept": "Прийняти", diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss index 07e9d9868b..a41272364a 100644 --- a/app/javascript/styles/mastodon-light/diff.scss +++ b/app/javascript/styles/mastodon-light/diff.scss @@ -48,6 +48,10 @@ html { } } +.icon-button:disabled { + color: darken($action-button-color, 25%); +} + .account__header__bar .avatar .account__avatar { border-color: $white; } diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index f2e0ad6ff7..c1b42cd398 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -1381,6 +1381,8 @@ body > [data-popper-placement] { min-height: 54px; border-bottom: 1px solid var(--background-border-color); cursor: auto; + opacity: 1; + animation: fade 150ms linear; @keyframes fade { 0% { @@ -1392,9 +1394,6 @@ body > [data-popper-placement] { } } - opacity: 1; - animation: fade 150ms linear; - .media-gallery, .video-player, .audio-player, @@ -5008,8 +5007,10 @@ a.status-card { &__menu { @include search-popout; - padding: 0; - background: $ui-secondary-color; + & { + padding: 0; + background: $ui-secondary-color; + } } &__menu-list { @@ -10622,8 +10623,7 @@ noscript { .filtered-notifications-banner { display: flex; align-items: center; - border: 1px solid var(--background-border-color); - border-top: 0; + border-bottom: 1px solid var(--background-border-color); padding: 24px 32px; gap: 16px; color: $darker-text-color; @@ -10884,7 +10884,7 @@ noscript { gap: 4px; dt { - flex: 0 0 auto; + flex: 0 1 auto; color: $dark-text-color; min-width: 0; overflow: hidden; diff --git a/app/lib/link_details_extractor.rb b/app/lib/link_details_extractor.rb index dbfdd33fcc..d81f4a3062 100644 --- a/app/lib/link_details_extractor.rb +++ b/app/lib/link_details_extractor.rb @@ -62,7 +62,8 @@ class LinkDetailsExtractor end def author_name - author['name'] + name = author['name'] + name.is_a?(Array) ? name.join(', ') : name end def author_url @@ -156,11 +157,11 @@ class LinkDetailsExtractor end def title - html_entities.decode(structured_data&.headline || opengraph_tag('og:title') || document.xpath('//title').map(&:content).first).strip + html_entities_decode(structured_data&.headline || opengraph_tag('og:title') || document.xpath('//title').map(&:content).first)&.strip end def description - html_entities.decode(structured_data&.description || opengraph_tag('og:description') || meta_tag('description')) + html_entities_decode(structured_data&.description || opengraph_tag('og:description') || meta_tag('description')) end def published_at @@ -180,7 +181,7 @@ class LinkDetailsExtractor end def provider_name - html_entities.decode(structured_data&.publisher_name || opengraph_tag('og:site_name')) + html_entities_decode(structured_data&.publisher_name || opengraph_tag('og:site_name')) end def provider_url @@ -188,7 +189,7 @@ class LinkDetailsExtractor end def author_name - html_entities.decode(structured_data&.author_name || opengraph_tag('og:author') || opengraph_tag('og:author:username')) + html_entities_decode(structured_data&.author_name || opengraph_tag('og:author') || opengraph_tag('og:author:username')) end def author_url @@ -257,7 +258,7 @@ class LinkDetailsExtractor next if json_ld.blank? - structured_data = StructuredData.new(html_entities.decode(json_ld)) + structured_data = StructuredData.new(html_entities_decode(json_ld)) next unless structured_data.valid? @@ -273,10 +274,11 @@ class LinkDetailsExtractor end def detect_encoding_and_parse_document - [detect_encoding, nil, @html_charset, 'UTF-8'].uniq.each do |encoding| + [detect_encoding, nil, header_encoding].uniq.each do |encoding| document = Nokogiri::HTML(@html, nil, encoding) return document if document.to_s.valid_encoding? end + Nokogiri::HTML(@html, nil, 'UTF-8') end def detect_encoding @@ -284,12 +286,28 @@ class LinkDetailsExtractor guess&.fetch(:confidence, 0).to_i > 60 ? guess&.fetch(:encoding, nil) : nil end + def header_encoding + Encoding.find(@html_charset).name if @html_charset + rescue ArgumentError + # Encoding from HTTP header is not recognized by ruby + nil + end + def detector @detector ||= CharlockHolmes::EncodingDetector.new.tap do |detector| detector.strip_tags = true end end + def html_entities_decode(string) + return if string.nil? + + unicode_string = string.to_s.encode('UTF-8') + raise EncodingError, 'cannot convert string to valid UTF-8' unless unicode_string.valid_encoding? + + html_entities.decode(unicode_string) + end + def html_entities @html_entities ||= HTMLEntities.new(:expanded) end diff --git a/app/models/concerns/user/has_settings.rb b/app/models/concerns/user/has_settings.rb index 6a12df1e69..2936bc0ba4 100644 --- a/app/models/concerns/user/has_settings.rb +++ b/app/models/concerns/user/has_settings.rb @@ -175,10 +175,6 @@ module User::HasSettings settings['web.display_media'] end - def setting_display_media_expand - settings['web.display_media_expand'] - end - def setting_expand_spoilers settings['web.expand_content_warnings'] end @@ -215,6 +211,10 @@ module User::HasSettings settings['web.disable_swiping'] end + def setting_disable_hover_cards + settings['web.disable_hover_cards'] + end + def setting_always_send_emails settings['always_send_emails'] end diff --git a/app/models/notification_policy.rb b/app/models/notification_policy.rb index f10b0c2a81..2bb58004e3 100644 --- a/app/models/notification_policy.rb +++ b/app/models/notification_policy.rb @@ -31,6 +31,6 @@ class NotificationPolicy < ApplicationRecord private def pending_notification_requests - @pending_notification_requests ||= notification_requests.where(dismissed: false).limit(MAX_MEANINGFUL_COUNT).pick(Arel.sql('count(*), coalesce(sum(notifications_count), 0)::bigint')) + @pending_notification_requests ||= notification_requests.limit(MAX_MEANINGFUL_COUNT).pick(Arel.sql('count(*), coalesce(sum(notifications_count), 0)::bigint')) end end diff --git a/app/models/notification_request.rb b/app/models/notification_request.rb index 6e9cae6625..2f601ac36b 100644 --- a/app/models/notification_request.rb +++ b/app/models/notification_request.rb @@ -9,12 +9,13 @@ # from_account_id :bigint(8) not null # last_status_id :bigint(8) # notifications_count :bigint(8) default(0), not null -# dismissed :boolean default(FALSE), not null # created_at :datetime not null # updated_at :datetime not null # class NotificationRequest < ApplicationRecord + self.ignored_columns += %w(dismissed) + include Paginable MAX_MEANINGFUL_COUNT = 100 @@ -34,8 +35,6 @@ class NotificationRequest < ApplicationRecord end def reconsider_existence! - return if dismissed? - prepare_notifications_count if notifications_count.positive? diff --git a/app/models/preview_card.rb b/app/models/preview_card.rb index bc359e7b25..b3a3f5f03d 100644 --- a/app/models/preview_card.rb +++ b/app/models/preview_card.rb @@ -46,6 +46,11 @@ class PreviewCard < ApplicationRecord y_comp: 4, }.freeze + # URL size limit to safely store in PosgreSQL's unique indexes + # Technically this is a byte-size limit but we use it as a + # character limit to work with length validation + URL_CHARACTER_LIMIT = 2692 + self.inheritance_column = false enum :type, { link: 0, photo: 1, video: 2, rich: 3 } @@ -63,7 +68,7 @@ class PreviewCard < ApplicationRecord convert_options: { all: '-quality 90 +profile "!icc,*" +set date:modify +set date:create +set date:timestamp' }, validate_media_type: false - validates :url, presence: true, uniqueness: true, url: true + validates :url, presence: true, uniqueness: true, url: true, length: { maximum: URL_CHARACTER_LIMIT } validates_attachment_content_type :image, content_type: IMAGE_MIME_TYPES validates_attachment_size :image, less_than: LIMIT remotable_attachment :image, LIMIT diff --git a/app/models/status.rb b/app/models/status.rb index 42feb80a1e..eb52922412 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -364,7 +364,7 @@ class Status < ApplicationRecord else map = media_attachments.index_by(&:id) ordered_media_attachment_ids.filter_map { |media_attachment_id| map[media_attachment_id] } - end + end.take(media_attachments_max) end def replies_count @@ -610,6 +610,10 @@ class Status < ApplicationRecord private + def media_attachments_max + local? ? MEDIA_ATTACHMENTS_LIMIT : MEDIA_ATTACHMENTS_LIMIT_FROM_REMOTE + end + def update_status_stat!(attrs) return if marked_for_destruction? || destroyed? diff --git a/app/models/status_edit.rb b/app/models/status_edit.rb index 21d83a78e1..6a094131d0 100644 --- a/app/models/status_edit.rb +++ b/app/models/status_edit.rb @@ -54,12 +54,14 @@ class StatusEdit < ApplicationRecord def ordered_media_attachments return @ordered_media_attachments if defined?(@ordered_media_attachments) - @ordered_media_attachments = if ordered_media_attachment_ids.nil? - [] - else - map = status.media_attachments.index_by(&:id) - ordered_media_attachment_ids.map.with_index { |media_attachment_id, index| PreservedMediaAttachment.new(media_attachment: map[media_attachment_id], description: media_descriptions[index]) } - end + @ordered_media_attachments = begin + if ordered_media_attachment_ids.nil? + [] + else + map = status.media_attachments.index_by(&:id) + ordered_media_attachment_ids.map.with_index { |media_attachment_id, index| PreservedMediaAttachment.new(media_attachment: map[media_attachment_id], description: media_descriptions[index]) } + end + end.take(Status::MEDIA_ATTACHMENTS_LIMIT) end def proper diff --git a/app/models/user_settings.rb b/app/models/user_settings.rb index 23ccb7eba2..505514307a 100644 --- a/app/models/user_settings.rb +++ b/app/models/user_settings.rb @@ -58,6 +58,7 @@ class UserSettings setting :use_system_font, default: false setting :bookmark_category_needed, default: false setting :disable_swiping, default: false + setting :disable_hover_cards, default: false setting :delete_modal, default: true setting :enable_dtl_menu, default: false setting :hide_recent_emojis, default: false @@ -67,7 +68,6 @@ class UserSettings setting :reduce_motion, default: false setting :expand_content_warnings, default: false setting :display_media, default: 'default', in: %w(default show_all hide_all) - setting :display_media_expand, default: true setting :auto_play, default: true setting :simple_timeline_menu, default: false setting :boost_menu, default: false diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 36089dc177..62a7d5660b 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -23,12 +23,12 @@ class InitialStateSerializer < ActiveModel::Serializer store[:delete_modal] = object_account_user.setting_delete_modal store[:auto_play_gif] = object_account_user.setting_auto_play_gif store[:display_media] = object_account_user.setting_display_media - store[:display_media_expand] = object_account_user.setting_display_media_expand store[:expand_spoilers] = object_account_user.setting_expand_spoilers store[:enable_emoji_reaction] = object_account_user.setting_enable_emoji_reaction && Setting.enable_emoji_reaction store[:enable_dtl_menu] = object_account_user.setting_enable_dtl_menu store[:reduce_motion] = object_account_user.setting_reduce_motion store[:disable_swiping] = object_account_user.setting_disable_swiping + store[:disable_hover_cards] = object_account_user.setting_disable_hover_cards store[:advanced_layout] = object_account_user.setting_advanced_layout store[:use_blurhash] = object_account_user.setting_use_blurhash store[:use_pending_items] = object_account_user.setting_use_pending_items diff --git a/app/serializers/rest/notification_serializer.rb b/app/serializers/rest/notification_serializer.rb index 13e2d682bd..70aebc34d2 100644 --- a/app/serializers/rest/notification_serializer.rb +++ b/app/serializers/rest/notification_serializer.rb @@ -3,6 +3,8 @@ class REST::NotificationSerializer < ActiveModel::Serializer attributes :id, :type, :created_at, :group_key + attribute :filtered, if: :filtered? + belongs_to :from_account, key: :account, serializer: REST::AccountSerializer belongs_to :target_status, key: :status, if: :status_type?, serializer: REST::StatusSerializer belongs_to :report, if: :report_type?, serializer: REST::ReportSerializer @@ -46,4 +48,6 @@ class REST::NotificationSerializer < ActiveModel::Serializer def moderation_warning_event? object.type == :moderation_warning end + + delegate :filtered?, to: :object end diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb index a8148dde14..73479db012 100644 --- a/app/services/fetch_link_card_service.rb +++ b/app/services/fetch_link_card_service.rb @@ -16,9 +16,6 @@ class FetchLinkCardService < BaseService ) }iox - # URL size limit to safely store in PosgreSQL's unique indexes - BYTESIZE_LIMIT = 2692 - def call(status) @status = status @original_url = parse_urls @@ -33,7 +30,7 @@ class FetchLinkCardService < BaseService end attach_card if @card&.persisted? - rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Encoding::UndefinedConversionError => e + rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, EncodingError, ActiveRecord::RecordInvalid => e Rails.logger.debug { "Error fetching link #{@original_url}: #{e}" } nil end @@ -109,7 +106,7 @@ class FetchLinkCardService < BaseService def bad_url?(uri) # Avoid local instance URLs and invalid URLs - uri.host.blank? || TagManager.instance.local_url?(uri.to_s) || !%w(http https).include?(uri.scheme) || uri.to_s.bytesize > BYTESIZE_LIMIT || + uri.host.blank? || TagManager.instance.local_url?(uri.to_s) || !%w(http https).include?(uri.scheme) || referenced_urls.include?(uri.to_s) || Setting.stop_link_preview_domains&.include?(uri.host) end diff --git a/app/views/settings/preferences/appearance/show.html.haml b/app/views/settings/preferences/appearance/show.html.haml index 4a2b05964e..7d0304d325 100644 --- a/app/views/settings/preferences/appearance/show.html.haml +++ b/app/views/settings/preferences/appearance/show.html.haml @@ -57,6 +57,7 @@ = ff.input :'web.auto_play', wrapper: :with_label, recommended: true, label: I18n.t('simple_form.labels.defaults.setting_auto_play_gif') = ff.input :'web.reduce_motion', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_reduce_motion') = ff.input :'web.disable_swiping', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_disable_swiping') + = ff.input :'web.disable_hover_cards', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_disable_hover_cards') = ff.input :'web.use_system_font', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_system_font_ui') %h4= t 'appearance.custom_emoji_and_emoji_reactions' @@ -101,15 +102,6 @@ = ff.input :'web.trends', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_trends') = ff.input :'web.show_relationships', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_show_relationships') - %h4= t 'appearance.media' - - .fields-group - = ff.input :'web.display_media_expand', - kmyblue: true, - hint: I18n.t('simple_form.hints.defaults.setting_display_media_expand'), - label: I18n.t('simple_form.labels.defaults.setting_display_media_expand'), - wrapper: :with_label - %h4= t 'appearance.confirmation_dialogs' .fields-group diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index 53b02edc40..5b2f317bf2 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -5,6 +5,23 @@ require_relative '../../lib/mastodon/sidekiq_middleware' Sidekiq.configure_server do |config| config.redis = REDIS_SIDEKIQ_PARAMS + # This is used in Kubernetes setups, to signal that the Sidekiq process has started and will begin processing jobs + # This comes from https://github.com/sidekiq/sidekiq/wiki/Kubernetes#sidekiq + ready_filename = ENV.fetch('MASTODON_SIDEKIQ_READY_FILENAME', nil) + if ready_filename + raise 'MASTODON_SIDEKIQ_READY_FILENAME is not a valid filename' if File.basename(ready_filename) != ready_filename + + ready_path = Rails.root.join('tmp', ready_filename) + + config.on(:startup) do + FileUtils.touch(ready_path) + end + + config.on(:shutdown) do + FileUtils.rm_f(ready_path) + end + end + config.server_middleware do |chain| chain.add Mastodon::SidekiqMiddleware end diff --git a/config/initializers/vapid.rb b/config/initializers/vapid.rb index 7dd870c8b7..551ede34fb 100644 --- a/config/initializers/vapid.rb +++ b/config/initializers/vapid.rb @@ -5,7 +5,7 @@ Rails.application.configure do # You should only generate this once per instance. If you later decide to change it, all push subscription will # be invalidated, requiring the users to access the website again to resubscribe. # - # Generate with `rake mastodon:webpush:generate_vapid_key` task (`docker-compose run --rm web rake mastodon:webpush:generate_vapid_key` if you use docker compose) + # Generate with `bundle exec rails mastodon:webpush:generate_vapid_key` task (`docker-compose run --rm web bundle exec rails mastodon:webpush:generate_vapid_key` if you use docker compose) # # For more information visit https://rossta.net/blog/using-the-web-push-api-with-vapid.html diff --git a/config/locales/activerecord.kab.yml b/config/locales/activerecord.kab.yml index b3ca90069b..8cdc6501cb 100644 --- a/config/locales/activerecord.kab.yml +++ b/config/locales/activerecord.kab.yml @@ -21,6 +21,18 @@ kab: username: invalid: ilaq ad ilin isekkilen, uṭṭunen d yijerriden n wadda kan reserved: yettwaṭṭef + admin/webhook: + attributes: + url: + invalid: mačči d URL ameɣtu + doorkeeper/application: + attributes: + website: + invalid: mačči d URL ameɣtu + import: + attributes: + data: + malformed: yir amsal status: attributes: reblog: @@ -28,4 +40,20 @@ kab: user: attributes: email: + blocked: isseqdac asaǧǧaw n yimayl ur yettusirgen ara unreachable: ur d-ttban ara d akken yella + role_id: + elevated: ur yezmir ara ad iεeddi tamlilt-ik tamirant + user_role: + attributes: + permissions_as_keys: + dangerous: deg-s tisirag tiriɣelsanin i temlilt tazadurt + elevated: ur yezmir ara ad yesεu tirirag ur nelli ara deg temlilit-ik tamirant + own_role: ur yezmir ara ad yettwabeddel s temlilt-ik tamirant + position: + elevated: ur yezmir ara ad iεeddi tamlilt-ik tamirant + own_role: ur yezmir ara ad yettwabeddel s temlilt-ik tamirant + webhook: + attributes: + events: + invalid_permissions: ur yezmir ara ad yesεu tidyanin iwumi ur tesεiḍ ara tisirag diff --git a/config/locales/ar.yml b/config/locales/ar.yml index 2ca7538c32..4df24c984c 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -1762,6 +1762,10 @@ ar: webauthn_authentication: مفاتيح الأمان severed_relationships: download: تنزيل (%{count}) + lost_followers: المتابعون المفقودون + lost_follows: المتابعات المفقودة + preamble: بحجبكم اسم نطاق قد تخسرون متابَعاتٍ، و كذلك إذا قرّر مديرو الخادوم حظر خادوم ما. و في هذه الحالات يكون بوسعكم تنزيل قائمة بالصلات المبتورة لمعاينتها، مع القدرة على استيرادها إلى خادوم آخر. + purged: حذف مدير خادومكم المعلومات عن هذا الخادوم. statuses: attached: audio: @@ -1978,6 +1982,7 @@ ar: edit_profile_title: قم بتخصيص ملفك التعريفي explanation: ها هي بعض النصائح قبل بداية الاستخدام feature_action: اعرف المزيد + feature_audience: يتيح لكم مًستُدون إدارة جمهوركم بلا وسطاء. فبتنصيب و تشغيل مَستُودون على بنيتكم التحتية تمكنكم متابعة مستخدمي مَستُدون من أيّ خادوم،كما يمكنهم متابعتكم، بلا تحكُّم من أي طرف ثالث. feature_audience_title: اِبنوا جُمهورَكم بِثِقَة feature_control: أنتم الأدرى بالمحتوى الذي تريدون أن تطالعوه في فيض المنشورات الرئيس. لا خوارزميات تتحكم فيما يظهر لكم ولا إعلانات تضيع وقتكم. بحساب واحد تمكنكم متابعة من تشاؤون على أيّ خادوم ماستدون، وتلقّى منشوراتهم بترتيبها الزمني، لتصنعوا ركنكم الأليف في الإنترنت. feature_control_title: تحكَّموا في فيض المنشورات الخاص بكم diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 20e7e4d46b..7e0aaaeefb 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -118,7 +118,7 @@ cs: promote: Povýšit protocol: Protokol public: Veřejný - push_subscription_expires: Odebírání PuSH expiruje + push_subscription_expires: Odebírání PuSH vyprší redownload: Obnovit profil redownloaded_msg: Profil účtu %{username} byl úspěšně obnoven ze zdroje reject: Zamítnout diff --git a/config/locales/devise.kab.yml b/config/locales/devise.kab.yml index 438c1df2b9..3fbc58c1f5 100644 --- a/config/locales/devise.kab.yml +++ b/config/locales/devise.kab.yml @@ -12,6 +12,7 @@ kab: last_attempt: Γur-k yiwen n uɛraḍ-nniḍen kan send ad yettucekkel umiḍan-ik. locked: Amiḍan-ik yettwargel. not_found_in_database: Tella tuccḍa deg %{authentication_keys} neγ deg wawal uffir. + omniauth_user_creation_failure: Tuccḍa lawan n tmerna n umiḍan i timagit-a. pending: Amiḍan-inek mazal-it deg ɛiwed n tmuγli. timeout: Tiɣimit n tuqqna tezri. Ma ulac aɣilif ɛiwed tuqqna akken ad tkemmleḍ. unauthenticated: Ilaq ad teqqneḍ neɣ ad tjerrḍeḍ akken ad tkemmelḍ. @@ -47,21 +48,41 @@ kab: subject: 'Mastodon: Iwellihen n uwennez n wawal uffir' title: Aɛiwed n wawal uffir two_factor_disabled: + explanation: Tuqqna tella tura s useqdec n tansa n yimayl tasuft d wawal n uεeddi. subject: 'Mastodon: Asesteb s snat n tarrayin yensa' + subtitle: Asesteb s snat tarrayin i umiḍan-ik yensan. title: Asesteb s snat n tarrayin insa two_factor_enabled: + explanation: Ajuṭu yettusirwen s usnas TOTP yeqqnen ilaq i wakken ad teqqneḍ. subject: 'Mastodon: Asesteb s snat n tarrayin yermed' + subtitle: Asesteb s snat tarrayin yettwarmed i umiḍan-ik. title: Asesteb s snat n tarrayin irmed two_factor_recovery_codes_changed: explanation: Tangalt n tuɣalin tettwaḥbes sakin nesnulfa-d yiwet d tamaynut. subject: 'Mastodon: Tingalin n tuɣalin n snat n tarayin ttwarnanat i tikkelt-nniḍen' + subtitle: Tangalt n tuɣalin tettwaḥbes sakin nesnulfa-d yiwet d tamaynut. title: Tangalt n tuɣalin 2FA tettwabeddel unlock_instructions: subject: 'Mastodon: iwelihhen n userreḥ' webauthn_credential: added: + explanation: Tasarut-a n tɣellist tettwarna ɣer umiḍan-ik·im subject: 'Maṣṭudun : Tasarutt tamaynutt n tɣellist' title: Tasarut tamaynutt n tɣellist tamaynut tettwarna + deleted: + explanation: Tasarut-a n tɣellist tettwakkes seg umiḍan-ik·im + subject: 'Mastodon: Tasarut n tɣellsit tettwakkes' + title: Yiwet seg tsura-k·m n tɣellist tettwakkes + webauthn_disabled: + explanation: Yensa usesteb s tsura n tɣellist i umiḍan-ik. + extra: Tzemreḍ ad tkecmeḍ tura s useqdec asuf n ujuṭu yettwasran s usnas TOPTP yeqqnen. + subject: 'Mastodon: Asesteb s tsura n tɣellist yensa' + title: Tisura n tɣellist nsant + webauthn_enabled: + explanation: Asesteb n tsarut n tɣellist tettwarmed i umiḍan-ik. + extra: Tasarut-ik n tɣellist tezmer tura ad tettuseqdec i unekcum. + subject: 'Mastodon: Asesteb n tsarut n tɣellist yermed' + title: Tisura n tɣellist remdent omniauth_callbacks: failure: Ur nezmir ara ad ak·akem-nsesṭeb seg %{kind} acku "%{reason}". success: Asesṭeb idda akken iwata seg umiḍan %{kind}. diff --git a/config/locales/devise.nl.yml b/config/locales/devise.nl.yml index ab6ae84db4..662401a57a 100644 --- a/config/locales/devise.nl.yml +++ b/config/locales/devise.nl.yml @@ -75,7 +75,7 @@ nl: title: Een van jouw beveiligingssleutels is verwijderd webauthn_disabled: explanation: Verificatie met beveiligingssleutels is uitgeschakeld voor je account. - extra: Het is nu alleen mogelijk om in te loggen met een door de authenticatie-app gegeneerde toegangscode. + extra: Het is nu alleen mogelijk om in te loggen met een door de authenticatie-app gegeneerde toegangscode als extra controle. subject: 'Mastodon: Verificatie met beveiligingssleutels is uitgeschakeld' title: Beveiligingssleutels uitgeschakeld webauthn_enabled: diff --git a/config/locales/doorkeeper.kab.yml b/config/locales/doorkeeper.kab.yml index 1b1a7df957..33aecd8c6f 100644 --- a/config/locales/doorkeeper.kab.yml +++ b/config/locales/doorkeeper.kab.yml @@ -5,6 +5,7 @@ kab: doorkeeper/application: name: Isem n usnas redirect_uri: URI n uwelleh + scopes: Tinerfadin website: Asmel web n usnas errors: models: @@ -39,6 +40,7 @@ kab: empty: Ulac ɣur-k·m isnasen. name: Isem new: Asnas amaynut + scopes: Tinerfadin show: Ẓer title: Isnasen-ik·im new: @@ -47,6 +49,8 @@ kab: actions: Tigawin application_id: ID n usnas callback_urls: URL n tririt n wawal + scopes: Tinerfadin + secret: Tuffirt n umsaɣ title: 'Asnas: %{name}' authorizations: buttons: @@ -55,6 +59,7 @@ kab: error: title: Tella-d tuccḍa new: + review_permissions: Asenqed n tsirag title: Tlaq tsiregt show: title: Nɣel tangalt n wurag sakkin senteḍ-itt deg usnas. @@ -64,8 +69,12 @@ kab: confirmations: revoke: Tetḥeqqeḍ? index: + authorized_at: Yettwasireg ɣef %{date} description_html: Ha-t-an yisnasen i izemren ad kecmen ɣer umiḍan-ik·im, s useqdec n API. Ma llan yisnasen ur teεqileḍ ara da, neɣ kra n wesnas ur iteddu ara akken ilaq, tzemreḍ ad tekkseḍ anekcum-is. last_used_at: Yettwaseqdec i tikkelt taneggarut ass n %{date} + never_used: Urǧin yettwaseqdac + scopes: Tisirag + superapp: Adigan title: Isnasen-ik·im yettusirgen errors: messages: @@ -82,13 +91,28 @@ kab: destroy: notice: Yettwaḥwi wesnas. grouped_scopes: + access: + read: Anekcum i tɣuri kan + read/write: Anekcum i tɣuri d tira + write: Anekcum i tira kan title: accounts: Imiḍanen admin/accounts: Tadbelt n imiḍan + admin/all: Akk timahilin tinebdalin + admin/reports: Tadbelt n yineqqisen + blocks: Yewḥel + bookmarks: Ticraḍ + conversations: Idiwenniyen crypto: Awgelhen seg yixef ɣer yixef + favourites: Imenyafen filters: Imzizdigen + follow: Aḍfar, asgugem akked usewḥel + follows: Aḍfar lists: Tibdarin + media: Imeddayen n umidya + mutes: Yeggugem notifications: Tilɣa + profile: Amaɣnu-k Mastodon push: Tilɣa yettudemmren reports: Ineqqisen search: Nadi diff --git a/config/locales/doorkeeper.ko.yml b/config/locales/doorkeeper.ko.yml index 3ab0698d51..7ec357bf9f 100644 --- a/config/locales/doorkeeper.ko.yml +++ b/config/locales/doorkeeper.ko.yml @@ -31,7 +31,7 @@ ko: form: error: 이런! 오류를 확인하세요 help: - native_redirect_uri: "%{native_redirect_uri}에서 로컬 테스트를 할 수 있습니다." + native_redirect_uri: "%{native_redirect_uri}를 이용해 로컬 테스트를 할 수 있습니다" redirect_uri: 한 줄에 하나의 URI를 작성하세요 scopes: 스페이스로 범위를 구분하세요. 빈 칸으로 놔두면 기본 범위를 사용합니다. index: diff --git a/config/locales/doorkeeper.lv.yml b/config/locales/doorkeeper.lv.yml index 5aa5daef3f..11c5020305 100644 --- a/config/locales/doorkeeper.lv.yml +++ b/config/locales/doorkeeper.lv.yml @@ -25,7 +25,7 @@ lv: edit: Labot submit: Apstiprināt confirmations: - destroy: Vai esi pārliecināts? + destroy: Vai tiešām? edit: title: Labot lietotni form: @@ -69,7 +69,7 @@ lv: buttons: revoke: Atsaukt confirmations: - revoke: Vai esi pārliecināts? + revoke: Vai tiešām? index: authorized_at: Autorizētas %{date} description_html: Šīs ir lietotnes, kas var piekļūt Tavam kontam ar API. Ja šeit ir lietotnes, kuras neatpazīsti, vai lietotne darbojas ne tā, kā paredzēts, vari atsaukt tās piekļuvi. @@ -135,6 +135,7 @@ lv: media: Multividesu pielikumi mutes: Apklusinātie notifications: Paziņojumi + profile: Tavs Mastodon profils push: Uznirstošie paziņojumi reports: Ziņojumi search: Meklēt @@ -165,6 +166,7 @@ lv: admin:write:reports: veikt moderācijas darbības pārskatos crypto: lieto pilnīgu šifrēšanu follow: mainīt konta attiecības + profile: lasīt tikai Tava konta profila informāciju push: saņemt savus push paziņojumus read: lasīt visus sava konta datus read:accounts: apskatīt kontu informāciju diff --git a/config/locales/doorkeeper.nl.yml b/config/locales/doorkeeper.nl.yml index 4115e0a17e..0a3d8fd081 100644 --- a/config/locales/doorkeeper.nl.yml +++ b/config/locales/doorkeeper.nl.yml @@ -129,7 +129,7 @@ nl: crypto: End-to-end-encryptie favourites: Favorieten filters: Filters - follow: Volgers, genegeerde en geblokkeerde gebruikers + follow: Gevolgde, genegeerde en geblokkeerde gebruikers follows: Volgend lists: Lijsten media: Mediabijlagen diff --git a/config/locales/en.yml b/config/locales/en.yml index 12922cc235..ca569c6726 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1348,7 +1348,6 @@ en: body: Mastodon is translated by volunteers. guide_link: https://crowdin.com/project/mastodon guide_link_text: Everyone can contribute. - media: Media quotes: Quotes remote_server_features: Other server features saved_posts: Saving posts diff --git a/config/locales/gl.yml b/config/locales/gl.yml index ad4744e15b..c9f08dcad7 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -31,18 +31,18 @@ gl: created_msg: Nota de moderación creada correctamente! destroyed_msg: Nota de moderación eliminada de xeito correcto! accounts: - add_email_domain_block: Bloquear o dominio do email + add_email_domain_block: Bloquear o dominio do enderezo approve: Aprobar approved_msg: Aprobada a solicitude de rexistro de %{username} are_you_sure: Está segura? avatar: Imaxe de perfil by_domain: Dominio change_email: - changed_msg: Email mudado de xeito correcto! - current_email: Email actual - label: Mudar email - new_email: Novo email - submit: Mudar email + changed_msg: Correo cambiado de xeito correcto! + current_email: Enderezo actual + label: Cambiar de enderezo + new_email: Novo enderezo + submit: Cambiar de enderezo title: Mudar email de %{username} change_role: changed_msg: Rol mudado correctamente! @@ -64,10 +64,10 @@ gl: display_name: Nome a amosar domain: Dominio edit: Editar - email: Email - email_status: Estado do email + email: Enderezo de correo + email_status: Estado do correo enable: Activar - enable_sign_in_token_auth: Activar autenticación cun token no email + enable_sign_in_token_auth: Activar autenticación cun token no correo enabled: Activado enabled_msg: Desbloqueada a conta de %{username} followers: Seguidoras @@ -132,7 +132,7 @@ gl: resubscribe: Resubscribir role: Rol search: Procurar - search_same_email_domain: Outras usuarias co mesmo dominio de email + search_same_email_domain: Outras usuarias co mesmo dominio de correo search_same_ip: Outras usuarias co mesmo IP security: Seguridade security_measures: @@ -154,9 +154,9 @@ gl: suspension_irreversible: Elimináronse de xeito irreversible os datos desta conta. Podes reactivar a conta para facela usable novamente pero non recuperará os datos eliminados. suspension_reversible_hint_html: Esta conta foi suspendida, e os datos serán totalmente eliminados o %{date}. Ata entón, a conta pode ser restaurada sen danos. Se desexas eliminar agora mesmo todos os datos da conta, podes facelo aquí embaixo. title: Contas - unblock_email: Desbloquear enderezo de email - unblocked_email_msg: Enderezo de email de %{username} desbloqueado - unconfirmed_email: Email non confirmado + unblock_email: Desbloquear enderezo de correo + unblocked_email_msg: Enderezo de correo de %{username} desbloqueado + unconfirmed_email: Enderezo de correo sen confirmar undo_sensitized: Desmarcar como sensible undo_silenced: Desfacer acalar undo_suspension: Desfacer suspensión @@ -173,12 +173,12 @@ gl: approve_appeal: Aprobar apelación approve_user: Aprobar Usuaria assigned_to_self_report: Asignar denuncia - change_email_user: Editar email da usuaria + change_email_user: Editar correo electrónico da usuaria change_role_user: Cambiar Rol da Usuaria confirm_user: Confirmar usuaria create_account_warning: Crear aviso create_announcement: Crear anuncio - create_canonical_email_block: Crear Bloqueo de email + create_canonical_email_block: Crear Bloqueo de correo electrónico create_custom_emoji: Crear emoticonas personalizadas create_domain_allow: Crear Dominio Permitido create_domain_block: Crear bloquedo do Dominio @@ -188,7 +188,7 @@ gl: create_user_role: Crear Rol demote_user: Degradar usuaria destroy_announcement: Eliminar anuncio - destroy_canonical_email_block: Eliminar Bloqueo de email + destroy_canonical_email_block: Eliminar Bloqueo de correo electrónico destroy_custom_emoji: Eliminar emoticona personalizada destroy_domain_allow: Eliminar Dominio permitido destroy_domain_block: Eliminar bloqueo do Dominio @@ -200,7 +200,7 @@ gl: destroy_user_role: Eliminar Rol disable_2fa_user: Desactivar 2FA disable_custom_emoji: Desactivar emoticona personalizada - disable_sign_in_token_auth_user: Desactivar Autenticación por token no email para Usuaria + disable_sign_in_token_auth_user: Desactivar Autenticación con token no correo para Usuaria disable_user: Desactivar usuaria enable_custom_emoji: Activar emoticona personalizada enable_sign_in_token_auth_user: Activar Autenticación con token no email para Usuaria @@ -211,14 +211,14 @@ gl: reject_user: Rexeitar Usuaria remove_avatar_user: Eliminar avatar reopen_report: Reabrir denuncia - resend_user: Reenviar o email de confirmación + resend_user: Reenviar o correo de confirmación reset_password_user: Restabelecer contrasinal resolve_report: Resolver denuncia sensitive_account: Marca o multimedia da túa conta como sensible silence_account: Silenciar conta suspend_account: Suspender conta unassigned_report: Desasignar denuncia - unblock_email_account: Desbloquear enderezo de email + unblock_email_account: Desbloquear enderezo de correo unsensitive_account: Retira a marca de sensible do multimedia da conta unsilence_account: Deixar de silenciar conta unsuspend_account: Retirar suspensión de conta @@ -660,7 +660,7 @@ gl: delete_data_html: Eliminar o perfil e contidos de @%{acct} para os próximos 30 días a non ser que sexa suspendida nese período preview_preamble_html: "@%{acct} vai recibir un aviso co seguinte contido:" record_strike_html: Anotar un aviso contra @%{acct} para axudarche a xestionar futuros problemas con esta conta - send_email_html: Enviar un email de aviso a @%{acct} + send_email_html: Enviar un correo de aviso a @%{acct} warning_placeholder: Razóns adicionais optativas para a acción de moderación. target_origin: Orixe da conta denunciada title: Denuncias @@ -1060,7 +1060,7 @@ gl: redirect_to_app_html: Ímoste redirixir á app %{app_name}. Se iso non acontece, proba %{clicking_this_link} ou volve ti manualmente á app. registration_complete: Completouse a creación da conta en %{domain}! welcome_title: Benvida, %{name}! - wrong_email_hint: Se o enderezo de email non é correcto, podes cambialo nos axustes da conta. + wrong_email_hint: Se o enderezo de correo non é correcto, podes cambialo nos axustes da conta. delete_account: Eliminar conta delete_account_html: Se queres eliminar a túa conta, podes facelo aquí. Deberás confirmar a acción. description: diff --git a/config/locales/ja.yml b/config/locales/ja.yml index ff23ed24bd..8215d8584a 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -306,6 +306,7 @@ ja: filter_by_action: アクションでフィルター filter_by_user: ユーザーでフィルター title: 操作履歴 + unavailable_instance: "(ドメイン名が利用できません)" announcements: destroyed_msg: お知らせが削除されました edit: @@ -1323,7 +1324,6 @@ ja: body: Mastodonは有志によって翻訳されています。 guide_link: https://ja.crowdin.com/project/mastodon guide_link_text: 誰でも参加することができます。 - media: メディア quotes: 引用 remote_server_features: 他のサーバーの機能 saved_posts: 投稿の記録 diff --git a/config/locales/ko.yml b/config/locales/ko.yml index a8e2ade61d..f7feb73ba0 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -1741,7 +1741,7 @@ ko: contrast: 마스토돈 (고대비) default: 마스토돈 (어두움) mastodon-light: 마스토돈 (밝음) - system: 자동 선택 (시스템 테마 이용) + system: 자동 (시스템 테마 사용) time: formats: default: "%Y-%m-%d %H:%M" diff --git a/config/locales/ro.yml b/config/locales/ro.yml index cd54d51051..79bc2a275f 100644 --- a/config/locales/ro.yml +++ b/config/locales/ro.yml @@ -116,6 +116,8 @@ ro: redownloaded_msg: S-a reîmprospătat cu succes profilul %{username} de la origine reject: Respinge rejected_msg: S-a respins cu succes cererea de înregistrare a utilizatorului %{username} + remote_suspension_irreversible: Datele acestui cont au fost șterse în mod ireversibil. + remote_suspension_reversible_hint_html: Contul a fost suspendat pe server-ul respectiv, iar datele vor fi șterse complet pe %{date}. Până atunci, server-ul remote poate restabili acest cont fără consecințe negative. Dacă dorești să elimini toate datele contului numaidecât, poți face acest lucru mai jos. remove_avatar: Elimină avatar remove_header: Elimină antet removed_avatar_msg: S-a îndepărtat cu succes poza de profil a utilizatorului %{username} diff --git a/config/locales/ry.yml b/config/locales/ry.yml index 6fe57b65cd..e384b7f1b7 100644 --- a/config/locales/ry.yml +++ b/config/locales/ry.yml @@ -1 +1,21 @@ +--- ry: + accounts: + follow: Пудписати ся + following: Пудпискы + posts: + few: Публикації + one: Публикація + other: Публикації + posts_tab_heading: Публикації + imports: + titles: + following: Імпортованя пудписок + types: + following: Испис пудписок + notification_mailer: + follow: + body: "%{name} ся пудписує ся на вас!" + subject: "%{name} ся пудписує ся на вас" + relationships: + following: Пудпискы diff --git a/config/locales/simple_form.ca.yml b/config/locales/simple_form.ca.yml index d3dc4b13f1..4bb906abdb 100644 --- a/config/locales/simple_form.ca.yml +++ b/config/locales/simple_form.ca.yml @@ -211,6 +211,7 @@ ca: setting_default_privacy: Privacitat dels tuts setting_default_sensitive: Marcar sempre el contingut gràfic com a sensible setting_delete_modal: Mostra la finestra de confirmació abans d'esborrar un tut + setting_disable_hover_cards: Deshabilita la vista prèvia del perfil en passar-hi per sobre setting_disable_swiping: Desactiva les animacions setting_display_media: Visualització multimèdia setting_display_media_default: Per defecte diff --git a/config/locales/simple_form.da.yml b/config/locales/simple_form.da.yml index 0719e26430..73a32cf2fd 100644 --- a/config/locales/simple_form.da.yml +++ b/config/locales/simple_form.da.yml @@ -211,6 +211,7 @@ da: setting_default_privacy: Fortrolighed for indlæg setting_default_sensitive: Markér altid medier som sensitive setting_delete_modal: Vis bekræftelsesdialog før et indlæg slettes + setting_disable_hover_cards: Deaktivér profilforhåndsvisning ved svæv (hover) setting_disable_swiping: Deaktivér strygebevægelser setting_display_media: Medievisning setting_display_media_default: Standard diff --git a/config/locales/simple_form.de.yml b/config/locales/simple_form.de.yml index 7d39786697..5711d2a12a 100644 --- a/config/locales/simple_form.de.yml +++ b/config/locales/simple_form.de.yml @@ -211,6 +211,7 @@ de: setting_default_privacy: Beitragssichtbarkeit setting_default_sensitive: Medien immer mit einer Inhaltswarnung versehen setting_delete_modal: Bestätigungsdialog beim Löschen eines Beitrags anzeigen + setting_disable_hover_cards: Profilvorschau deaktivieren, wenn die Maus über das Profil bewegt wird setting_disable_swiping: Wischgesten deaktivieren setting_display_media: Darstellung von Medien setting_display_media_default: Standard diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 4a726bd65b..b33801d6fb 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -66,7 +66,6 @@ en: setting_default_sensitive: Sensitive media is hidden by default and can be revealed with a click setting_disallow_unlisted_public_searchability: この設定を有効にすると、非収載投稿と検索範囲「誰でも」は両立できず不特定多数からの検索が不可になります。Fedibirdと同じ挙動になります setting_display_media_default: Hide media marked as sensitive - setting_display_media_expand: Misskey and others can submit more than 4. The additions will be displayed up to 16. kmyblue will not allow uploading from kmyblue. setting_display_media_hide_all: Always hide media setting_display_media_show_all: Always show media setting_dtl_force_searchability: 'With using #%{tag} tag, your post settings will be changed forcibly' @@ -271,11 +270,11 @@ en: setting_default_searchability_of_search: Your search setting setting_default_sensitive: Always mark media as sensitive setting_delete_modal: Show confirmation dialog before deleting a post + setting_disable_hover_cards: Disable profile preview on hover setting_disable_swiping: Disable swiping motions setting_disallow_unlisted_public_searchability: Disallow everyone or local searchability when unlisted visibility setting_display_media: Media display setting_display_media_default: Default - setting_display_media_expand: Show more medias setting_display_media_hide_all: Hide all setting_display_media_show_all: Show all setting_dtl_force_searchability: Post searchability @@ -366,6 +365,7 @@ en: exclude_quote: Exclude quote or references form_admin_settings: activity_api_enabled: Publish aggregate statistics about user activity in the API + app_icon: App icon backups_retention_period: User archive retention period bootstrap_timeline_accounts: Always recommend these accounts to new users check_lts_version_only: Check kmyblue LTS version only when update check @@ -377,6 +377,7 @@ en: enable_local_timeline: Enable local timeline enable_public_unlisted_visibility: Enable public-unlisted visibility / public-unlisted searchability enable_public_visibility: Enable public visibility + favicon: Favicon mascot: Custom mascot (legacy) media_cache_retention_period: Media cache retention period peers_api_enabled: Publish list of discovered servers in the API diff --git a/config/locales/simple_form.eo.yml b/config/locales/simple_form.eo.yml index e83f71a2cb..40535bf96b 100644 --- a/config/locales/simple_form.eo.yml +++ b/config/locales/simple_form.eo.yml @@ -203,6 +203,7 @@ eo: setting_default_privacy: Privateco de afiŝado setting_default_sensitive: Ĉiam marki plurmediojn kiel tiklaj setting_delete_modal: Montri konfirman fenestron antaŭ ol forigi mesaĝon + setting_disable_hover_cards: Malebligi profilan antaŭmontron kiam oni musumas setting_disable_swiping: Malebligi svingajn movojn setting_display_media: Montrado de plurmedioj setting_display_media_default: Implicita diff --git a/config/locales/simple_form.es-AR.yml b/config/locales/simple_form.es-AR.yml index e346a23a02..1d1ac87689 100644 --- a/config/locales/simple_form.es-AR.yml +++ b/config/locales/simple_form.es-AR.yml @@ -211,6 +211,7 @@ es-AR: setting_default_privacy: Privacidad de mensajes setting_default_sensitive: Siempre marcar medios como sensibles setting_delete_modal: Mostrar diálogo de confirmación antes de eliminar un mensaje + setting_disable_hover_cards: Deshabilitar previsualización del perfil al pasar el cursor setting_disable_swiping: Deshabilitar movimientos de deslizamiento setting_display_media: Visualización de medios setting_display_media_default: Predeterminada diff --git a/config/locales/simple_form.es-MX.yml b/config/locales/simple_form.es-MX.yml index b3c8a857e8..19a1c9d0c0 100644 --- a/config/locales/simple_form.es-MX.yml +++ b/config/locales/simple_form.es-MX.yml @@ -211,6 +211,7 @@ es-MX: setting_default_privacy: Privacidad de publicaciones setting_default_sensitive: Marcar siempre imágenes como sensibles setting_delete_modal: Mostrar diálogo de confirmación antes de borrar un toot + setting_disable_hover_cards: Desactivar vista previa del perfil al pasar el cursor setting_disable_swiping: Deshabilitar movimientos de deslizamiento setting_display_media: Visualización multimedia setting_display_media_default: Por defecto diff --git a/config/locales/simple_form.es.yml b/config/locales/simple_form.es.yml index 2fb5cab987..cc71e19266 100644 --- a/config/locales/simple_form.es.yml +++ b/config/locales/simple_form.es.yml @@ -211,6 +211,7 @@ es: setting_default_privacy: Privacidad de publicaciones setting_default_sensitive: Marcar siempre imágenes como sensibles setting_delete_modal: Mostrar diálogo de confirmación antes de borrar una publicación + setting_disable_hover_cards: Desactivar vista previa del perfil al pasar el cursor setting_disable_swiping: Deshabilitar movimientos de deslizamiento setting_display_media: Visualización multimedia setting_display_media_default: Por defecto diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml index b0bc8c735b..214308ba5c 100644 --- a/config/locales/simple_form.fi.yml +++ b/config/locales/simple_form.fi.yml @@ -211,6 +211,7 @@ fi: setting_default_privacy: Julkaisun näkyvyys setting_default_sensitive: Merkitse media aina arkaluonteiseksi setting_delete_modal: Kysy vahvistusta ennen julkaisun poistamista + setting_disable_hover_cards: Poista käytöstä profiilin esikatselu osoitettaessa setting_disable_swiping: Poista pyyhkäisyeleet käytöstä setting_display_media: Median näyttäminen setting_display_media_default: Oletus diff --git a/config/locales/simple_form.fo.yml b/config/locales/simple_form.fo.yml index 7d4da2b51e..8f0b51719f 100644 --- a/config/locales/simple_form.fo.yml +++ b/config/locales/simple_form.fo.yml @@ -211,6 +211,7 @@ fo: setting_default_privacy: Hvussu privatir eru postar? setting_default_sensitive: Merk altíð miðlafílur sum viðkvæmar setting_delete_modal: Vís váttanarmynd, áðrenn postar verða strikaðir + setting_disable_hover_cards: Ger undanvísing, tá músin verður flutt yvir vangan, óvirkna setting_disable_swiping: Ger sveipurørslur óvirknar setting_display_media: Vístir miðlar setting_display_media_default: Sjálvvirði diff --git a/config/locales/simple_form.gl.yml b/config/locales/simple_form.gl.yml index 0411c45bc1..0653d76204 100644 --- a/config/locales/simple_form.gl.yml +++ b/config/locales/simple_form.gl.yml @@ -211,6 +211,7 @@ gl: setting_default_privacy: Privacidade da publicación setting_default_sensitive: Marcar sempre multimedia como sensible setting_delete_modal: Solicitar confirmación antes de eliminar unha publicación + setting_disable_hover_cards: Desactivar vista previa do perfil ao poñerse enriba setting_disable_swiping: Desactivar opcións de desprazamento setting_display_media: Mostrar multimedia setting_display_media_default: Por defecto @@ -255,7 +256,7 @@ gl: require_invite_text: Pedir unha razón para unirse show_domain_blocks: Amosar dominios bloqueados show_domain_blocks_rationale: Explicar porque están bloqueados os dominios - site_contact_email: Email de contacto + site_contact_email: Correo de contacto site_contact_username: Nome do contacto site_extended_description: Descrición ampla site_short_description: Descrición do servidor diff --git a/config/locales/simple_form.he.yml b/config/locales/simple_form.he.yml index 65c6f6110f..1331d2f62b 100644 --- a/config/locales/simple_form.he.yml +++ b/config/locales/simple_form.he.yml @@ -211,6 +211,7 @@ he: setting_default_privacy: פרטיות ההודעות setting_default_sensitive: תמיד לתת סימון "רגיש" למדיה setting_delete_modal: להראות תיבת אישור לפני מחיקת חיצרוץ + setting_disable_hover_cards: כבה הצצה מקדימה לפרופיל בעת מעבר עכבר מעליו setting_disable_swiping: ביטול החלקת-צד setting_display_media: תצוגת מדיה setting_display_media_default: ברירת מחדל diff --git a/config/locales/simple_form.is.yml b/config/locales/simple_form.is.yml index 044e24deb0..cc267db8d5 100644 --- a/config/locales/simple_form.is.yml +++ b/config/locales/simple_form.is.yml @@ -211,6 +211,7 @@ is: setting_default_privacy: Gagnaleynd færslna setting_default_sensitive: Alltaf merkja myndefni sem viðkvæmt setting_delete_modal: Birta staðfestingarglugga áður en færslu er eytt + setting_disable_hover_cards: Gera óvirka forskoðun notandasniðs við yfirsvif setting_disable_swiping: Gera strokuhreyfingar óvirkar setting_display_media: Birting myndefnis setting_display_media_default: Sjálfgefið diff --git a/config/locales/simple_form.it.yml b/config/locales/simple_form.it.yml index f5624344b9..540812faa9 100644 --- a/config/locales/simple_form.it.yml +++ b/config/locales/simple_form.it.yml @@ -211,6 +211,7 @@ it: setting_default_privacy: Privacy dei post setting_default_sensitive: Segna sempre i media come sensibili setting_delete_modal: Mostra dialogo di conferma prima di eliminare un post + setting_disable_hover_cards: Disabilita l'anteprima del profilo al passaggio del mouse setting_disable_swiping: Disabilita i movimenti di scorrimento setting_display_media: Visualizzazione dei media setting_display_media_default: Predefinita diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index 7933a6b383..b23f381d3b 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -66,7 +66,6 @@ ja: setting_default_sensitive: 閲覧注意状態のメディアはデフォルトでは内容が伏せられ、クリックして初めて閲覧できるようになります setting_disallow_unlisted_public_searchability: この設定を有効にすると、非収載投稿と検索範囲「誰でも」は両立できず不特定多数からの検索が不可になります。Fedibirdと同じ挙動になります setting_display_media_default: 閲覧注意としてマークされたメディアは隠す - setting_display_media_expand: Misskeyなどは4個を超えて投稿可能です。その追加分を最大16個まで表示します。kmyblueからアップロードはできません setting_display_media_hide_all: メディアを常に隠す setting_display_media_show_all: メディアを常に表示する setting_dtl_force_searchability: 'ハッシュタグ #%{tag} をつけて投稿するとき、検索許可を強制的に置き換えるかを設定します' @@ -267,11 +266,11 @@ ja: setting_default_searchability_of_search: 自分が検索するときの検索許可設定 setting_default_sensitive: メディアを常に閲覧注意としてマークする setting_delete_modal: 投稿を削除する前に確認ダイアログを表示する + setting_disable_hover_cards: マウスオーバーでプロフィールをポップアップしない setting_disable_swiping: スワイプでの切り替えを無効にする setting_disallow_unlisted_public_searchability: 非収載投稿の検索許可が「誰でも」「ローカルとフォロワー」だった場合、「フォロワーのみ」に変更する setting_display_media: メディアの表示 setting_display_media_default: 標準 - setting_display_media_expand: 5個目以降のメディアも表示する (最大16) setting_display_media_hide_all: 非表示 setting_display_media_show_all: 表示 setting_dtl_force_searchability: DTL投稿の検索許可 diff --git a/config/locales/simple_form.kab.yml b/config/locales/simple_form.kab.yml index 9461f16cd5..63e2b9aacf 100644 --- a/config/locales/simple_form.kab.yml +++ b/config/locales/simple_form.kab.yml @@ -5,6 +5,7 @@ kab: account: display_name: Isem-ik·im ummid neɣ isem-ik·im n uqeṣṣer. fields: Asebter-ik·im agejdan, imqimen, leεmer, ayen tebɣiḍ. + note: 'Tzemreḍ ad d-@tbedreḍ imdanen niḍen neɣ #ihacṭagen.' account_alias: acct: Sekcem isem n umseqdac@domain n umiḍan s wansa itebγiḍ ad gujjeḍ account_migration: @@ -27,6 +28,8 @@ kab: name: 'Ha-t-an kra seg ihacṭagen i tesseqdaceḍ ussan-a ineggura maḍi :' imports: data: Afaylu CSV id yusan seg uqeddac-nniḍen n Maṣṭudun + invite_request: + text: Aya ad aɣ-iɛiwen ad nessenqed tuttra-k•m ip_block: comment: D afrayan. Cfu ɣef wayɣer i terniḍ alugen-a. severities: @@ -36,6 +39,8 @@ kab: fields: name: Tabzimt value: Agbur + account_alias: + acct: Tansa n umiḍan aqbur account_migration: acct: Tansa n umiḍan amaynut account_warning_preset: @@ -51,6 +56,7 @@ kab: suspend: Ḥbes di leεḍil announcement: ends_at: Tagara n tedyant + starts_at: Tazwara n tedyant text: Alɣu defaults: autofollow: Ɛreḍ-it-id ad yeḍfer amiḍan-ik·im @@ -59,18 +65,25 @@ kab: chosen_languages: Sizdeg tutlayin confirm_new_password: Sentem awal uffir amaynut confirm_password: Sentem awal uffir + context: Isatalen n umsizdeg current_password: Awal uffir n tura data: Isefka display_name: Isem ara d-yettwaskanen email: Tansa imayl expires_in: Ad yemmet + fields: Urtiyen niḍen header: Ixef + honeypot: "%{label} (ur tettaččar ara)" + inbox_url: URL n tbewwaḍt n urmas yettwacudden + irreversible: Kkes deg wadeg n tuffra locale: Tutlayt n wegrudem max_uses: Amḍan afellay n iseqdacen new_password: Awal uffir amaynut note: Tameddurt otp_attempt: Tangalt n snat n tarayin password: Awal uffir + phrase: Awal n tsarut neɣ tafyirt + setting_advanced_layout: Rmed agrudem n web leqqayen setting_default_language: Tutlayt n tira setting_default_privacy: Tabaḍnit n tira setting_display_media_default: Akk-a kan @@ -88,8 +101,15 @@ kab: featured_tag: name: Ahacṭag form_admin_settings: + custom_css: CSS udmawan + profile_directory: Rmed akaram n imaγnuten + site_contact_email: Imayl n unermas + site_short_description: Aglam n uqeddac site_terms: Tasertit tabaḍnit site_title: Isem n uqeddac + status_page_url: URL n uusebter n waddaden + theme: Asentel amezwer + thumbnail: Tanfult n uqeddac interactions: must_be_follower: Ssewḥel ilɣa sɣur wid akked tid ur yellin ara d imeḍfaren-ik·im must_be_following: Ssewḥel ilɣa sɣur wid akked tid ur tettḍafareḍ ara @@ -109,18 +129,25 @@ kab: follow: Yeḍfer-ik·im-id walbɛaḍ follow_request: Ma yella win i d-yessutren ad k·em-yeḍfer mention: Yuder-ik·em-id walbɛaḍ + pending_account: Amiḍan amaynut yesran asenqed reblog: Yella win yesselhan adda-dik·im + report: Aneqis amaynut yettwazen rule: hint: Isallen-nniḍen text: Alugen tag: name: Ahacṭag user: + role: Tamlilt time_zone: Tamnaḍt tasragant user_role: name: Isem permissions_as_keys: Tisirag + webhook: + events: Tidyanin turmidin 'no': Ala + not_recommended: Ur yettuwelleh ara + overridden: Yeččur recommended: Yettuwelleh required: mark: "*" diff --git a/config/locales/simple_form.ko.yml b/config/locales/simple_form.ko.yml index 54d36eafe0..1107e4cba5 100644 --- a/config/locales/simple_form.ko.yml +++ b/config/locales/simple_form.ko.yml @@ -211,6 +211,7 @@ ko: setting_default_privacy: 게시물 프라이버시 setting_default_sensitive: 미디어를 언제나 민감한 콘텐츠로 설정 setting_delete_modal: 게시물 삭제 전 확인 창을 표시 + setting_disable_hover_cards: 호버시 프로필 미리보기를 비활성화 setting_disable_swiping: 스와이프 모션 비활성화 setting_display_media: 미디어 표시 setting_display_media_default: 기본 diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml index 2271d7037e..5110e1e6d0 100644 --- a/config/locales/simple_form.nl.yml +++ b/config/locales/simple_form.nl.yml @@ -211,6 +211,7 @@ nl: setting_default_privacy: Zichtbaarheid van nieuwe berichten setting_default_sensitive: Media altijd als gevoelig markeren setting_delete_modal: Vraag voor het verwijderen van een bericht een bevestiging + setting_disable_hover_cards: Profielvoorbeelden door eroverheen te zweven uitschakelen setting_disable_swiping: Swipebewegingen uitschakelen setting_display_media: Mediaweergave setting_display_media_default: Standaard diff --git a/config/locales/simple_form.pl.yml b/config/locales/simple_form.pl.yml index 9d82384af9..b8de10de26 100644 --- a/config/locales/simple_form.pl.yml +++ b/config/locales/simple_form.pl.yml @@ -211,6 +211,7 @@ pl: setting_default_privacy: Widoczność wpisów setting_default_sensitive: Zawsze oznaczaj zawartość multimedialną jako wrażliwą setting_delete_modal: Pytaj o potwierdzenie przed usunięciem wpisu + setting_disable_hover_cards: Wyłącz podgląd profilu po najechaniu setting_disable_swiping: Wyłącz ruchy przesuwania setting_display_media: Wyświetlanie zawartości multimedialnej setting_display_media_default: Domyślne diff --git a/config/locales/simple_form.pt-PT.yml b/config/locales/simple_form.pt-PT.yml index 7fcbb210c5..f993687b91 100644 --- a/config/locales/simple_form.pt-PT.yml +++ b/config/locales/simple_form.pt-PT.yml @@ -211,6 +211,7 @@ pt-PT: setting_default_privacy: Privacidade da publicação setting_default_sensitive: Marcar sempre os media como problemáticos setting_delete_modal: Solicitar confirmação antes de eliminar uma publicação + setting_disable_hover_cards: Desativar visualização de perfil ao passar o cursor setting_disable_swiping: Desativar os movimentos de deslize setting_display_media: Visualização de media setting_display_media_default: Pré-definição diff --git a/config/locales/simple_form.ro.yml b/config/locales/simple_form.ro.yml index dfb44c7745..5df411b951 100644 --- a/config/locales/simple_form.ro.yml +++ b/config/locales/simple_form.ro.yml @@ -2,6 +2,12 @@ ro: simple_form: hints: + account: + discoverable: Este posibil ca postările și profilul tău să fie recomandate în diferite zone ale Mastodon, iar profilul tău ar poate fi sugerat altor utilizatori. + fields: Pagina ta principală, pronumele tale, vârsta, sau orice îți dorești. + indexable: Postările tale publice pot apărea în rezultatele căutărilor pe Mastodon. Persoanele care au interacționat cu postările tale vor putea să le caute oricând. + note: 'Poți @menționa alte persoane sau #hashtag-uri.' + unlocked: Alte persoane vă vor putea urmări fără a solicita aprobare. Debifați dacă doriți să revizuiți cererile și să alegeți dacă doriți să acceptați sau să respingeți noii urmăritori. account_alias: acct: Specificați numele de utilizator@domeniu al contului de la care doriți să treceți account_migration: @@ -23,12 +29,14 @@ ro: text: Poți folosi sintaxa de postare. Te rugăm să fii atent la spațiul pe care anunțul îl va ocupa pe ecranul utilizatorului defaults: autofollow: Persoanele care se înregistrează datorită invitației tale te vor urmări automat + avatar: WEBP, PNG, GIF sau JPG. Cel mult %{size}. Va fi redimensionată la %{dimensions}px bot: Acest cont performează în cea mai mare parte acțiuni automate și nu poate fi monitorizat context: Contextele în care filtrul trebuie aplicat current_password: În scopuri de securitate, vă rugăm să introduceţi parola contului curent current_username: Pentru a confirma, vă rugăm să introduceţi numele de utilizator al contului curent digest: Este trimis doar după o lungă perioadă de inactivitate și numai dacă primești mesaje personale în perioada de absență email: Vei primi un e-mail de confirmare + header: WEBP, PNG, GIF sau JPG. Cel mult %{size}. Va fi redimensionată la %{dimensions}px inbox_url: Copiază adresa URL de pe prima pagină a reului pe care vrei să îl utilizezi irreversible: Postările sortate vor dispărea ireversibil, chiar dacă filtrul este ulterior șters locale: Limba interfaței de utilizator, e-mailurile si notificările push @@ -36,17 +44,27 @@ ro: phrase: Vor fi potrivite indiferent de textul din casetă sau advertismentul unei postări scopes: La care API-uri aplicația are nevoie de acces. Dacă selectezi un scop principal nu mai e nevoie să selectezi fiecare sub-scop al acestuia. setting_aggregate_reblogs: Nu afișa impulsurile noi pentru postările care au fost deja recent impulsionate (afectează doar noile impulsuri primite) + setting_always_send_emails: În mod normal, notificările prin e-mail nu vor fi trimise când utilizați în mod activ Mastodon setting_default_sensitive: Fișierele media sensibile sunt ascunse implicit și pot fi dezvăluite cu un clic setting_display_media_default: Ascunde conținutul media marcat ca sensibil (NSFW) setting_display_media_hide_all: Întotdeauna ascunde tot conținutul media setting_display_media_show_all: Întotdeauna afișează conținutul media marcat ca sensibil setting_use_blurhash: Gradienții sunt bazați pe culorile vizualelor ascunse, dar ofuscă orice detalii setting_use_pending_items: Ascunde actualizările cronologice din spatele unui click în loc de a derula automat fluxul + username: Poți folosi litere, numere sau liniuțe de subliniere whole_word: Când fraza sau cuvântul este doar alfanumeric, acesta se aplică doar dacă există o potrivire completă domain_allow: domain: Acest domeniu va putea prelua date de pe acest server și datele primite de la el vor fi procesate și stocate email_domain_block: + domain: Acesta poate fi numele de domeniu care apare în adresa de e-mail sau în înregistrarea MX pe care o utilizează. Acestea vor fi verificate la înscriere. with_dns_records: Se va face o încercare de a rezolva înregistrările DNS ale domeniului dat și rezultatele vor fi de asemenea afișate pe lista neagră + featured_tag: + name: 'Iată câteva dintre hashtag-urile pe care le-ai folosit cel mai recent:' + filters: + action: Alege ce acţiune va fi efectuată atunci când o postare corespunde filtrului + actions: + hide: Ascunde complet conținutul filtrat, ca și cum nu ar exista + warn: Ascunde conținutul filtrat în spatele unui avertisment care menționează titlul filtrului form_challenge: current_password: Ați intrat într-o zonă securizată imports: diff --git a/config/locales/simple_form.sl.yml b/config/locales/simple_form.sl.yml index 96b36307a5..14551774fe 100644 --- a/config/locales/simple_form.sl.yml +++ b/config/locales/simple_form.sl.yml @@ -211,6 +211,7 @@ sl: setting_default_privacy: Zasebnost objave setting_default_sensitive: Vedno označi medije kot občutljive setting_delete_modal: Pred brisanjem objave prikaži okno za pritrditev + setting_disable_hover_cards: Onemogoči predogled profila pod kazalcem setting_disable_swiping: Onemogoči poteze drsanja setting_display_media: Prikaz medijev setting_display_media_default: Privzeto diff --git a/config/locales/simple_form.sq.yml b/config/locales/simple_form.sq.yml index c3c3920962..6fedf31572 100644 --- a/config/locales/simple_form.sq.yml +++ b/config/locales/simple_form.sq.yml @@ -211,6 +211,7 @@ sq: setting_default_privacy: Privatësi postimi setting_default_sensitive: Mediave vëru përherë shenjë si rezervat setting_delete_modal: Shfaq dialog ripohimi përpara fshirjes së një mesazhi + setting_disable_hover_cards: Çaktivizo paraparje profili, kur i kalohet kursori përsipër setting_disable_swiping: Çaktivizo lëvizje me fërkim setting_display_media: Shfaqje mediash setting_display_media_default: Parazgjedhje diff --git a/config/locales/simple_form.sr-Latn.yml b/config/locales/simple_form.sr-Latn.yml index 710f81e84f..22c07aa7c6 100644 --- a/config/locales/simple_form.sr-Latn.yml +++ b/config/locales/simple_form.sr-Latn.yml @@ -211,6 +211,7 @@ sr-Latn: setting_default_privacy: Privatnost objava setting_default_sensitive: Uvek označi multimediju kao osetljivu setting_delete_modal: Prikaži dijalog za potvrdu pre brisanja objave + setting_disable_hover_cards: Onemogući pregled profila prelaskom kursora setting_disable_swiping: Onemogući pokrete prevlačenja setting_display_media: Prikaz medija setting_display_media_default: Podrazumevano diff --git a/config/locales/simple_form.sr.yml b/config/locales/simple_form.sr.yml index c5fbc9185a..10c1796637 100644 --- a/config/locales/simple_form.sr.yml +++ b/config/locales/simple_form.sr.yml @@ -211,6 +211,7 @@ sr: setting_default_privacy: Приватност објава setting_default_sensitive: Увек означи мултимедију као осетљиву setting_delete_modal: Прикажи дијалог за потврду пре брисања објаве + setting_disable_hover_cards: Онемогући преглед профила преласком курсора setting_disable_swiping: Онемогући покрете превлачења setting_display_media: Приказ медија setting_display_media_default: Подразумевано diff --git a/config/locales/simple_form.th.yml b/config/locales/simple_form.th.yml index 0d9a88bc38..cdc82367f9 100644 --- a/config/locales/simple_form.th.yml +++ b/config/locales/simple_form.th.yml @@ -211,6 +211,7 @@ th: setting_default_privacy: ความเป็นส่วนตัวของการโพสต์ setting_default_sensitive: ทำเครื่องหมายสื่อว่าละเอียดอ่อนเสมอ setting_delete_modal: แสดงกล่องโต้ตอบการยืนยันก่อนลบโพสต์ + setting_disable_hover_cards: ปิดใช้งานตัวอย่างโปรไฟล์เมื่อวางเมาส์เหนือ setting_disable_swiping: ปิดใช้งานการเคลื่อนไหวในการปัด setting_display_media: การแสดงสื่อ setting_display_media_default: ค่าเริ่มต้น diff --git a/config/locales/simple_form.tr.yml b/config/locales/simple_form.tr.yml index 697417a541..b1e90122ec 100644 --- a/config/locales/simple_form.tr.yml +++ b/config/locales/simple_form.tr.yml @@ -211,6 +211,7 @@ tr: setting_default_privacy: Gönderi gizliliği setting_default_sensitive: Medyayı her zaman hassas olarak işaretle setting_delete_modal: Bir gönderiyi silmeden önce onay iletişim kutusu göster + setting_disable_hover_cards: Üstüne geldiğinde profil önizlemesini devre dışı bırak setting_disable_swiping: Kaydırma hareketlerini devre dışı bırak setting_display_media: Medya görüntüleme setting_display_media_default: Varsayılan diff --git a/config/locales/simple_form.uk.yml b/config/locales/simple_form.uk.yml index 11337f2f61..332f2c91dc 100644 --- a/config/locales/simple_form.uk.yml +++ b/config/locales/simple_form.uk.yml @@ -211,6 +211,7 @@ uk: setting_default_privacy: Видимість дописів setting_default_sensitive: Позначати медіа делікатними setting_delete_modal: Показувати діалог підтвердження під час видалення допису + setting_disable_hover_cards: Вимкнути попередній перегляд профілю при наведенні setting_disable_swiping: Вимкнути рух посування setting_display_media: Показ медіа setting_display_media_default: За промовчанням diff --git a/config/locales/simple_form.vi.yml b/config/locales/simple_form.vi.yml index e5063e6112..9006156db1 100644 --- a/config/locales/simple_form.vi.yml +++ b/config/locales/simple_form.vi.yml @@ -211,6 +211,7 @@ vi: setting_default_privacy: Kiểu đăng setting_default_sensitive: Đánh dấu media nhạy cảm setting_delete_modal: Hỏi trước khi xóa tút + setting_disable_hover_cards: Tắt thẻ xem trước hồ sơ setting_disable_swiping: Không dùng chuyển động vuốt setting_display_media: Media nhạy cảm setting_display_media_default: Mặc định diff --git a/config/locales/simple_form.zh-CN.yml b/config/locales/simple_form.zh-CN.yml index 6058cc00cf..bbee8b6706 100644 --- a/config/locales/simple_form.zh-CN.yml +++ b/config/locales/simple_form.zh-CN.yml @@ -211,6 +211,7 @@ zh-CN: setting_default_privacy: 嘟文默认可见范围 setting_default_sensitive: 始终标记媒体为敏感内容 setting_delete_modal: 在删除嘟文前询问我 + setting_disable_hover_cards: 禁用悬停资料预览 setting_disable_swiping: 禁用滑动动作 setting_display_media: 媒体显示 setting_display_media_default: 默认 diff --git a/config/locales/simple_form.zh-TW.yml b/config/locales/simple_form.zh-TW.yml index b7a67c6a6f..7c460a25f5 100644 --- a/config/locales/simple_form.zh-TW.yml +++ b/config/locales/simple_form.zh-TW.yml @@ -211,6 +211,7 @@ zh-TW: setting_default_privacy: 嘟文隱私設定 setting_default_sensitive: 總是將媒體標記為敏感內容 setting_delete_modal: 刪除嘟文前先詢問我 + setting_disable_hover_cards: 停用於滑鼠懸停時預覽個人檔案 setting_disable_swiping: 停用滑動手勢 setting_display_media: 媒體顯示 setting_display_media_default: 預設 diff --git a/config/routes.rb b/config/routes.rb index cabe1b8501..ac08a52b64 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -70,12 +70,16 @@ Rails.application.routes.draw do tokens: 'oauth/tokens' end - get '.well-known/oauth-authorization-server', to: 'well_known/oauth_metadata#show', as: :oauth_metadata, defaults: { format: 'json' } - get '.well-known/host-meta', to: 'well_known/host_meta#show', as: :host_meta, defaults: { format: 'xml' } - get '.well-known/nodeinfo', to: 'well_known/node_info#index', as: :nodeinfo, defaults: { format: 'json' } - get '.well-known/webfinger', to: 'well_known/webfinger#show', as: :webfinger - get '.well-known/change-password', to: redirect('/auth/edit') - get '.well-known/proxy', to: redirect { |_, request| "/authorize_interaction?#{request.params.to_query}" } + scope path: '.well-known' do + scope module: :well_known do + get 'oauth-authorization-server', to: 'oauth_metadata#show', as: :oauth_metadata, defaults: { format: 'json' } + get 'host-meta', to: 'host_meta#show', as: :host_meta, defaults: { format: 'xml' } + get 'nodeinfo', to: 'node_info#index', as: :nodeinfo, defaults: { format: 'json' } + get 'webfinger', to: 'webfinger#show', as: :webfinger + end + get 'change-password', to: redirect('/auth/edit'), as: nil + get 'proxy', to: redirect { |_, request| "/authorize_interaction?#{request.params.to_query}" }, as: nil + end get '/nodeinfo/2.0', to: 'well_known/node_info#show', as: :nodeinfo_schema @@ -101,19 +105,15 @@ Rails.application.routes.draw do namespace :auth do resource :setup, only: [:show, :update], controller: :setup - resource :challenge, only: [:create], controller: :challenges + resource :challenge, only: [:create] get 'sessions/security_key_options', to: 'sessions#webauthn_options' post 'captcha_confirmation', to: 'confirmations#confirm_captcha', as: :captcha_confirmation end end - devise_for :users, path: 'auth', format: false, controllers: { - omniauth_callbacks: 'auth/omniauth_callbacks', - sessions: 'auth/sessions', - registrations: 'auth/registrations', - passwords: 'auth/passwords', - confirmations: 'auth/confirmations', - } + scope module: :auth do + devise_for :users, path: 'auth', format: false + end with_options constraints: ->(req) { req.format.nil? || req.format.html? } do get '/users/:username', to: redirect_with_vary('/@%{username}') diff --git a/config/routes/api.rb b/config/routes/api.rb index b4054d096e..c6e093531c 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -218,9 +218,11 @@ namespace :api, format: false do post :unmute end - resource :pin, only: :create, controller: 'accounts/pins' - post :unpin, to: 'accounts/pins#destroy' - resource :note, only: :create, controller: 'accounts/notes' + scope module: :accounts do + resource :pin, only: :create + post :unpin, to: 'pins#destroy' + resource :note, only: :create + end end resources :tags, only: [:show] do @@ -233,7 +235,7 @@ namespace :api, format: false do resources :followed_tags, only: [:index] resources :lists, only: [:index, :create, :show, :update, :destroy] do - resource :accounts, only: [:show, :create, :destroy], controller: 'lists/accounts' + resource :accounts, only: [:show, :create, :destroy], module: :lists end resources :antennas, only: [:index, :create, :show, :update, :destroy] do @@ -263,7 +265,7 @@ namespace :api, format: false do resources :featured_tags, only: [:index, :create, :destroy] resources :polls, only: [:create, :show] do - resources :votes, only: :create, controller: 'polls/votes' + resources :votes, only: :create, module: :polls end namespace :push do @@ -349,8 +351,10 @@ namespace :api, format: false do resources :suggestions, only: [:index] resource :instance, only: [:show] resources :filters, only: [:index, :create, :show, :update, :destroy] do - resources :keywords, only: [:index, :create], controller: 'filters/keywords' - resources :statuses, only: [:index, :create], controller: 'filters/statuses' + scope module: :filters do + resources :keywords, only: [:index, :create] + resources :statuses, only: [:index, :create] + end end namespace :filters do diff --git a/config/routes/settings.rb b/config/routes/settings.rb index 7b7ed21dd6..6018415fc1 100644 --- a/config/routes/settings.rb +++ b/config/routes/settings.rb @@ -27,9 +27,9 @@ namespace :settings do resources :follows, only: :index, controller: :following_accounts resources :blocks, only: :index, controller: :blocked_accounts resources :mutes, only: :index, controller: :muted_accounts - resources :lists, only: :index, controller: :lists + resources :lists, only: :index resources :domain_blocks, only: :index, controller: :blocked_domains - resources :bookmarks, only: :index, controller: :bookmarks + resources :bookmarks, only: :index end resources :two_factor_authentication_methods, only: [:index] do @@ -38,13 +38,13 @@ namespace :settings do end end - resource :otp_authentication, only: [:show, :create], controller: 'two_factor_authentication/otp_authentication' + scope module: :two_factor_authentication do + resource :otp_authentication, only: [:show, :create], controller: :otp_authentication - resources :webauthn_credentials, only: [:index, :new, :create, :destroy], - path: 'security_keys', - controller: 'two_factor_authentication/webauthn_credentials' do - collection do - get :options + resources :webauthn_credentials, only: [:index, :new, :create, :destroy], path: 'security_keys' do + collection do + get :options + end end end diff --git a/db/post_migrate/20240712064044_remove_dismissed_from_notification_requests.rb b/db/post_migrate/20240712064044_remove_dismissed_from_notification_requests.rb new file mode 100644 index 0000000000..0d85838073 --- /dev/null +++ b/db/post_migrate/20240712064044_remove_dismissed_from_notification_requests.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class RemoveDismissedFromNotificationRequests < ActiveRecord::Migration[7.1] + def up + safety_assured do + execute 'DELETE FROM notification_requests WHERE dismissed' + remove_column :notification_requests, :dismissed + end + end + + def down + add_column :notification_requests, :dismissed, :boolean, default: false, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index f1cde1f528..0673e3e252 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_07_09_063700) do +ActiveRecord::Schema[7.1].define(version: 2024_07_12_064044) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -983,11 +983,9 @@ ActiveRecord::Schema[7.1].define(version: 2024_07_09_063700) do t.bigint "from_account_id", null: false t.bigint "last_status_id" t.bigint "notifications_count", default: 0, null: false - t.boolean "dismissed", default: false, null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["account_id", "from_account_id"], name: "index_notification_requests_on_account_id_and_from_account_id", unique: true - t.index ["account_id", "id"], name: "index_notification_requests_on_account_id_and_id", order: { id: :desc }, where: "(dismissed = false)" t.index ["from_account_id"], name: "index_notification_requests_on_from_account_id" t.index ["last_status_id"], name: "index_notification_requests_on_last_status_id" end diff --git a/spec/controllers/admin/disputes/appeals_controller_spec.rb b/spec/controllers/admin/disputes/appeals_controller_spec.rb index bf7f9bd704..678ceee115 100644 --- a/spec/controllers/admin/disputes/appeals_controller_spec.rb +++ b/spec/controllers/admin/disputes/appeals_controller_spec.rb @@ -34,7 +34,7 @@ RSpec.describe Admin::Disputes::AppealsController do let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } - it 'redirects back to the strike page and notifies target account about approved appeal', :sidekiq_inline do + it 'redirects back to the strike page and notifies target account about approved appeal', :inline_jobs do emails = capture_emails { subject } expect(response) @@ -58,7 +58,7 @@ RSpec.describe Admin::Disputes::AppealsController do let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } - it 'redirects back to the strike page and notifies target account about rejected appeal', :sidekiq_inline do + it 'redirects back to the strike page and notifies target account about rejected appeal', :inline_jobs do emails = capture_emails { subject } expect(response) diff --git a/spec/controllers/admin/domain_blocks_controller_spec.rb b/spec/controllers/admin/domain_blocks_controller_spec.rb index 87b08323da..eb2c6265d1 100644 --- a/spec/controllers/admin/domain_blocks_controller_spec.rb +++ b/spec/controllers/admin/domain_blocks_controller_spec.rb @@ -176,7 +176,7 @@ RSpec.describe Admin::DomainBlocksController do end end - describe 'PUT #update', :sidekiq_inline do + describe 'PUT #update', :inline_jobs do subject do post :update, params: { :id => domain_block.id, :domain_block => { domain: 'example.com', severity: new_severity }, 'confirm' => '' } end diff --git a/spec/controllers/admin/resets_controller_spec.rb b/spec/controllers/admin/resets_controller_spec.rb index 10ed2cf969..0cbc3b60ab 100644 --- a/spec/controllers/admin/resets_controller_spec.rb +++ b/spec/controllers/admin/resets_controller_spec.rb @@ -13,7 +13,7 @@ describe Admin::ResetsController do sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')), scope: :user end - describe 'POST #create', :sidekiq_inline do + describe 'POST #create', :inline_jobs do it 'redirects to admin accounts page' do emails = capture_emails { subject } diff --git a/spec/controllers/auth/sessions_controller_spec.rb b/spec/controllers/auth/sessions_controller_spec.rb index e78554ec7d..9a94e5e1a1 100644 --- a/spec/controllers/auth/sessions_controller_spec.rb +++ b/spec/controllers/auth/sessions_controller_spec.rb @@ -123,7 +123,7 @@ RSpec.describe Auth::SessionsController do user.update(current_sign_in_at: 1.month.ago) end - it 'logs the user in and sends suspicious email and redirects home', :sidekiq_inline do + it 'logs the user in and sends suspicious email and redirects home', :inline_jobs do emails = capture_emails { subject } expect(response) @@ -263,7 +263,7 @@ RSpec.describe Auth::SessionsController do travel_to '2023-12-20T10:00:00Z' end - it 'does not log the user in, sets a flash message, and sends a suspicious sign in email', :sidekiq_inline do + it 'does not log the user in, sets a flash message, and sends a suspicious sign in email', :inline_jobs do emails = capture_emails do Auth::SessionsController::MAX_2FA_ATTEMPTS_PER_HOUR.times do post :create, params: { user: { otp_attempt: '1234' } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s } diff --git a/spec/controllers/concerns/user_tracking_concern_spec.rb b/spec/controllers/concerns/user_tracking_concern_spec.rb index b1de3cf4e2..f23d482f5f 100644 --- a/spec/controllers/concerns/user_tracking_concern_spec.rb +++ b/spec/controllers/concerns/user_tracking_concern_spec.rb @@ -75,7 +75,7 @@ describe UserTrackingConcern do expect(redis.ttl("account:#{user.account_id}:regeneration")).to be >= 0 end - it 'regenerates feed when sign in is older than two weeks', :sidekiq_inline do + it 'regenerates feed when sign in is older than two weeks', :inline_jobs do get :show expect_updated_sign_in_at(user) diff --git a/spec/controllers/disputes/appeals_controller_spec.rb b/spec/controllers/disputes/appeals_controller_spec.rb index 99d5a8b17f..3e874bbdcc 100644 --- a/spec/controllers/disputes/appeals_controller_spec.rb +++ b/spec/controllers/disputes/appeals_controller_spec.rb @@ -17,7 +17,7 @@ RSpec.describe Disputes::AppealsController do let(:strike) { Fabricate(:account_warning, target_account: current_user.account) } let(:params) { { strike_id: strike.id, appeal: { text: 'Foo' } } } - it 'notifies staff about new appeal and redirects back to strike page', :sidekiq_inline do + it 'notifies staff about new appeal and redirects back to strike page', :inline_jobs do emails = capture_emails { subject } expect(emails.size) @@ -36,7 +36,7 @@ RSpec.describe Disputes::AppealsController do let(:strike) { Fabricate(:account_warning, target_account: current_user.account) } let(:params) { { strike_id: strike.id, appeal: { text: '' } } } - it 'does not send email and renders strike show page', :sidekiq_inline do + it 'does not send email and renders strike show page', :inline_jobs do emails = capture_emails { subject } expect(emails).to be_empty diff --git a/spec/controllers/invites_controller_spec.rb b/spec/controllers/invites_controller_spec.rb index 3190c82884..5221941267 100644 --- a/spec/controllers/invites_controller_spec.rb +++ b/spec/controllers/invites_controller_spec.rb @@ -69,19 +69,16 @@ describe InvitesController do end end - describe 'DELETE #create' do + describe 'DELETE #destroy' do + subject { delete :destroy, params: { id: invite.id } } + let(:invite) { Fabricate(:invite, user: user, expires_at: nil) } - before do - delete :destroy, params: { id: invite.id } - end - - it 'redirects' do - expect(response).to redirect_to invites_path - end - - it 'expires invite' do - expect(invite.reload).to be_expired + it 'expires invite and redirects' do + expect { subject } + .to(change { invite.reload.expired? }.to(true)) + expect(response) + .to redirect_to invites_path end end end diff --git a/spec/controllers/settings/deletes_controller_spec.rb b/spec/controllers/settings/deletes_controller_spec.rb index ccca4564e7..3342599bc1 100644 --- a/spec/controllers/settings/deletes_controller_spec.rb +++ b/spec/controllers/settings/deletes_controller_spec.rb @@ -50,7 +50,7 @@ describe Settings::DeletesController do delete :destroy, params: { form_delete_confirmation: { password: 'petsmoldoggos' } } end - it 'removes user record and redirects', :aggregate_failures, :sidekiq_inline do + it 'removes user record and redirects', :aggregate_failures, :inline_jobs do expect(response).to redirect_to '/auth/sign_in' expect(User.find_by(id: user.id)).to be_nil expect(user.account.reload).to be_suspended diff --git a/spec/fabricators/notification_request_fabricator.rb b/spec/fabricators/notification_request_fabricator.rb index 05a13b8ef8..a20d3b3ef2 100644 --- a/spec/fabricators/notification_request_fabricator.rb +++ b/spec/fabricators/notification_request_fabricator.rb @@ -4,5 +4,4 @@ Fabricator(:notification_request) do account from_account { Fabricate.build(:account) } last_status { Fabricate.build(:status) } - dismissed false end diff --git a/spec/fixtures/requests/alternative_utf8_spelling_in_header.txt b/spec/fixtures/requests/alternative_utf8_spelling_in_header.txt new file mode 100644 index 0000000000..7aaea370e8 --- /dev/null +++ b/spec/fixtures/requests/alternative_utf8_spelling_in_header.txt @@ -0,0 +1,18 @@ +HTTP/1.1 200 OK +server: nginx +date: Thu, 13 Jun 2024 14:33:13 GMT +content-type: text/html; charset=utf8 +content-length: 192 +accept-ranges: bytes + + + + + + Webserver Configs R Us + + +

Welcome

+

Sneaky non-UTF character:

+ + diff --git a/spec/fixtures/requests/latin1_posing_as_utf8_broken.txt b/spec/fixtures/requests/latin1_posing_as_utf8_broken.txt new file mode 100644 index 0000000000..ed8a4716a3 --- /dev/null +++ b/spec/fixtures/requests/latin1_posing_as_utf8_broken.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=utf-8 +content-length: 158 +accept-ranges: bytes + + + + + + Tofu l'orange + + +

Tofu l'orange

+ + diff --git a/spec/fixtures/requests/latin1_posing_as_utf8_recoverable.txt b/spec/fixtures/requests/latin1_posing_as_utf8_recoverable.txt new file mode 100644 index 0000000000..a24985832c --- /dev/null +++ b/spec/fixtures/requests/latin1_posing_as_utf8_recoverable.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=utf-8 +content-length: 158 +accept-ranges: bytes + + + + + + Tofu with orange sauce + + +

Tofu l'orange

+ + diff --git a/spec/fixtures/requests/long_canonical_url.txt b/spec/fixtures/requests/long_canonical_url.txt new file mode 100644 index 0000000000..97d6c93961 --- /dev/null +++ b/spec/fixtures/requests/long_canonical_url.txt @@ -0,0 +1,18 @@ +HTTP/1.1 200 OK +server: nginx +date: Thu, 13 Jun 2024 14:33:13 GMT +content-type: text/html; charset=utf-8 +content-length: 3225 +accept-ranges: bytes + + + + + + + Very long canonical URL + + +

We have very long URLs

+ + diff --git a/spec/fixtures/requests/page_without_title.txt b/spec/fixtures/requests/page_without_title.txt new file mode 100644 index 0000000000..0054aa3b7e --- /dev/null +++ b/spec/fixtures/requests/page_without_title.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=utf-8 +content-length: 171 +accept-ranges: bytes + + + + + + + +

I am not a valid page

+

Thankfully, browsers do not care

+ + diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index d9cd0494f0..03951d6999 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -1046,7 +1046,7 @@ RSpec.describe ActivityPub::Activity::Create do expect(status.mentions.map(&:account_id)).to contain_exactly(recipient.id, ancestor_account.id, mentioned_account.id, local_mentioned_account.id) end - it 'forwards to observers', :sidekiq_inline do + it 'forwards to observers', :inline_jobs do expect(a_request(:post, 'http://or.example.com/actor/inbox')).to have_been_made.once expect(a_request(:post, 'http://example.com/bob/inbox')).to have_been_made.once end @@ -1089,7 +1089,7 @@ RSpec.describe ActivityPub::Activity::Create do expect(status.mentions.map(&:account_id)).to contain_exactly(recipient.id, ancestor_account.id, mentioned_account.id, local_mentioned_account.id, new_mentioned_account.id, new_local_mentioned_account.id) end - it 'forwards to observers', :sidekiq_inline do + it 'forwards to observers', :inline_jobs do expect(a_request(:post, 'http://or.example.com/actor/inbox')).to have_been_made.once expect(a_request(:post, 'http://example.com/bob/inbox')).to have_been_made.once expect(a_request(:post, 'http://example.com/alice/inbox')).to have_been_made.once @@ -1142,7 +1142,7 @@ RSpec.describe ActivityPub::Activity::Create do expect(status.mentioned_accounts.map(&:uri)).to include 'https://foo.test' end - it 'forwards to observers', :sidekiq_inline do + it 'forwards to observers', :inline_jobs do expect(a_request(:post, 'https://foo.test/inbox')).to have_been_made.once end end @@ -1159,7 +1159,7 @@ RSpec.describe ActivityPub::Activity::Create do expect(status.mentions.map(&:account_id)).to contain_exactly(recipient.id) end - it 'do not forward to observers', :sidekiq_inline do + it 'do not forward to observers', :inline_jobs do expect(a_request(:post, 'http://or.example.com/actor/inbox')).to_not have_been_made expect(a_request(:post, 'http://example.com/bob/inbox')).to_not have_been_made end diff --git a/spec/lib/activitypub/activity/delete_spec.rb b/spec/lib/activitypub/activity/delete_spec.rb index f1631f73da..9e31533a97 100644 --- a/spec/lib/activitypub/activity/delete_spec.rb +++ b/spec/lib/activitypub/activity/delete_spec.rb @@ -47,7 +47,7 @@ RSpec.describe ActivityPub::Activity::Delete do expect(Status.find_by(id: status.id)).to be_nil end - it 'sends delete activity to followers of rebloggers', :sidekiq_inline do + it 'sends delete activity to followers of rebloggers', :inline_jobs do expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once end @@ -91,7 +91,7 @@ RSpec.describe ActivityPub::Activity::Delete do subject.perform end - it 'forwards to parent status holder', :sidekiq_inline do + it 'forwards to parent status holder', :inline_jobs do expect(a_request(:post, 'https://example.com/inbox').with(body: hash_including({ type: 'Delete', signature: 'foo', diff --git a/spec/lib/activitypub/activity/follow_spec.rb b/spec/lib/activitypub/activity/follow_spec.rb index ef8ff24321..ec0e5e4eef 100644 --- a/spec/lib/activitypub/activity/follow_spec.rb +++ b/spec/lib/activitypub/activity/follow_spec.rb @@ -455,7 +455,7 @@ RSpec.describe ActivityPub::Activity::Follow do stub_request(:post, 'https://example.com/inbox') end - it 'marks me as idle and the friend as accepted', :sidekiq_inline do + it 'marks me as idle and the friend as accepted', :inline_jobs do subject.perform expect(friend.reload.they_are_accepted?).to be true expect(friend.i_am_idle?).to be true @@ -503,7 +503,7 @@ RSpec.describe ActivityPub::Activity::Follow do stub_request(:post, 'https://example.com/inbox') end - it 'marks the friend as accepted', :sidekiq_inline do + it 'marks the friend as accepted', :inline_jobs do subject.perform friend = FriendDomain.find_by(domain: 'abc.com') @@ -523,7 +523,7 @@ RSpec.describe ActivityPub::Activity::Follow do stub_request(:post, 'https://example.com/inbox') end - it 'marks the friend as accepted', :sidekiq_inline do + it 'marks the friend as accepted', :inline_jobs do subject.perform friend = FriendDomain.find_by(domain: 'abc.com') diff --git a/spec/lib/activitypub/activity/move_spec.rb b/spec/lib/activitypub/activity/move_spec.rb index 4dda014a06..d69ef21516 100644 --- a/spec/lib/activitypub/activity/move_spec.rb +++ b/spec/lib/activitypub/activity/move_spec.rb @@ -38,7 +38,7 @@ RSpec.describe ActivityPub::Activity::Move do subject.perform end - context 'when all conditions are met', :sidekiq_inline do + context 'when all conditions are met', :inline_jobs do it 'sets moved account on old account' do expect(old_account.reload.moved_to_account_id).to eq new_account.id end diff --git a/spec/lib/activitypub/activity/update_spec.rb b/spec/lib/activitypub/activity/update_spec.rb index 7f312e044b..d2c4c1ce28 100644 --- a/spec/lib/activitypub/activity/update_spec.rb +++ b/spec/lib/activitypub/activity/update_spec.rb @@ -138,7 +138,7 @@ RSpec.describe ActivityPub::Activity::Update do subject.perform end - it 'does not create a new status', :sidekiq_inline do + it 'does not create a new status', :inline_jobs do status = Status.find_by(uri: 'https://example.com/note') expect(status).to be_nil end @@ -170,7 +170,7 @@ RSpec.describe ActivityPub::Activity::Update do subject.perform end - it 'forwards to parent status holder', :sidekiq_inline do + it 'forwards to parent status holder', :inline_jobs do expect(a_request(:post, 'https://example.com/inbox').with(body: hash_including({ type: 'Update', signature: 'foo', diff --git a/spec/lib/link_details_extractor_spec.rb b/spec/lib/link_details_extractor_spec.rb index 26d9d4e265..2a4df70a8b 100644 --- a/spec/lib/link_details_extractor_spec.rb +++ b/spec/lib/link_details_extractor_spec.rb @@ -192,6 +192,35 @@ RSpec.describe LinkDetailsExtractor do include_examples 'structured data' end + + context 'with author names as array' do + let(:ld_json) do + { + '@context' => 'https://schema.org', + '@type' => 'NewsArticle', + 'headline' => 'A lot of authors', + 'description' => 'But we decided to cram them into one', + 'author' => { + '@type' => 'Person', + 'name' => ['Author 1', 'Author 2'], + }, + }.to_json + end + let(:html) { <<~HTML } + + + + + + + HTML + + it 'joins author names' do + expect(subject.author_name).to eq 'Author 1, Author 2' + end + end end context 'when Open Graph protocol data is present' do diff --git a/spec/lib/vacuum/media_attachments_vacuum_spec.rb b/spec/lib/vacuum/media_attachments_vacuum_spec.rb index 3c17ecb000..1039c36cea 100644 --- a/spec/lib/vacuum/media_attachments_vacuum_spec.rb +++ b/spec/lib/vacuum/media_attachments_vacuum_spec.rb @@ -17,32 +17,21 @@ RSpec.describe Vacuum::MediaAttachmentsVacuum do let!(:old_unattached_media) { Fabricate(:media_attachment, account_id: nil, created_at: 10.days.ago) } let!(:new_unattached_media) { Fabricate(:media_attachment, account_id: nil, created_at: 1.hour.ago) } - before do - subject.perform - end + before { subject.perform } - it 'deletes cache of remote media attachments past the retention period' do - expect(old_remote_media.reload.file).to be_blank - end - - it 'does not touch local media attachments past the retention period' do - expect(old_local_media.reload.file).to_not be_blank - end - - it 'does not delete cache of remote media attachments within the retention period' do - expect(new_remote_media.reload.file).to_not be_blank - end - - it 'does not touch local media attachments within the retention period' do - expect(new_local_media.reload.file).to_not be_blank - end - - it 'deletes unattached media attachments past TTL' do - expect { old_unattached_media.reload }.to raise_error(ActiveRecord::RecordNotFound) - end - - it 'does not delete unattached media attachments within TTL' do - expect(new_unattached_media.reload).to be_persisted + it 'handles attachments based on metadata details' do + expect(old_remote_media.reload.file) # Remote and past retention period + .to be_blank + expect(old_local_media.reload.file) # Local and past retention + .to_not be_blank + expect(new_remote_media.reload.file) # Remote and within retention + .to_not be_blank + expect(new_local_media.reload.file) # Local and within retention + .to_not be_blank + expect { old_unattached_media.reload } # Unattached and past TTL + .to raise_error(ActiveRecord::RecordNotFound) + expect(new_unattached_media.reload) # Unattached and within TTL + .to be_persisted end end end diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index 2851bbe83c..c4e5b15bac 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -1238,21 +1238,26 @@ RSpec.describe Account do context 'when is local' do it 'generates keys' do - account = described_class.create!(domain: nil, username: Faker::Internet.user_name(separators: ['_'])) - expect(account.keypair).to be_private - expect(account.keypair).to be_public + account = described_class.create!(domain: nil, username: 'user_without_keys') + + expect(account) + .to be_private_key + .and be_public_key + expect(account.keypair) + .to be_private + .and be_public end end context 'when is remote' do it 'does not generate keys' do key = OpenSSL::PKey::RSA.new(1024).public_key - account = described_class.create!(domain: 'remote', uri: 'https://remote/actor', username: Faker::Internet.user_name(separators: ['_']), public_key: key.to_pem) + account = described_class.create!(domain: 'remote', uri: 'https://remote/actor', username: 'remote_user_with_public', public_key: key.to_pem) expect(account.keypair.params).to eq key.params end it 'normalizes domain' do - account = described_class.create!(domain: 'にゃん', uri: 'https://xn--r9j5b5b/actor', username: Faker::Internet.user_name(separators: ['_'])) + account = described_class.create!(domain: 'にゃん', uri: 'https://xn--r9j5b5b/actor', username: 'remote_user_with_idn_domain') expect(account.domain).to eq 'xn--r9j5b5b' end end diff --git a/spec/models/admin/account_action_spec.rb b/spec/models/admin/account_action_spec.rb index e55db2f814..49bc2b4a91 100644 --- a/spec/models/admin/account_action_spec.rb +++ b/spec/models/admin/account_action_spec.rb @@ -69,7 +69,7 @@ RSpec.describe Admin::AccountAction do end end - it 'sends email to target account user', :sidekiq_inline do + it 'sends email to target account user', :inline_jobs do emails = capture_emails { subject } expect(emails).to contain_exactly( diff --git a/spec/models/custom_emoji_spec.rb b/spec/models/custom_emoji_spec.rb index d4fa823d8c..329bab170d 100644 --- a/spec/models/custom_emoji_spec.rb +++ b/spec/models/custom_emoji_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -RSpec.describe CustomEmoji, :paperclip_processing do +RSpec.describe CustomEmoji, :attachment_processing do describe '#search' do subject { described_class.search(search_term) } diff --git a/spec/models/friend_domain_spec.rb b/spec/models/friend_domain_spec.rb index b92dbe7550..98dcb9cd90 100644 --- a/spec/models/friend_domain_spec.rb +++ b/spec/models/friend_domain_spec.rb @@ -10,7 +10,7 @@ describe FriendDomain do end describe '#follow!' do - it 'call inbox', :sidekiq_inline do + it 'call inbox', :inline_jobs do friend.update(active_state: :accepted, passive_state: :accepted) friend.follow! expect(friend.active_follow_activity_id).to_not be_nil @@ -27,7 +27,7 @@ describe FriendDomain do end describe '#unfollow!' do - it 'call inbox', :sidekiq_inline do + it 'call inbox', :inline_jobs do friend.update(active_follow_activity_id: 'ohagi', active_state: :accepted, passive_state: :accepted) friend.unfollow! expect(friend.active_follow_activity_id).to be_nil @@ -46,7 +46,7 @@ describe FriendDomain do end describe '#accept!' do - it 'call inbox', :sidekiq_inline do + it 'call inbox', :inline_jobs do friend.update(passive_follow_activity_id: 'ohagi', active_state: :accepted, passive_state: :pending) friend.accept! expect(friend.they_are_accepted?).to be true @@ -61,7 +61,7 @@ describe FriendDomain do end describe '#reject!' do - it 'call inbox', :sidekiq_inline do + it 'call inbox', :inline_jobs do friend.update(passive_follow_activity_id: 'ohagi', active_state: :accepted, passive_state: :pending) friend.reject! expect(friend.they_are_rejected?).to be true @@ -76,7 +76,7 @@ describe FriendDomain do end describe '#delete!' do - it 'call inbox', :sidekiq_inline do + it 'call inbox', :inline_jobs do friend.update(active_state: :pending) friend.destroy expect(a_request(:post, 'https://foo.bar/inbox').with(body: hash_including({ diff --git a/spec/models/media_attachment_spec.rb b/spec/models/media_attachment_spec.rb index a8f1ce7745..24e8ca39c1 100644 --- a/spec/models/media_attachment_spec.rb +++ b/spec/models/media_attachment_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -RSpec.describe MediaAttachment, :paperclip_processing do +RSpec.describe MediaAttachment, :attachment_processing do describe 'local?' do subject { media_attachment.local? } diff --git a/spec/models/notification_request_spec.rb b/spec/models/notification_request_spec.rb index 07bbc3e0a8..4adddc194f 100644 --- a/spec/models/notification_request_spec.rb +++ b/spec/models/notification_request_spec.rb @@ -4,9 +4,7 @@ require 'rails_helper' RSpec.describe NotificationRequest do describe '#reconsider_existence!' do - subject { Fabricate(:notification_request, dismissed: dismissed) } - - let(:dismissed) { false } + subject { Fabricate(:notification_request) } context 'when there are remaining notifications' do before do @@ -28,14 +26,6 @@ RSpec.describe NotificationRequest do subject.reconsider_existence! end - context 'when dismissed' do - let(:dismissed) { true } - - it 'leaves request intact' do - expect(subject.destroyed?).to be false - end - end - it 'removes the request' do expect(subject.destroyed?).to be true end diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb index 18a62e451c..7e757f0759 100644 --- a/spec/models/status_spec.rb +++ b/spec/models/status_spec.rb @@ -422,6 +422,41 @@ RSpec.describe Status do end end + describe '#ordered_media_attachments' do + let(:status) { Fabricate(:status) } + + let(:first_attachment) { Fabricate(:media_attachment) } + let(:second_attachment) { Fabricate(:media_attachment) } + let(:last_attachment) { Fabricate(:media_attachment) } + let(:extra_attachment) { Fabricate(:media_attachment) } + + before do + stub_const('Status::MEDIA_ATTACHMENTS_LIMIT', 3) + + # Add attachments out of order + status.media_attachments << second_attachment + status.media_attachments << last_attachment + status.media_attachments << extra_attachment + status.media_attachments << first_attachment + end + + context 'when ordered_media_attachment_ids is not set' do + it 'returns up to MEDIA_ATTACHMENTS_LIMIT attachments' do + expect(status.ordered_media_attachments.size).to eq Status::MEDIA_ATTACHMENTS_LIMIT + end + end + + context 'when ordered_media_attachment_ids is set' do + before do + status.update!(ordered_media_attachment_ids: [first_attachment.id, second_attachment.id, last_attachment.id, extra_attachment.id]) + end + + it 'returns up to MEDIA_ATTACHMENTS_LIMIT attachments in the expected order' do + expect(status.ordered_media_attachments).to eq [first_attachment, second_attachment, last_attachment] + end + end + end + describe '.mutes_map' do subject { described_class.mutes_map([status.conversation.id], account) } diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 287b73e770..f6f4a2104c 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -101,7 +101,7 @@ RSpec.describe User do end end - describe 'scopes', :sidekiq_inline do + describe 'scopes', :inline_jobs do describe 'recent' do it 'returns an array of recent users ordered by id' do first_user = Fabricate(:user) @@ -539,7 +539,7 @@ RSpec.describe User do context 'when user is new' do let(:confirmed_at) { nil } - it 'confirms user and delivers welcome email', :sidekiq_inline do + it 'confirms user and delivers welcome email', :inline_jobs do emails = capture_emails { subject } expect(user.confirmed_at).to be_present diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 38aa711089..79031f1a94 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -120,7 +120,7 @@ RSpec.configure do |config| end config.around do |example| - if example.metadata[:sidekiq_inline] == true + if example.metadata[:inline_jobs] == true Sidekiq::Testing.inline! else Sidekiq::Testing.fake! @@ -137,7 +137,7 @@ RSpec.configure do |config| end config.before do |example| - unless example.metadata[:paperclip_processing] + unless example.metadata[:attachment_processing] allow_any_instance_of(Paperclip::Attachment).to receive(:post_process).and_return(true) # rubocop:disable RSpec/AnyInstance end end diff --git a/spec/requests/api/v1/accounts/statuses_spec.rb b/spec/requests/api/v1/accounts/statuses_spec.rb index 371867b215..97cdbe0156 100644 --- a/spec/requests/api/v1/accounts/statuses_spec.rb +++ b/spec/requests/api/v1/accounts/statuses_spec.rb @@ -10,12 +10,15 @@ describe 'API V1 Accounts Statuses' do describe 'GET /api/v1/accounts/:account_id/statuses' do it 'returns expected headers', :aggregate_failures do - Fabricate(:status, account: user.account) + status = Fabricate(:status, account: user.account) get "/api/v1/accounts/#{user.account.id}/statuses", params: { limit: 1 }, headers: headers - expect(response).to have_http_status(200) - expect(links_from_header.size) - .to eq(2) + expect(response) + .to have_http_status(200) + .and include_pagination_headers( + prev: api_v1_account_statuses_url(limit: 1, min_id: status.id), + next: api_v1_account_statuses_url(limit: 1, max_id: status.id) + ) end context 'with only media' do @@ -55,16 +58,9 @@ describe 'API V1 Accounts Statuses' do it 'returns http success and includes a header link' do get "/api/v1/accounts/#{user.account.id}/statuses", params: { pinned: true }, headers: headers - expect(response).to have_http_status(200) - expect(links_from_header.size) - .to eq(1) - expect(links_from_header) - .to contain_exactly( - have_attributes( - href: /pinned=true/, - attr_pairs: contain_exactly(['rel', 'prev']) - ) - ) + expect(response) + .to have_http_status(200) + .and include_pagination_headers(prev: api_v1_account_statuses_url(pinned: true, min_id: Status.first.id)) end end @@ -77,19 +73,11 @@ describe 'API V1 Accounts Statuses' do it 'returns http success and header pagination links to prev and next' do get "/api/v1/accounts/#{user.account.id}/statuses", params: { pinned: true }, headers: headers - expect(response).to have_http_status(200) - expect(links_from_header.size) - .to eq(2) - expect(links_from_header) - .to contain_exactly( - have_attributes( - href: /pinned=true/, - attr_pairs: contain_exactly(['rel', 'next']) - ), - have_attributes( - href: /pinned=true/, - attr_pairs: contain_exactly(['rel', 'prev']) - ) + expect(response) + .to have_http_status(200) + .and include_pagination_headers( + prev: api_v1_account_statuses_url(pinned: true, min_id: Status.first.id), + next: api_v1_account_statuses_url(pinned: true, max_id: Status.first.id) ) end end @@ -138,12 +126,4 @@ describe 'API V1 Accounts Statuses' do end end end - - private - - def links_from_header - response - .headers['Link'] - .links - end end diff --git a/spec/requests/api/v1/admin/account_actions_spec.rb b/spec/requests/api/v1/admin/account_actions_spec.rb index 778658508e..5bcf809401 100644 --- a/spec/requests/api/v1/admin/account_actions_spec.rb +++ b/spec/requests/api/v1/admin/account_actions_spec.rb @@ -10,7 +10,7 @@ RSpec.describe 'Account actions' do let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } shared_examples 'a successful notification delivery' do - it 'notifies the user about the action taken', :sidekiq_inline do + it 'notifies the user about the action taken', :inline_jobs do emails = capture_emails { subject } expect(emails.size) diff --git a/spec/requests/api/v1/conversations_spec.rb b/spec/requests/api/v1/conversations_spec.rb index caa0f5c52c..f136e1f4e8 100644 --- a/spec/requests/api/v1/conversations_spec.rb +++ b/spec/requests/api/v1/conversations_spec.rb @@ -10,7 +10,7 @@ RSpec.describe 'API V1 Conversations' do let(:other) { Fabricate(:user) } - describe 'GET /api/v1/conversations', :sidekiq_inline do + describe 'GET /api/v1/conversations', :inline_jobs do before do user.account.follow!(other.account) PostStatusService.new.call(other.account, text: 'Hey @alice', visibility: 'direct') @@ -20,8 +20,12 @@ RSpec.describe 'API V1 Conversations' do it 'returns pagination headers', :aggregate_failures do get '/api/v1/conversations', params: { limit: 1 }, headers: headers - expect(response).to have_http_status(200) - expect(response.headers['Link'].links.size).to eq(2) + expect(response) + .to have_http_status(200) + .and include_pagination_headers( + prev: api_v1_conversations_url(limit: 1, min_id: Status.first.id), + next: api_v1_conversations_url(limit: 1, max_id: Status.first.id) + ) end it 'returns conversations', :aggregate_failures do diff --git a/spec/requests/api/v1/featured_tags_spec.rb b/spec/requests/api/v1/featured_tags_spec.rb index f499dd1d09..4b96988704 100644 --- a/spec/requests/api/v1/featured_tags_spec.rb +++ b/spec/requests/api/v1/featured_tags_spec.rb @@ -147,7 +147,7 @@ RSpec.describe 'FeaturedTags' do expect(body).to be_empty end - it 'deletes the featured tag', :sidekiq_inline do + it 'deletes the featured tag', :inline_jobs do delete "/api/v1/featured_tags/#{id}", headers: headers featured_tag = FeaturedTag.find_by(id: id) diff --git a/spec/requests/api/v1/media_spec.rb b/spec/requests/api/v1/media_spec.rb index 26c76b9c5b..c89c49afdf 100644 --- a/spec/requests/api/v1/media_spec.rb +++ b/spec/requests/api/v1/media_spec.rb @@ -121,19 +121,19 @@ RSpec.describe 'Media' do end end - context 'with image/jpeg', :paperclip_processing do + context 'with image/jpeg', :attachment_processing do let(:params) { { file: fixture_file_upload('attachment.jpg', 'image/jpeg'), description: 'jpeg image' } } it_behaves_like 'a successful media upload', 'image' end - context 'with image/gif', :paperclip_processing do + context 'with image/gif', :attachment_processing do let(:params) { { file: fixture_file_upload('attachment.gif', 'image/gif') } } it_behaves_like 'a successful media upload', 'image' end - context 'with video/webm', :paperclip_processing do + context 'with video/webm', :attachment_processing do let(:params) { { file: fixture_file_upload('attachment.webm', 'video/webm') } } it_behaves_like 'a successful media upload', 'gifv' diff --git a/spec/requests/api/v1/notifications/policies_spec.rb b/spec/requests/api/v1/notifications/policies_spec.rb index d02d2ed0d7..cbd4499772 100644 --- a/spec/requests/api/v1/notifications/policies_spec.rb +++ b/spec/requests/api/v1/notifications/policies_spec.rb @@ -8,7 +8,7 @@ RSpec.describe 'Policies' do let(:scopes) { 'read:notifications write:notifications' } let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } - describe 'GET /api/v1/notifications/policy', :sidekiq_inline do + describe 'GET /api/v1/notifications/policy', :inline_jobs do subject do get '/api/v1/notifications/policy', headers: headers, params: params end diff --git a/spec/requests/api/v1/notifications/requests_spec.rb b/spec/requests/api/v1/notifications/requests_spec.rb index 772402a6b5..d3a9753246 100644 --- a/spec/requests/api/v1/notifications/requests_spec.rb +++ b/spec/requests/api/v1/notifications/requests_spec.rb @@ -8,7 +8,7 @@ RSpec.describe 'Requests' do let(:scopes) { 'read:notifications write:notifications' } let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } - describe 'GET /api/v1/notifications/requests', :sidekiq_inline do + describe 'GET /api/v1/notifications/requests', :inline_jobs do subject do get '/api/v1/notifications/requests', headers: headers, params: params end @@ -17,7 +17,6 @@ RSpec.describe 'Requests' do before do Fabricate(:notification_request, account: user.account) - Fabricate(:notification_request, account: user.account, dismissed: true) end it_behaves_like 'forbidden for wrong scope', 'write write:notifications' @@ -29,16 +28,6 @@ RSpec.describe 'Requests' do expect(response).to have_http_status(200) end end - - context 'with dismissed' do - let(:params) { { dismissed: '1' } } - - it 'returns http success', :aggregate_failures do - subject - - expect(response).to have_http_status(200) - end - end end describe 'POST /api/v1/notifications/requests/:id/accept' do @@ -78,15 +67,14 @@ RSpec.describe 'Requests' do post "/api/v1/notifications/requests/#{notification_request.id}/dismiss", headers: headers end - let(:notification_request) { Fabricate(:notification_request, account: user.account) } + let!(:notification_request) { Fabricate(:notification_request, account: user.account) } it_behaves_like 'forbidden for wrong scope', 'read read:notifications' - it 'returns http success and dismisses the notification request', :aggregate_failures do - subject + it 'returns http success and destroys the notification request', :aggregate_failures do + expect { subject }.to change(NotificationRequest, :count).by(-1) expect(response).to have_http_status(200) - expect(notification_request.reload.dismissed?).to be true end context 'when notification request belongs to someone else' do diff --git a/spec/requests/api/v1/notifications_spec.rb b/spec/requests/api/v1/notifications_spec.rb index 55d3cdac94..c9034c17dc 100644 --- a/spec/requests/api/v1/notifications_spec.rb +++ b/spec/requests/api/v1/notifications_spec.rb @@ -8,7 +8,7 @@ RSpec.describe 'Notifications' do let(:scopes) { 'read:notifications write:notifications' } let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } - describe 'GET /api/v1/notifications', :sidekiq_inline do + describe 'GET /api/v1/notifications', :inline_jobs do subject do get '/api/v1/notifications', headers: headers, params: params end @@ -20,8 +20,8 @@ RSpec.describe 'Notifications' do before do first_status = PostStatusService.new.call(user.account, text: 'Test') ReblogService.new.call(bob.account, first_status) - mentioning_status = PostStatusService.new.call(bob.account, text: 'Hello @alice') - mentioning_status.mentions.first + PostStatusService.new.call(bob.account, text: 'Hello @alice') + PostStatusService.new.call(tom.account, text: 'Hello @alice', visibility: :direct) # Filtered by default FavouriteService.new.call(bob.account, first_status) FavouriteService.new.call(tom.account, first_status) FollowService.new.call(bob.account, user.account) @@ -34,10 +34,22 @@ RSpec.describe 'Notifications' do subject expect(response).to have_http_status(200) - expect(body_json_types).to include 'reblog' - expect(body_json_types).to include 'mention' - expect(body_json_types).to include 'favourite' - expect(body_json_types).to include 'follow' + expect(body_as_json.size).to eq 5 + expect(body_json_types).to include('reblog', 'mention', 'favourite', 'follow') + expect(body_as_json.any? { |x| x[:filtered] }).to be false + end + end + + context 'with include_filtered' do + let(:params) { { include_filtered: true } } + + it 'returns expected notification types, including filtered notifications' do + subject + + expect(response).to have_http_status(200) + expect(body_as_json.size).to eq 6 + expect(body_json_types).to include('reblog', 'mention', 'favourite', 'follow') + expect(body_as_json.any? { |x| x[:filtered] }).to be true end end @@ -96,7 +108,7 @@ RSpec.describe 'Notifications' do it 'returns the requested number of notifications paginated', :aggregate_failures do subject - notifications = user.account.notifications + notifications = user.account.notifications.browserable expect(body_as_json.size) .to eq(params[:limit]) diff --git a/spec/requests/api/v1/polls/votes_spec.rb b/spec/requests/api/v1/polls/votes_spec.rb index e2b22708be..669f64b6e4 100644 --- a/spec/requests/api/v1/polls/votes_spec.rb +++ b/spec/requests/api/v1/polls/votes_spec.rb @@ -10,9 +10,10 @@ RSpec.describe 'API V1 Polls Votes' do describe 'POST /api/v1/polls/:poll_id/votes' do let(:poll) { Fabricate(:poll) } + let(:params) { { choices: %w(1) } } before do - post "/api/v1/polls/#{poll.id}/votes", params: { choices: %w(1) }, headers: headers + post "/api/v1/polls/#{poll.id}/votes", params: params, headers: headers end it 'creates a vote', :aggregate_failures do @@ -24,6 +25,14 @@ RSpec.describe 'API V1 Polls Votes' do expect(poll.reload.cached_tallies).to eq [0, 1] end + context 'when the required choices param is not provided' do + let(:params) { {} } + + it 'returns http bad request' do + expect(response).to have_http_status(400) + end + end + private def vote diff --git a/spec/requests/api/v1/reports_spec.rb b/spec/requests/api/v1/reports_spec.rb index 9e8954a4c6..491c6263d3 100644 --- a/spec/requests/api/v1/reports_spec.rb +++ b/spec/requests/api/v1/reports_spec.rb @@ -33,7 +33,7 @@ RSpec.describe 'Reports' do it_behaves_like 'forbidden for wrong scope', 'read read:reports' - it 'creates a report', :aggregate_failures, :sidekiq_inline do + it 'creates a report', :aggregate_failures, :inline_jobs do emails = capture_emails { subject } expect(response).to have_http_status(200) diff --git a/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb b/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb index 44296f4c37..2fd79f424b 100644 --- a/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb +++ b/spec/requests/api/v1/statuses/favourited_by_accounts_spec.rb @@ -29,8 +29,10 @@ RSpec.describe 'API V1 Statuses Favourited by Accounts' do expect(response) .to have_http_status(200) - expect(response.headers['Link'].links.size) - .to eq(2) + .and include_pagination_headers( + prev: api_v1_status_favourited_by_index_url(limit: 2, since_id: Favourite.last.id), + next: api_v1_status_favourited_by_index_url(limit: 2, max_id: Favourite.first.id) + ) expect(body_as_json.size) .to eq(2) diff --git a/spec/requests/api/v1/statuses/favourites_spec.rb b/spec/requests/api/v1/statuses/favourites_spec.rb index 033aed7e28..22d0e4831f 100644 --- a/spec/requests/api/v1/statuses/favourites_spec.rb +++ b/spec/requests/api/v1/statuses/favourites_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -RSpec.describe 'Favourites', :sidekiq_inline do +RSpec.describe 'Favourites', :inline_jobs do let(:user) { Fabricate(:user) } let(:scopes) { 'write:favourites' } let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } diff --git a/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb b/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb index 6f99ce9464..5fc54042f9 100644 --- a/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb +++ b/spec/requests/api/v1/statuses/reblogged_by_accounts_spec.rb @@ -28,8 +28,10 @@ RSpec.describe 'API V1 Statuses Reblogged by Accounts' do expect(response) .to have_http_status(200) - expect(response.headers['Link'].links.size) - .to eq(2) + .and include_pagination_headers( + prev: api_v1_status_reblogged_by_index_url(limit: 2, since_id: bob.statuses.first.id), + next: api_v1_status_reblogged_by_index_url(limit: 2, max_id: alice.statuses.first.id) + ) expect(body_as_json.size) .to eq(2) diff --git a/spec/requests/api/v1/statuses/reblogs_spec.rb b/spec/requests/api/v1/statuses/reblogs_spec.rb index cf0a1f861d..503d804ed0 100644 --- a/spec/requests/api/v1/statuses/reblogs_spec.rb +++ b/spec/requests/api/v1/statuses/reblogs_spec.rb @@ -41,7 +41,7 @@ describe 'API V1 Statuses Reblogs' do end end - describe 'POST /api/v1/statuses/:status_id/unreblog', :sidekiq_inline do + describe 'POST /api/v1/statuses/:status_id/unreblog', :inline_jobs do context 'with public status' do let(:status) { Fabricate(:status, account: user.account) } diff --git a/spec/requests/api/v1/timelines/home_spec.rb b/spec/requests/api/v1/timelines/home_spec.rb index 2bebe8cf45..96bd153aff 100644 --- a/spec/requests/api/v1/timelines/home_spec.rb +++ b/spec/requests/api/v1/timelines/home_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -describe 'Home', :sidekiq_inline do +describe 'Home', :inline_jobs do let(:user) { Fabricate(:user) } let(:scopes) { 'read:statuses' } let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } diff --git a/spec/requests/api/v2/admin/accounts_spec.rb b/spec/requests/api/v2/admin/accounts_spec.rb index f5db93233c..8f52c6a613 100644 --- a/spec/requests/api/v2/admin/accounts_spec.rb +++ b/spec/requests/api/v2/admin/accounts_spec.rb @@ -83,7 +83,8 @@ RSpec.describe 'API V2 Admin Accounts' do let(:params) { { limit: 1 } } it 'sets the correct pagination headers' do - expect(response.headers['Link'].find_link(%w(rel next)).href).to eq api_v2_admin_accounts_url(limit: 1, max_id: admin_account.id) + expect(response) + .to include_pagination_headers(next: api_v2_admin_accounts_url(limit: 1, max_id: admin_account.id)) end end end diff --git a/spec/requests/api/v2/media_spec.rb b/spec/requests/api/v2/media_spec.rb index 990fa5d0ba..97540413f1 100644 --- a/spec/requests/api/v2/media_spec.rb +++ b/spec/requests/api/v2/media_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -RSpec.describe 'Media API', :paperclip_processing do +RSpec.describe 'Media API', :attachment_processing do let(:user) { Fabricate(:user) } let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) } let(:scopes) { 'write' } diff --git a/spec/requests/api/v2_alpha/notifications_spec.rb b/spec/requests/api/v2_alpha/notifications_spec.rb index ac44605ac5..104651ebe3 100644 --- a/spec/requests/api/v2_alpha/notifications_spec.rb +++ b/spec/requests/api/v2_alpha/notifications_spec.rb @@ -8,7 +8,7 @@ RSpec.describe 'Notifications' do let(:scopes) { 'read:notifications write:notifications' } let(:headers) { { 'Authorization' => "Bearer #{token.token}" } } - describe 'GET /api/v2_alpha/notifications', :sidekiq_inline do + describe 'GET /api/v2_alpha/notifications', :inline_jobs do subject do get '/api/v2_alpha/notifications', headers: headers, params: params end diff --git a/spec/search/models/concerns/account/statuses_search_spec.rb b/spec/search/models/concerns/account/statuses_search_spec.rb index a1b0bf405c..b1bf4968ca 100644 --- a/spec/search/models/concerns/account/statuses_search_spec.rb +++ b/spec/search/models/concerns/account/statuses_search_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -describe Account::StatusesSearch, :sidekiq_inline do +describe Account::StatusesSearch, :inline_jobs do describe 'a non-indexable account becoming indexable' do let(:account) { Account.find_by(username: 'search_test_account_1') } diff --git a/spec/services/activate_remote_statuses_service_spec.rb b/spec/services/activate_remote_statuses_service_spec.rb index 73b23159ed..e42e1a7346 100644 --- a/spec/services/activate_remote_statuses_service_spec.rb +++ b/spec/services/activate_remote_statuses_service_spec.rb @@ -36,7 +36,7 @@ RSpec.describe ActivateRemoteStatusesService, type: :service do subject end - it 'original status is fetched', :sidekiq_inline do + it 'original status is fetched', :inline_jobs do status = sender.statuses.first expect(status).to_not be_nil @@ -54,7 +54,7 @@ RSpec.describe ActivateRemoteStatusesService, type: :service do subject end - it 'original status is not fetched', :sidekiq_inline do + it 'original status is not fetched', :inline_jobs do status = sender.statuses.first expect(status).to be_nil diff --git a/spec/services/activitypub/fetch_remote_status_service_spec.rb b/spec/services/activitypub/fetch_remote_status_service_spec.rb index a86f141fe0..c3adb9c470 100644 --- a/spec/services/activitypub/fetch_remote_status_service_spec.rb +++ b/spec/services/activitypub/fetch_remote_status_service_spec.rb @@ -225,7 +225,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do end end - context 'with statuses referencing other statuses', :sidekiq_inline do + context 'with statuses referencing other statuses', :inline_jobs do before do stub_const 'ActivityPub::FetchRemoteStatusService::DISCOVERIES_PER_REQUEST', 5 end diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb index f801227f57..5f6822185c 100644 --- a/spec/services/activitypub/process_account_service_spec.rb +++ b/spec/services/activitypub/process_account_service_spec.rb @@ -611,7 +611,7 @@ RSpec.describe ActivityPub::ProcessAccountService do end end - it 'creates accounts without exceeding rate limit', :sidekiq_inline do + it 'creates accounts without exceeding rate limit', :inline_jobs do expect { subject.call('user1', 'foo.test', payload) } .to create_some_remote_accounts .and create_fewer_than_rate_limit_accounts diff --git a/spec/services/appeal_service_spec.rb b/spec/services/appeal_service_spec.rb index 3fad74db9d..6a47bb2cea 100644 --- a/spec/services/appeal_service_spec.rb +++ b/spec/services/appeal_service_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -RSpec.describe AppealService, :sidekiq_inline do +RSpec.describe AppealService, :inline_jobs do describe '#call' do let!(:admin) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } diff --git a/spec/services/authorize_follow_service_spec.rb b/spec/services/authorize_follow_service_spec.rb index be2a864185..533b791fb7 100644 --- a/spec/services/authorize_follow_service_spec.rb +++ b/spec/services/authorize_follow_service_spec.rb @@ -41,7 +41,7 @@ RSpec.describe AuthorizeFollowService do expect(bob.following?(sender)).to be true end - it 'sends an accept activity', :sidekiq_inline do + it 'sends an accept activity', :inline_jobs do expect(a_request(:post, bob.inbox_url)).to have_been_made.once end end diff --git a/spec/services/batched_remove_status_service_spec.rb b/spec/services/batched_remove_status_service_spec.rb index e501b9ba84..628bb198ef 100644 --- a/spec/services/batched_remove_status_service_spec.rb +++ b/spec/services/batched_remove_status_service_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -RSpec.describe BatchedRemoveStatusService, :sidekiq_inline do +RSpec.describe BatchedRemoveStatusService, :inline_jobs do subject { described_class.new } let!(:alice) { Fabricate(:account) } diff --git a/spec/services/block_domain_service_spec.rb b/spec/services/block_domain_service_spec.rb index 379c8b0911..1e0d55147c 100644 --- a/spec/services/block_domain_service_spec.rb +++ b/spec/services/block_domain_service_spec.rb @@ -70,7 +70,7 @@ RSpec.describe BlockDomainService do end describe 'for a silence with reject media' do - it 'does not mark the domain as blocked, but silences accounts with an appropriate silencing date, clears media', :aggregate_failures, :sidekiq_inline do + it 'does not mark the domain as blocked, but silences accounts with an appropriate silencing date, clears media', :aggregate_failures, :inline_jobs do subject.call(DomainBlock.create!(domain: 'evil.org', severity: :silence, reject_media: true)) expect(DomainBlock.blocked?('evil.org')).to be false diff --git a/spec/services/block_service_spec.rb b/spec/services/block_service_spec.rb index d096aa1ea3..46dd691986 100644 --- a/spec/services/block_service_spec.rb +++ b/spec/services/block_service_spec.rb @@ -33,7 +33,7 @@ RSpec.describe BlockService do expect(sender.blocking?(bob)).to be true end - it 'sends a block activity', :sidekiq_inline do + it 'sends a block activity', :inline_jobs do expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once end end diff --git a/spec/services/delete_account_service_spec.rb b/spec/services/delete_account_service_spec.rb index e9226f3e04..9055dc8819 100644 --- a/spec/services/delete_account_service_spec.rb +++ b/spec/services/delete_account_service_spec.rb @@ -119,7 +119,7 @@ RSpec.describe DeleteAccountService do end end - describe '#call on local account', :sidekiq_inline do + describe '#call on local account', :inline_jobs do before do stub_request(:post, remote_alice.inbox_url).to_return(status: 201) stub_request(:post, remote_bob.inbox_url).to_return(status: 201) @@ -140,7 +140,7 @@ RSpec.describe DeleteAccountService do end end - describe '#call on remote account', :sidekiq_inline do + describe '#call on remote account', :inline_jobs do before do stub_request(:post, account.inbox_url).to_return(status: 201) end diff --git a/spec/services/delivery_antenna_service_spec.rb b/spec/services/delivery_antenna_service_spec.rb index 83546ccbfe..17cc832d43 100644 --- a/spec/services/delivery_antenna_service_spec.rb +++ b/spec/services/delivery_antenna_service_spec.rb @@ -88,11 +88,11 @@ RSpec.describe DeliveryAntennaService, type: :service do let!(:antenna) { antenna_with_account(bob, alice) } let!(:empty_antenna) { antenna_with_account(tom, bob) } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -100,7 +100,7 @@ RSpec.describe DeliveryAntennaService, type: :service do context 'when blocked' do let!(:empty_antenna) { antenna_with_account(ohagi, alice) } - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -109,7 +109,7 @@ RSpec.describe DeliveryAntennaService, type: :service do let(:last_active_at_tom) { Time.now.utc.ago(1.year) } let!(:empty_antenna) { antenna_with_account(tom, alice) } - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -119,11 +119,11 @@ RSpec.describe DeliveryAntennaService, type: :service do let!(:antenna) { antenna_with_domain(bob, 'fast.example.com') } let!(:empty_antenna) { antenna_with_domain(tom, 'ohagi.example.com') } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -133,18 +133,18 @@ RSpec.describe DeliveryAntennaService, type: :service do let!(:antenna) { antenna_with_domain(bob, 'cb6e6126.ngrok.io') } let!(:empty_antenna) { antenna_with_domain(tom, 'ohagi.example.com') } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end context 'when local timeline is disabled' do let(:ltl_enabled) { false } - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to_not include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -155,11 +155,11 @@ RSpec.describe DeliveryAntennaService, type: :service do let!(:antenna) { antenna_with_tag(bob, 'hoge') } let!(:empty_antenna) { antenna_with_tag(tom, 'hog') } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -168,11 +168,11 @@ RSpec.describe DeliveryAntennaService, type: :service do let!(:antenna) { antenna_with_keyword(bob, 'body') } let!(:empty_antenna) { antenna_with_keyword(tom, 'anime') } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -182,11 +182,11 @@ RSpec.describe DeliveryAntennaService, type: :service do let!(:antenna) { antenna_with_keyword(bob, 'some') } let!(:empty_antenna) { antenna_with_keyword(tom, 'anime') } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -196,11 +196,11 @@ RSpec.describe DeliveryAntennaService, type: :service do let!(:antenna) { antenna_with_keyword(bob, 'body') } let!(:empty_antenna) { antenna_with_keyword(tom, 'anime') } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -210,11 +210,11 @@ RSpec.describe DeliveryAntennaService, type: :service do let!(:antenna) { antenna_with_domain(bob, 'fast.example.com', exclude_accounts: [tom.id]) } let!(:empty_antenna) { antenna_with_domain(tom, 'fast.example.com', exclude_accounts: [alice.id]) } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -224,11 +224,11 @@ RSpec.describe DeliveryAntennaService, type: :service do let!(:antenna) { antenna_with_domain(bob, 'fast.example.com', exclude_keywords: ['aaa']) } let!(:empty_antenna) { antenna_with_domain(tom, 'fast.example.com', exclude_keywords: ['body']) } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -238,11 +238,11 @@ RSpec.describe DeliveryAntennaService, type: :service do let!(:antenna) { antenna_with_domain(bob, 'fast.example.com') } let!(:empty_antenna) { antenna_with_domain(tom, 'fast.example.com', exclude_tags: [Tag.find_or_create_by_names(['hoge']).first.id]) } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -252,11 +252,11 @@ RSpec.describe DeliveryAntennaService, type: :service do let!(:antenna) { antenna_with_keyword(bob, 'body', exclude_domains: ['ohagi.example.com']) } let!(:empty_antenna) { antenna_with_keyword(tom, 'body', exclude_domains: ['fast.example.com']) } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -265,7 +265,7 @@ RSpec.describe DeliveryAntennaService, type: :service do let!(:antenna) { antenna_with_keyword(bob, 'body') } let!(:empty_antenna) { antenna_with_keyword(tom, 'body') } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to include status.id end @@ -276,7 +276,7 @@ RSpec.describe DeliveryAntennaService, type: :service do let!(:empty_antenna) { antenna_with_keyword(tom, 'body') } [1, 2, 3, 4, 5].each do |_| - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to include status.id end @@ -287,7 +287,7 @@ RSpec.describe DeliveryAntennaService, type: :service do let!(:antenna) { antenna_with_keyword(bob, 'body', insert_feeds: true) } let!(:empty_antenna) { antenna_with_keyword(tom, 'body', insert_feeds: true) } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(home_feed_of(bob)).to include status.id expect(antenna_feed_of(empty_antenna)).to include status.id @@ -299,7 +299,7 @@ RSpec.describe DeliveryAntennaService, type: :service do let!(:antenna) { antenna_with_keyword(bob, 'body', insert_feeds: true, list: list(bob)) } let!(:empty_antenna) { antenna_with_keyword(tom, 'body', insert_feeds: true, list: list(tom)) } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(list_feed_of(antenna.list)).to include status.id expect(antenna_feed_of(empty_antenna)).to include status.id @@ -313,11 +313,11 @@ RSpec.describe DeliveryAntennaService, type: :service do let(:visibility) { :unlisted } context 'when public searchability' do - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -325,11 +325,11 @@ RSpec.describe DeliveryAntennaService, type: :service do context 'when public_unlisted searchability' do let(:searchability) { :public_unlisted } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -337,7 +337,7 @@ RSpec.describe DeliveryAntennaService, type: :service do context 'when private searchability' do let(:searchability) { :private } - it 'not detecting antenna', :sidekiq_inline do + it 'not detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to_not include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -350,7 +350,7 @@ RSpec.describe DeliveryAntennaService, type: :service do let(:visibility) { :unlisted } context 'when public searchability' do - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to include status.id end @@ -359,7 +359,7 @@ RSpec.describe DeliveryAntennaService, type: :service do context 'when public_unlisted searchability' do let(:searchability) { :public_unlisted } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to include status.id end @@ -368,7 +368,7 @@ RSpec.describe DeliveryAntennaService, type: :service do context 'when private searchability' do let(:searchability) { :private } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to include status.id end @@ -379,7 +379,7 @@ RSpec.describe DeliveryAntennaService, type: :service do let(:mode) { :stl } let!(:antenna) { antenna_with_keyword(bob, 'anime', stl: true) } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end end @@ -388,7 +388,7 @@ RSpec.describe DeliveryAntennaService, type: :service do let(:mode) { :ltl } let!(:antenna) { antenna_with_keyword(bob, 'anime', ltl: true) } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end end @@ -397,7 +397,7 @@ RSpec.describe DeliveryAntennaService, type: :service do let(:mode) { :stl } let!(:antenna) { antenna_with_keyword(bob, 'anime', exclude_keywords: ['body'], stl: true) } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end end @@ -406,7 +406,7 @@ RSpec.describe DeliveryAntennaService, type: :service do let(:mode) { :ltl } let!(:antenna) { antenna_with_keyword(bob, 'anime', exclude_keywords: ['body'], ltl: true) } - it 'detecting antenna', :sidekiq_inline do + it 'detecting antenna', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end end diff --git a/spec/services/emoji_react_service_spec.rb b/spec/services/emoji_react_service_spec.rb index cf0f6f5957..5ff4d80c3f 100644 --- a/spec/services/emoji_react_service_spec.rb +++ b/spec/services/emoji_react_service_spec.rb @@ -218,7 +218,7 @@ RSpec.describe EmojiReactService, type: :service do stub_request(:post, 'https://author.foo.bar/inbox') end - it 'react with emoji', :sidekiq_inline do + it 'react with emoji', :inline_jobs do expect(subject.count).to eq 1 expect(a_request(:post, 'https://author.foo.bar/inbox').with(body: hash_including({ type: 'Like', @@ -235,7 +235,7 @@ RSpec.describe EmojiReactService, type: :service do stub_request(:post, 'https://foo.bar/inbox') end - it 'react with emoji', :sidekiq_inline do + it 'react with emoji', :inline_jobs do expect(subject.count).to eq 1 expect(a_request(:post, 'https://foo.bar/inbox').with(body: hash_including({ type: 'Like', @@ -254,7 +254,7 @@ RSpec.describe EmojiReactService, type: :service do stub_request(:post, 'https://foo.bar/inbox') end - it 'react with emoji', :sidekiq_inline do + it 'react with emoji', :inline_jobs do expect(subject.count).to eq 1 expect(a_request(:post, 'https://foo.bar/inbox').with(body: hash_including({ type: 'Like', @@ -270,7 +270,7 @@ RSpec.describe EmojiReactService, type: :service do stub_request(:post, 'https://foo.bar/inbox') end - it 'react with emoji', :sidekiq_inline do + it 'react with emoji', :inline_jobs do expect(subject.count).to eq 1 expect(a_request(:post, 'https://foo.bar/inbox').with(body: hash_including({ type: 'Like', @@ -286,7 +286,7 @@ RSpec.describe EmojiReactService, type: :service do stub_request(:post, 'https://foo.bar/inbox') end - it 'react with emoji', :sidekiq_inline do + it 'react with emoji', :inline_jobs do expect(subject.count).to eq 1 expect(a_request(:post, 'https://foo.bar/inbox').with(body: hash_including({ type: 'Like', diff --git a/spec/services/fan_out_on_write_service_spec.rb b/spec/services/fan_out_on_write_service_spec.rb index 39f318aac1..de20af9317 100644 --- a/spec/services/fan_out_on_write_service_spec.rb +++ b/spec/services/fan_out_on_write_service_spec.rb @@ -85,43 +85,43 @@ RSpec.describe FanOutOnWriteService do context 'when status is public' do let(:visibility) { 'public' } - it 'is added to the home feed of its author', :sidekiq_inline do + it 'is added to the home feed of its author', :inline_jobs do expect(home_feed_of(alice)).to include status.id end - it 'is added to the home feed of the mentioned follower', :sidekiq_inline do + it 'is added to the home feed of the mentioned follower', :inline_jobs do expect(home_feed_of(bob)).to include status.id end - it 'is added to the home feed of a follower', :sidekiq_inline do + it 'is added to the home feed of a follower', :inline_jobs do expect(home_feed_of(bob)).to include status.id expect(home_feed_of(tom)).to include status.id end - it 'is added to the tag follower', :sidekiq_inline do + it 'is added to the tag follower', :inline_jobs do expect(home_feed_of(tagf)).to include status.id end - it 'is broadcast to the hashtag stream', :sidekiq_inline do + it 'is broadcast to the hashtag stream', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything) expect(redis).to have_received(:publish).with('timeline:hashtag:hoge:local', anything) end - it 'is broadcast to the public stream', :sidekiq_inline do + it 'is broadcast to the public stream', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:public', anything) expect(redis).to have_received(:publish).with('timeline:public:local', anything) expect(redis).to have_received(:publish).with('timeline:public:media', anything) end - context 'when local timeline is disabled', :sidekiq_inline do + context 'when local timeline is disabled', :inline_jobs do let(:ltl_enabled) { false } - it 'is broadcast to the hashtag stream', :sidekiq_inline do + it 'is broadcast to the hashtag stream', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything) expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge:local', anything) end - it 'is broadcast to the public stream', :sidekiq_inline do + it 'is broadcast to the public stream', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:public', anything) expect(redis).to_not have_received(:publish).with('timeline:public:local', anything) end @@ -131,7 +131,7 @@ RSpec.describe FanOutOnWriteService do let!(:list) { list_with_account(bob, alice) } let!(:empty_list) { Fabricate(:list, account: tom) } - it 'is added to the list feed of list follower', :sidekiq_inline do + it 'is added to the list feed of list follower', :inline_jobs do expect(list_feed_of(list)).to include status.id expect(list_feed_of(empty_list)).to_not include status.id end @@ -141,7 +141,7 @@ RSpec.describe FanOutOnWriteService do let!(:antenna) { antenna_with_account(bob, alice) } let!(:empty_antenna) { antenna_with_account(tom, bob) } - it 'is added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -149,7 +149,7 @@ RSpec.describe FanOutOnWriteService do context 'when subscription is blocked' do let(:subscription_policy) { :block } - it 'is not added to the antenna feed', :sidekiq_inline do + it 'is not added to the antenna feed', :inline_jobs do expect(antenna_feed_of(antenna)).to_not include status.id end end @@ -158,14 +158,14 @@ RSpec.describe FanOutOnWriteService do let(:subscription_policy) { :followers_only } let!(:antenna) { antenna_with_account(ohagi, alice) } - it 'is not added to the antenna feed', :sidekiq_inline do + it 'is not added to the antenna feed', :inline_jobs do expect(antenna_feed_of(antenna)).to_not include status.id end context 'with following' do let!(:antenna) { antenna_with_account(bob, alice) } - it 'is added to the antenna feed', :sidekiq_inline do + it 'is added to the antenna feed', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end end @@ -181,7 +181,7 @@ RSpec.describe FanOutOnWriteService do end context 'with listening tag' do - it 'is added to the antenna feed', :sidekiq_inline do + it 'is added to the antenna feed', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end end @@ -189,7 +189,7 @@ RSpec.describe FanOutOnWriteService do context 'with listening tag but sender is limiting subscription' do let(:subscription_policy) { :block } - it 'does not add to the antenna feed', :sidekiq_inline do + it 'does not add to the antenna feed', :inline_jobs do expect(antenna_feed_of(antenna)).to_not include status.id end end @@ -204,7 +204,7 @@ RSpec.describe FanOutOnWriteService do subject.call(status) end - it 'is added to the antenna feed', :sidekiq_inline do + it 'is added to the antenna feed', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end end @@ -215,7 +215,7 @@ RSpec.describe FanOutOnWriteService do let!(:antenna) { antenna_with_options(bob, stl: true) } let!(:empty_antenna) { antenna_with_options(tom) } - it 'is added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -223,7 +223,7 @@ RSpec.describe FanOutOnWriteService do context 'when subscription is blocked' do let(:subscription_policy) { :block } - it 'is added to the antenna feed', :sidekiq_inline do + it 'is added to the antenna feed', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end end @@ -242,7 +242,7 @@ RSpec.describe FanOutOnWriteService do let!(:antenna) { antenna_with_options(bob, ltl: true) } let!(:empty_antenna) { antenna_with_options(tom) } - it 'is added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -250,7 +250,7 @@ RSpec.describe FanOutOnWriteService do context 'when subscription is blocked' do let(:subscription_policy) { :block } - it 'is added to the antenna feed', :sidekiq_inline do + it 'is added to the antenna feed', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end end @@ -258,7 +258,7 @@ RSpec.describe FanOutOnWriteService do context 'when local timeline is disabled' do let(:ltl_enabled) { false } - it 'is not added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is not added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(antenna)).to_not include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -286,23 +286,23 @@ RSpec.describe FanOutOnWriteService do context 'when status is limited' do let(:visibility) { 'limited' } - it 'is added to the home feed of its author', :sidekiq_inline do + it 'is added to the home feed of its author', :inline_jobs do expect(home_feed_of(alice)).to include status.id end - it 'is added to the home feed of the mentioned follower', :sidekiq_inline do + it 'is added to the home feed of the mentioned follower', :inline_jobs do expect(home_feed_of(bob)).to include status.id end - it 'is not added to the home feed of the other follower', :sidekiq_inline do + it 'is not added to the home feed of the other follower', :inline_jobs do expect(home_feed_of(tom)).to_not include status.id end - it 'is not added to the tag follower', :sidekiq_inline do + it 'is not added to the tag follower', :inline_jobs do expect(home_feed_of(tagf)).to_not include status.id end - it 'is not broadcast publicly', :sidekiq_inline do + it 'is not broadcast publicly', :inline_jobs 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 @@ -311,7 +311,7 @@ RSpec.describe FanOutOnWriteService do let!(:list) { list_with_account(bob, alice) } let!(:empty_list) { list_with_account(tom, alice) } - it 'is added to the list feed of list follower', :sidekiq_inline do + it 'is added to the list feed of list follower', :inline_jobs do expect(list_feed_of(list)).to include status.id expect(list_feed_of(empty_list)).to_not include status.id end @@ -321,7 +321,7 @@ RSpec.describe FanOutOnWriteService do let!(:antenna) { antenna_with_account(bob, alice) } let!(:empty_antenna) { antenna_with_account(tom, alice) } - it 'is added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -331,7 +331,7 @@ RSpec.describe FanOutOnWriteService do let!(:antenna) { antenna_with_options(bob, stl: true) } let!(:empty_antenna) { antenna_with_options(tom, stl: true) } - it 'is added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -340,7 +340,7 @@ RSpec.describe FanOutOnWriteService do context 'with LTL antenna' do let!(:empty_antenna) { antenna_with_options(bob, ltl: true) } - it 'is added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -349,25 +349,25 @@ RSpec.describe FanOutOnWriteService do context 'when status is private' do let(:visibility) { 'private' } - it 'is added to the home feed of its author', :sidekiq_inline do + it 'is added to the home feed of its author', :inline_jobs do expect(home_feed_of(alice)).to include status.id end - it 'is added to the home feed of a follower', :sidekiq_inline do + it 'is added to the home feed of a follower', :inline_jobs do expect(home_feed_of(bob)).to include status.id expect(home_feed_of(tom)).to include status.id end - it 'is not added to the tag follower', :sidekiq_inline do + it 'is not added to the tag follower', :inline_jobs do expect(home_feed_of(tagf)).to_not include status.id end - it 'is not broadcast publicly', :sidekiq_inline do + it 'is not broadcast publicly', :inline_jobs 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 - it 'is added to the home feed of the mentioned follower', :sidekiq_inline do + it 'is added to the home feed of the mentioned follower', :inline_jobs do expect(home_feed_of(bob)).to include status.id end @@ -375,7 +375,7 @@ RSpec.describe FanOutOnWriteService do let!(:list) { list_with_account(bob, alice) } let!(:empty_list) { list_with_account(ohagi, bob) } - it 'is added to the list feed of list follower', :sidekiq_inline do + it 'is added to the list feed of list follower', :inline_jobs do expect(list_feed_of(list)).to include status.id expect(list_feed_of(empty_list)).to_not include status.id end @@ -385,7 +385,7 @@ RSpec.describe FanOutOnWriteService do let!(:antenna) { antenna_with_account(bob, alice) } let!(:empty_antenna) { antenna_with_account(ohagi, alice) } - it 'is added to the list feed of list follower', :sidekiq_inline do + it 'is added to the list feed of list follower', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -395,7 +395,7 @@ RSpec.describe FanOutOnWriteService do let!(:antenna) { antenna_with_options(bob, stl: true) } let!(:empty_antenna) { antenna_with_options(ohagi, stl: true) } - it 'is added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -403,7 +403,7 @@ RSpec.describe FanOutOnWriteService do context 'when local timeline is disabled' do let(:ltl_enabled) { false } - it 'is not added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is not added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(antenna)).to_not include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -413,14 +413,14 @@ RSpec.describe FanOutOnWriteService do context 'with LTL antenna' do let!(:empty_antenna) { antenna_with_options(bob, ltl: true) } - it 'is added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end context 'when local timeline is disabled' do let(:ltl_enabled) { false } - it 'is not added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is not added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -430,20 +430,20 @@ RSpec.describe FanOutOnWriteService do context 'when status is public_unlisted' do let(:visibility) { 'public_unlisted' } - it 'is added to the home feed of its author', :sidekiq_inline do + it 'is added to the home feed of its author', :inline_jobs do expect(home_feed_of(alice)).to include status.id end - it 'is added to the home feed of a follower', :sidekiq_inline do + it 'is added to the home feed of a follower', :inline_jobs do expect(home_feed_of(bob)).to include status.id expect(home_feed_of(tom)).to include status.id end - it 'is added to the tag follower', :sidekiq_inline do + it 'is added to the tag follower', :inline_jobs do expect(home_feed_of(tagf)).to include status.id end - it 'is broadcast publicly', :sidekiq_inline do + it 'is broadcast publicly', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything) expect(redis).to have_received(:publish).with('timeline:public:local', anything) expect(redis).to have_received(:publish).with('timeline:public', anything) @@ -452,12 +452,12 @@ RSpec.describe FanOutOnWriteService do context 'when local timeline is disabled' do let(:ltl_enabled) { false } - it 'is broadcast to the hashtag stream', :sidekiq_inline do + it 'is broadcast to the hashtag stream', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything) expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge:local', anything) end - it 'is broadcast to the public stream', :sidekiq_inline do + it 'is broadcast to the public stream', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:public', anything) expect(redis).to_not have_received(:publish).with('timeline:public:local', anything) end @@ -467,7 +467,7 @@ RSpec.describe FanOutOnWriteService do let!(:list) { list_with_account(bob, alice) } let!(:empty_list) { list_with_account(ohagi, bob) } - it 'is added to the list feed of list follower', :sidekiq_inline do + it 'is added to the list feed of list follower', :inline_jobs do expect(list_feed_of(list)).to include status.id expect(list_feed_of(empty_list)).to_not include status.id end @@ -477,7 +477,7 @@ RSpec.describe FanOutOnWriteService do let!(:antenna) { antenna_with_account(bob, alice) } let!(:empty_antenna) { antenna_with_account(tom, bob) } - it 'is added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -485,7 +485,7 @@ RSpec.describe FanOutOnWriteService do context 'when subscription is blocked' do let(:subscription_policy) { :block } - it 'is not added to the antenna feed', :sidekiq_inline do + it 'is not added to the antenna feed', :inline_jobs do expect(antenna_feed_of(antenna)).to_not include status.id end end @@ -495,7 +495,7 @@ RSpec.describe FanOutOnWriteService do let!(:antenna) { antenna_with_options(bob, stl: true) } let!(:empty_antenna) { antenna_with_options(tom) } - it 'is added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -503,7 +503,7 @@ RSpec.describe FanOutOnWriteService do context 'when subscription is blocked' do let(:subscription_policy) { :block } - it 'is added to the antenna feed', :sidekiq_inline do + it 'is added to the antenna feed', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end end @@ -511,7 +511,7 @@ RSpec.describe FanOutOnWriteService do context 'when local timeline is disabled' do let(:ltl_enabled) { false } - it 'is not added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is not added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(antenna)).to_not include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -522,7 +522,7 @@ RSpec.describe FanOutOnWriteService do let!(:antenna) { antenna_with_options(bob, ltl: true) } let!(:empty_antenna) { antenna_with_options(tom) } - it 'is added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -530,7 +530,7 @@ RSpec.describe FanOutOnWriteService do context 'when subscription is blocked' do let(:subscription_policy) { :block } - it 'is added to the antenna feed', :sidekiq_inline do + it 'is added to the antenna feed', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id end end @@ -538,7 +538,7 @@ RSpec.describe FanOutOnWriteService do context 'when local timeline is disabled' do let(:ltl_enabled) { false } - it 'is not added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is not added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(antenna)).to_not include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -549,20 +549,20 @@ RSpec.describe FanOutOnWriteService do context 'when status is unlisted' do let(:visibility) { 'unlisted' } - it 'is added to the home feed of its author', :sidekiq_inline do + it 'is added to the home feed of its author', :inline_jobs do expect(home_feed_of(alice)).to include status.id end - it 'is added to the home feed of a follower', :sidekiq_inline do + it 'is added to the home feed of a follower', :inline_jobs do expect(home_feed_of(bob)).to include status.id expect(home_feed_of(tom)).to include status.id end - it 'is added to the tag follower', :sidekiq_inline do + it 'is added to the tag follower', :inline_jobs do expect(home_feed_of(tagf)).to include status.id end - it 'is not broadcast publicly', :sidekiq_inline do + it 'is not broadcast publicly', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything) expect(redis).to_not have_received(:publish).with('timeline:public', anything) end @@ -570,12 +570,12 @@ RSpec.describe FanOutOnWriteService do context 'with searchability public_unlisted' do let(:searchability) { 'public_unlisted' } - it 'is broadcast to the hashtag stream', :sidekiq_inline do + it 'is broadcast to the hashtag stream', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything) expect(redis).to have_received(:publish).with('timeline:hashtag:hoge:local', anything) end - it 'is added to the tag follower', :sidekiq_inline do + it 'is added to the tag follower', :inline_jobs do expect(home_feed_of(tagf)).to include status.id end end @@ -583,12 +583,12 @@ RSpec.describe FanOutOnWriteService do context 'with searchability private' do let(:searchability) { 'private' } - it 'is not broadcast to the hashtag stream', :sidekiq_inline do + it 'is not broadcast to the hashtag stream', :inline_jobs do expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge', anything) expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge:local', anything) end - it 'is not added to the tag follower', :sidekiq_inline do + it 'is not added to the tag follower', :inline_jobs do expect(home_feed_of(tagf)).to_not include status.id end end @@ -596,7 +596,7 @@ RSpec.describe FanOutOnWriteService do context 'when local timeline is disabled' do let(:ltl_enabled) { false } - it 'is broadcast to the hashtag stream', :sidekiq_inline do + it 'is broadcast to the hashtag stream', :inline_jobs do expect(redis).to have_received(:publish).with('timeline:hashtag:hoge', anything) expect(redis).to_not have_received(:publish).with('timeline:hashtag:hoge:local', anything) end @@ -606,7 +606,7 @@ RSpec.describe FanOutOnWriteService do let!(:list) { list_with_account(bob, alice) } let!(:empty_list) { list_with_account(ohagi, bob) } - it 'is added to the list feed of list follower', :sidekiq_inline do + it 'is added to the list feed of list follower', :inline_jobs do expect(list_feed_of(list)).to include status.id expect(list_feed_of(empty_list)).to_not include status.id end @@ -616,7 +616,7 @@ RSpec.describe FanOutOnWriteService do let!(:antenna) { antenna_with_account(bob, alice) } let!(:empty_antenna) { antenna_with_account(ohagi, alice) } - it 'is added to the list feed of list follower', :sidekiq_inline do + it 'is added to the list feed of list follower', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -626,7 +626,7 @@ RSpec.describe FanOutOnWriteService do let!(:antenna) { antenna_with_options(bob, stl: true) } let!(:empty_antenna) { antenna_with_options(ohagi, stl: true) } - it 'is added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(antenna)).to include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -634,7 +634,7 @@ RSpec.describe FanOutOnWriteService do context 'when local timeline is disabled' do let(:ltl_enabled) { false } - it 'is not added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is not added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(antenna)).to_not include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -644,14 +644,14 @@ RSpec.describe FanOutOnWriteService do context 'with LTL antenna' do let!(:empty_antenna) { antenna_with_options(bob, ltl: true) } - it 'is added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end context 'when local timeline is disabled' do let(:ltl_enabled) { false } - it 'is not added to the antenna feed of antenna follower', :sidekiq_inline do + it 'is not added to the antenna feed of antenna follower', :inline_jobs do expect(antenna_feed_of(empty_antenna)).to_not include status.id end end @@ -660,7 +660,7 @@ RSpec.describe FanOutOnWriteService do context 'with non-public searchability' do let(:searchability) { 'direct' } - it 'hashtag-timeline is not detected', :sidekiq_inline do + it 'hashtag-timeline is not detected', :inline_jobs 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 @@ -670,23 +670,23 @@ RSpec.describe FanOutOnWriteService do context 'when status is direct' do let(:visibility) { 'direct' } - it 'is added to the home feed of its author', :sidekiq_inline do + it 'is added to the home feed of its author', :inline_jobs do expect(home_feed_of(alice)).to include status.id end - it 'is added to the home feed of the mentioned follower', :sidekiq_inline do + it 'is added to the home feed of the mentioned follower', :inline_jobs do expect(home_feed_of(bob)).to include status.id end - it 'is not added to the home feed of the other follower', :sidekiq_inline do + it 'is not added to the home feed of the other follower', :inline_jobs do expect(home_feed_of(tom)).to_not include status.id end - it 'is not added to the tag follower', :sidekiq_inline do + it 'is not added to the tag follower', :inline_jobs do expect(home_feed_of(tagf)).to_not include status.id end - it 'is not broadcast publicly', :sidekiq_inline do + it 'is not broadcast publicly', :inline_jobs 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 @@ -695,7 +695,7 @@ RSpec.describe FanOutOnWriteService do let!(:list) { list_with_account(bob, alice) } let!(:empty_list) { list_with_account(ohagi, bob) } - it 'is added to the list feed of list follower', :sidekiq_inline do + it 'is added to the list feed of list follower', :inline_jobs do expect(list_feed_of(list)).to_not include status.id expect(list_feed_of(empty_list)).to_not include status.id end @@ -705,7 +705,7 @@ RSpec.describe FanOutOnWriteService do let!(:antenna) { antenna_with_account(bob, alice) } let!(:empty_antenna) { antenna_with_account(ohagi, alice) } - it 'is added to the list feed of list follower', :sidekiq_inline do + it 'is added to the list feed of list follower', :inline_jobs do expect(antenna_feed_of(antenna)).to_not include status.id expect(antenna_feed_of(empty_antenna)).to_not include status.id end @@ -733,28 +733,28 @@ RSpec.describe FanOutOnWriteService do end context 'when public visibility' do - it 'does not create notification', :sidekiq_inline do + it 'does not create notification', :inline_jobs do notification = Notification.find_by(account: bob, type: 'mention') expect(notification).to be_nil end - it 'creates notification for active mention', :sidekiq_inline do + it 'creates notification for active mention', :inline_jobs do notification = Notification.find_by(account: tom, type: 'mention') expect(notification).to_not be_nil expect(notification.mention.status_id).to eq status.id end - it 'inserts home feed for reply', :sidekiq_inline do + it 'inserts home feed for reply', :inline_jobs do expect(home_feed_of(bob)).to include status.id end - it 'inserts home feed for non-replied but mentioned and following replied account', :sidekiq_inline do + it 'inserts home feed for non-replied but mentioned and following replied account', :inline_jobs do expect(home_feed_of(zilu)).to include status.id end - it 'does not insert home feed for non-replied, non-following replied account but mentioned', :sidekiq_inline do + it 'does not insert home feed for non-replied, non-following replied account but mentioned', :inline_jobs do expect(home_feed_of(tom)).to_not include status.id end end @@ -762,29 +762,29 @@ RSpec.describe FanOutOnWriteService do context 'when limited visibility' do let(:visibility) { :limited } - it 'creates notification', :sidekiq_inline do + it 'creates notification', :inline_jobs do notification = Notification.find_by(account: bob, type: 'mention') expect(notification).to_not be_nil expect(notification.mention.status_id).to eq status.id end - it 'creates notification for other conversation account', :sidekiq_inline do + it 'creates notification for other conversation account', :inline_jobs do notification = Notification.find_by(account: ohagi, type: 'mention') expect(notification).to_not be_nil expect(notification.mention.status_id).to eq status.id end - it 'inserts home feed for reply', :sidekiq_inline do + it 'inserts home feed for reply', :inline_jobs do expect(home_feed_of(bob)).to include status.id end - it 'inserts home feed for non-replied but mentioned and following replied account', :sidekiq_inline do + it 'inserts home feed for non-replied but mentioned and following replied account', :inline_jobs do expect(home_feed_of(zilu)).to include status.id end - it 'does not insert home feed for non-replied, non-following replied account but mentioned', :sidekiq_inline do + it 'does not insert home feed for non-replied, non-following replied account but mentioned', :inline_jobs do expect(home_feed_of(tom)).to_not include status.id end end @@ -800,21 +800,21 @@ RSpec.describe FanOutOnWriteService do subject.call(status, update: true) end - it 'notified to boosted account', :sidekiq_inline do + it 'notified to boosted account', :inline_jobs do notification = Notification.find_by(account: bob, type: 'update') expect(notification).to_not be_nil expect(notification.activity_id).to eq status.id end - it 'notified to quoted account', :sidekiq_inline do + it 'notified to quoted account', :inline_jobs do notification = Notification.find_by(account: tom, type: 'update') expect(notification).to_not be_nil expect(notification.activity_id).to eq status.id end - it 'notified not to non-boosted account', :sidekiq_inline do + it 'notified not to non-boosted account', :inline_jobs do notification = Notification.find_by(account: ohagi, type: 'update') expect(notification).to be_nil diff --git a/spec/services/favourite_service_spec.rb b/spec/services/favourite_service_spec.rb index b09c1f2693..fb27494de5 100644 --- a/spec/services/favourite_service_spec.rb +++ b/spec/services/favourite_service_spec.rb @@ -33,7 +33,7 @@ RSpec.describe FavouriteService do expect(status.favourites.first).to_not be_nil end - it 'sends a like activity', :sidekiq_inline do + it 'sends a like activity', :inline_jobs do expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once end end diff --git a/spec/services/fetch_link_card_service_spec.rb b/spec/services/fetch_link_card_service_spec.rb index d32b482087..8dce2f1647 100644 --- a/spec/services/fetch_link_card_service_spec.rb +++ b/spec/services/fetch_link_card_service_spec.rb @@ -29,7 +29,12 @@ RSpec.describe FetchLinkCardService do 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')) + stub_request(:get, 'http://example.com/latin1_posing_as_utf8_broken').to_return(request_fixture('latin1_posing_as_utf8_broken.txt')) + stub_request(:get, 'http://example.com/latin1_posing_as_utf8_recoverable').to_return(request_fixture('latin1_posing_as_utf8_recoverable.txt')) stub_request(:get, 'http://example.com/aergerliche-umlaute').to_return(request_fixture('redirect_with_utf8_url.txt')) + stub_request(:get, 'http://example.com/page_without_title').to_return(request_fixture('page_without_title.txt')) + stub_request(:get, 'http://example.com/long_canonical_url').to_return(request_fixture('long_canonical_url.txt')) + stub_request(:get, 'http://example.com/alternative_utf8_spelling_in_header').to_return(request_fixture('alternative_utf8_spelling_in_header.txt')) Rails.cache.write('oembed_endpoint:example.com', oembed_cache) if oembed_cache @@ -112,6 +117,14 @@ RSpec.describe FetchLinkCardService do end end + context 'with a page that has no title' do + let(:status) { Fabricate(:status, text: 'http://example.com/page_without_title') } + + it 'does not create a preview card' do + expect(status.preview_card).to be_nil + end + end + context 'with a 404 URL' do let(:status) { Fabricate(:status, text: 'http://example.com/not-found') } @@ -161,10 +174,30 @@ RSpec.describe FetchLinkCardService do 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') } + context 'when encoding in http header is correct' 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") + it 'decodes the HTML' do + expect(status.preview_card.title).to eq("Tofu á l'orange") + end + end + + context 'when encoding in http header is incorrect' do + context 'when encoding problems appear in unrelated tags' do + let(:status) { Fabricate(:status, text: 'Check out http://example.com/latin1_posing_as_utf8_recoverable') } + + it 'decodes the HTML' do + expect(status.preview_card.title).to eq('Tofu with orange sauce') + end + end + + context 'when encoding problems appear in title tag' do + let(:status) { Fabricate(:status, text: 'Check out http://example.com/latin1_posing_as_utf8_broken') } + + it 'does not create a preview card' do + expect(status.preview_card).to be_nil + end + end end end @@ -204,19 +237,6 @@ RSpec.describe FetchLinkCardService do end end - context 'with an URL too long for PostgreSQL unique indexes' do - let(:url) { "http://example.com/#{'a' * 2674}" } - let(:status) { Fabricate(:status, text: url) } - - it 'does not fetch the URL' do - expect(a_request(:get, url)).to_not have_been_made - end - - it 'does not create a preview card' do - expect(status.preview_card).to be_nil - end - end - context 'with a URL of a page with oEmbed support' do let(:html) { 'Hello world' } let(:status) { Fabricate(:status, text: 'http://example.com/html') } @@ -294,6 +314,14 @@ RSpec.describe FetchLinkCardService do end end + context 'with a URL of a page that includes a canonical URL too long for PostgreSQL unique indexes' do + let(:status) { Fabricate(:status, text: 'test http://example.com/long_canonical_url') } + + it 'does not create a preview card' do + expect(status.preview_card).to be_nil + end + end + context 'with URL of reference' do let(:status) { Fabricate(:status, text: 'RT http://example.com/text') } let(:custom_before) { true } @@ -329,6 +357,14 @@ RSpec.describe FetchLinkCardService do expect(status.preview_card).to be_nil end end + + context 'with a URL where the `Content-Type` header uses `utf8` instead of `utf-8`' do + let(:status) { Fabricate(:status, text: 'test http://example.com/alternative_utf8_spelling_in_header') } + + it 'does not create a preview card' do + expect(status.preview_card.title).to eq 'Webserver Configs R Us' + end + end end context 'with a remote status' do diff --git a/spec/services/follow_service_spec.rb b/spec/services/follow_service_spec.rb index 69986a1b66..a0b3b7fec4 100644 --- a/spec/services/follow_service_spec.rb +++ b/spec/services/follow_service_spec.rb @@ -150,7 +150,7 @@ RSpec.describe FollowService do expect(FollowRequest.find_by(account: sender, target_account: bob)).to_not be_nil end - it 'sends a follow activity to the inbox', :sidekiq_inline do + it 'sends a follow activity to the inbox', :inline_jobs do expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once end end diff --git a/spec/services/import_service_spec.rb b/spec/services/import_service_spec.rb index 90877d9997..0a99c5e748 100644 --- a/spec/services/import_service_spec.rb +++ b/spec/services/import_service_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -RSpec.describe ImportService, :sidekiq_inline do +RSpec.describe ImportService, :inline_jobs do include RoutingHelper let!(:account) { Fabricate(:account, locked: false) } diff --git a/spec/services/mute_service_spec.rb b/spec/services/mute_service_spec.rb index 681afc0b16..3bde92b87a 100644 --- a/spec/services/mute_service_spec.rb +++ b/spec/services/mute_service_spec.rb @@ -17,7 +17,7 @@ RSpec.describe MuteService do redis.del(home_timeline_key) end - it "clears account's statuses", :sidekiq_inline do + it "clears account's statuses", :inline_jobs do FeedManager.instance.push_to_home(account, status) FeedManager.instance.push_to_home(account, other_account_status) diff --git a/spec/services/notify_service_spec.rb b/spec/services/notify_service_spec.rb index 8c810f1c32..c7e00129b2 100644 --- a/spec/services/notify_service_spec.rb +++ b/spec/services/notify_service_spec.rb @@ -105,7 +105,7 @@ RSpec.describe NotifyService do context 'when email notification is enabled' do let(:enabled) { true } - it 'sends email', :sidekiq_inline do + it 'sends email', :inline_jobs do emails = capture_emails { subject } expect(emails.size) @@ -129,6 +129,39 @@ RSpec.describe NotifyService do end end + context 'with filtered notifications' do + let(:unknown) { Fabricate(:account, username: 'unknown') } + let(:status) { Fabricate(:status, account: unknown) } + let(:activity) { Fabricate(:mention, account: recipient, status: status) } + let(:type) { :mention } + + before do + Fabricate(:notification_policy, account: recipient, filter_not_following: true) + end + + it 'creates a filtered notification' do + expect { subject }.to change(Notification, :count) + expect(Notification.last).to be_filtered + end + + context 'when no notification request exists' do + it 'creates a notification request' do + expect { subject }.to change(NotificationRequest, :count) + end + end + + context 'when a notification request exists' do + let!(:notification_request) do + Fabricate(:notification_request, account: recipient, from_account: unknown, last_status: Fabricate(:status, account: unknown)) + end + + it 'updates the existing notification request' do + expect { subject }.to_not change(NotificationRequest, :count) + expect(notification_request.reload.last_status).to eq status + end + end + end + describe NotifyService::DismissCondition do subject { described_class.new(notification) } diff --git a/spec/services/process_references_service_spec.rb b/spec/services/process_references_service_spec.rb index d54d5e6bd9..f10a181832 100644 --- a/spec/services/process_references_service_spec.rb +++ b/spec/services/process_references_service_spec.rb @@ -34,14 +34,14 @@ RSpec.describe ProcessReferencesService, type: :service do context 'when a simple case' do let(:text) { "Hello RT #{target_status_uri}" } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 1 expect(subject.pluck(0)).to include target_status.id expect(subject.pluck(1)).to include 'RT' expect(notify?).to be true end - it 'not quote', :sidekiq_inline do + it 'not quote', :inline_jobs do expect(status.quote).to be_nil end end @@ -51,7 +51,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:target_status2_uri) { ActivityPub::TagManager.instance.uri_for(target_status2) } let(:text) { "Hello RT #{target_status_uri}\nBT #{target_status2_uri}" } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 2 expect(subject).to include [target_status.id, 'RT'] expect(subject).to include [target_status2.id, 'BT'] @@ -64,7 +64,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:text) { "Hello RT #{target_status_uri}" } let(:visibility) { :private } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 1 expect(subject.pluck(0)).to include target_status.id expect(subject.pluck(1)).to include 'RT' @@ -76,7 +76,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:text) { "Hello RT #{target_status_uri}" } let(:target_status_visibility) { :private } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 0 expect(notify?).to be false end @@ -85,7 +85,7 @@ RSpec.describe ProcessReferencesService, type: :service do context 'with quote' do let(:text) { "Hello QT #{target_status_uri}" } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 1 expect(subject.pluck(0)).to include target_status.id expect(subject.pluck(1)).to include 'QT' @@ -99,7 +99,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:text) { 'Hello' } let(:quote_urls) { [ActivityPub::TagManager.instance.uri_for(target_status)] } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 1 expect(subject.pluck(0)).to include target_status.id expect(subject.pluck(1)).to include 'QT' @@ -113,7 +113,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:text) { "Hello QT #{target_status_uri}" } let(:quote_urls) { [ActivityPub::TagManager.instance.uri_for(target_status)] } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 1 expect(subject.pluck(0)).to include target_status.id expect(subject.pluck(1)).to include 'QT' @@ -127,7 +127,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:text) { "Hello RE #{target_status_uri}" } let(:quote_urls) { [ActivityPub::TagManager.instance.uri_for(target_status)] } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 1 expect(subject.pluck(0)).to include target_status.id expect(subject.pluck(1)).to include 'QT' @@ -141,7 +141,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:text) { "Hello QT #{target_status_uri}" } let(:allow_quote) { false } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 1 expect(subject.pluck(0)).to include target_status.id expect(subject.pluck(1)).to include 'BT' @@ -155,7 +155,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:target_status2_uri) { ActivityPub::TagManager.instance.uri_for(target_status2) } let(:text) { "Hello QT #{target_status_uri}\nBT #{target_status2_uri}" } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 2 expect(subject).to include [target_status.id, 'QT'] expect(subject).to include [target_status2.id, 'BT'] @@ -169,7 +169,7 @@ RSpec.describe ProcessReferencesService, type: :service do context 'when url only' do let(:text) { "Hello #{target_status_uri}" } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 0 expect(notify?).to be false end @@ -186,7 +186,7 @@ RSpec.describe ProcessReferencesService, type: :service do context 'when the post is known' do let(:target_status) { Fabricate(:status, uri: 'https://example.com/note', url: 'https://web.example.com/note') } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 1 expect(subject.pluck(0)).to include target_status.id expect(subject.pluck(1)).to include 'RT' @@ -195,7 +195,7 @@ RSpec.describe ProcessReferencesService, type: :service do end context 'when the post is unknown' do - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 0 expect(a_request(:get, 'https://web.example.com/note')).to_not have_been_made end @@ -224,7 +224,7 @@ RSpec.describe ProcessReferencesService, type: :service do stub_request(:get, 'https://example.com/not_found').to_return(status: 404) end - it 'reference it', :sidekiq_inline do + it 'reference it', :inline_jobs do expect(subject.size).to eq 1 expect(subject[0][1]).to eq 'BT' @@ -236,7 +236,7 @@ RSpec.describe ProcessReferencesService, type: :service do context 'with fetch_remote later' do let(:fetch_remote) { false } - it 'reference it', :sidekiq_inline do + it 'reference it', :inline_jobs do ids = subject.pluck(0) expect(ids.size).to eq 1 @@ -250,7 +250,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:fetch_remote) { false } let(:text) { "RT #{ActivityPub::TagManager.instance.uri_for(target_status)} BT https://example.com/test_post" } - it 'reference it', :sidekiq_inline do + it 'reference it', :inline_jobs do expect(subject.size).to eq 2 expect(subject).to include [target_status.id, 'RT'] expect(subject.pluck(1)).to include 'BT' @@ -263,7 +263,7 @@ RSpec.describe ProcessReferencesService, type: :service do context 'with not exists reference' do let(:text) { 'BT https://example.com/not_found' } - it 'reference it', :sidekiq_inline do + it 'reference it', :inline_jobs do expect(subject.size).to eq 0 end end @@ -286,7 +286,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:text) { 'BT:https://example.com/test_post' } shared_examples 'reference once' do |uri, url| - it 'reference it', :sidekiq_inline do + it 'reference it', :inline_jobs do expect(subject.size).to eq 1 expect(subject[0][1]).to eq 'BT' @@ -326,7 +326,7 @@ RSpec.describe ProcessReferencesService, type: :service do it_behaves_like 'reference once', 'https://example.com/test_post', 'https://example.com/test_post_ohagi' - it 'do not request to uri', :sidekiq_inline do + it 'do not request to uri', :inline_jobs do subject expect(a_request(:get, 'https://example.com/test_post_ohagi')).to_not have_been_made end @@ -362,7 +362,7 @@ RSpec.describe ProcessReferencesService, type: :service do context 'when add reference to empty' do let(:new_text) { "BT #{target_status_uri}" } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 1 expect(subject).to include target_status.id expect(notify?).to be true @@ -373,7 +373,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:text) { "BT #{target_status_uri}" } let(:new_text) { "BT #{target_status_uri}\nBT #{target_status2_uri}" } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 2 expect(subject).to include target_status.id expect(subject).to include target_status2.id @@ -385,7 +385,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:text) { "BT #{target_status_uri}" } let(:new_text) { "BT #{target_status_uri}\nBT #{target_status_uri}" } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 1 expect(subject).to include target_status.id end @@ -395,7 +395,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:text) { "BT #{target_status_uri}" } let(:new_text) { 'Hello' } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 0 expect(notify?).to be false end @@ -405,7 +405,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:text) { "QT #{target_status_uri}" } let(:new_text) { 'Hello' } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 0 expect(status.quote).to be_nil expect(notify?).to be false @@ -416,7 +416,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:text) { "BT #{target_status_uri}" } let(:new_text) { "BT #{target_status2_uri}" } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 1 expect(subject).to include target_status2.id expect(notify?(target_status2.id)).to be true @@ -427,7 +427,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:text) { "QT #{target_status_uri}" } let(:new_text) { "QT #{target_status2_uri}" } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 1 expect(subject).to include target_status2.id expect(status.quote).to_not be_nil @@ -440,7 +440,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:text) { "QT #{target_status_uri}" } let(:new_text) { "RT #{target_status_uri}" } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 1 expect(subject).to include target_status.id expect(status.quote).to be_nil @@ -452,7 +452,7 @@ RSpec.describe ProcessReferencesService, type: :service do let(:text) { "RT #{target_status_uri}" } let(:new_text) { "QT #{target_status_uri}" } - it 'post status', :sidekiq_inline do + it 'post status', :inline_jobs do expect(subject.size).to eq 1 expect(subject).to include target_status.id expect(status.quote).to_not be_nil diff --git a/spec/services/reject_follow_service_spec.rb b/spec/services/reject_follow_service_spec.rb index 98aaf70478..d2c7a00206 100644 --- a/spec/services/reject_follow_service_spec.rb +++ b/spec/services/reject_follow_service_spec.rb @@ -41,7 +41,7 @@ RSpec.describe RejectFollowService do expect(bob.following?(sender)).to be false end - it 'sends a reject activity', :sidekiq_inline do + it 'sends a reject activity', :inline_jobs do expect(a_request(:post, bob.inbox_url)).to have_been_made.once end end diff --git a/spec/services/remove_from_followers_service_spec.rb b/spec/services/remove_from_followers_service_spec.rb index d6420f7674..515600096c 100644 --- a/spec/services/remove_from_followers_service_spec.rb +++ b/spec/services/remove_from_followers_service_spec.rb @@ -33,7 +33,7 @@ RSpec.describe RemoveFromFollowersService do expect(bob.followed_by?(sender)).to be false end - it 'sends a reject activity', :sidekiq_inline do + it 'sends a reject activity', :inline_jobs do expect(a_request(:post, sender.inbox_url)).to have_been_made.once end end diff --git a/spec/services/remove_status_service_spec.rb b/spec/services/remove_status_service_spec.rb index 65e755844e..da77144458 100644 --- a/spec/services/remove_status_service_spec.rb +++ b/spec/services/remove_status_service_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -RSpec.describe RemoveStatusService, :sidekiq_inline do +RSpec.describe RemoveStatusService, :inline_jobs do subject { described_class.new } let!(:alice) { Fabricate(:account) } @@ -141,7 +141,7 @@ RSpec.describe RemoveStatusService, :sidekiq_inline do )).to have_been_made.once end - it 'do not send Delete activity to followers', :sidekiq_inline do + it 'do not send Delete activity to followers', :inline_jobs do subject.call(status) expect(a_request(:post, hank.inbox_url)).to_not have_been_made diff --git a/spec/services/report_service_spec.rb b/spec/services/report_service_spec.rb index d77d8904db..393a59e30e 100644 --- a/spec/services/report_service_spec.rb +++ b/spec/services/report_service_spec.rb @@ -23,7 +23,7 @@ RSpec.describe ReportService do stub_request(:post, 'http://example.com/inbox').to_return(status: 200) end - context 'when forward is true', :sidekiq_inline do + context 'when forward is true', :inline_jobs do let(:forward) { true } it 'sends ActivityPub payload when forward is true' do @@ -53,7 +53,7 @@ RSpec.describe ReportService do end context 'when forward_to_domains includes only the replied-to domain' do - it 'sends ActivityPub payload only to the author of the replied-to post', :sidekiq_inline do + it 'sends ActivityPub payload only to the author of the replied-to post', :inline_jobs do subject.call(source_account, remote_account, status_ids: [reported_status.id], forward: forward, forward_to_domains: [remote_thread_account.domain]) expect(a_request(:post, 'http://foo.com/inbox')).to have_been_made expect(a_request(:post, 'http://example.com/inbox')).to_not have_been_made @@ -61,7 +61,7 @@ RSpec.describe ReportService do end context 'when forward_to_domains does not include the replied-to domain' do - it 'does not send ActivityPub payload to the author of the replied-to post', :sidekiq_inline do + it 'does not send ActivityPub payload to the author of the replied-to post', :inline_jobs do subject.call(source_account, remote_account, status_ids: [reported_status.id], forward: forward) expect(a_request(:post, 'http://foo.com/inbox')).to_not have_been_made end @@ -89,7 +89,7 @@ RSpec.describe ReportService do end context 'when forward is false' do - it 'does not send anything', :sidekiq_inline do + it 'does not send anything', :inline_jobs do subject.call(source_account, remote_account, forward: forward) expect(a_request(:post, 'http://example.com/inbox')).to_not have_been_made end diff --git a/spec/services/resolve_account_service_spec.rb b/spec/services/resolve_account_service_spec.rb index 9e05eb09af..74e229a92a 100644 --- a/spec/services/resolve_account_service_spec.rb +++ b/spec/services/resolve_account_service_spec.rb @@ -199,7 +199,7 @@ RSpec.describe ResolveAccountService do expect(account.uri).to eq 'https://ap.example.com/users/foo' end - it 'merges accounts', :sidekiq_inline do + it 'merges accounts', :inline_jobs do account = subject.call('foo@ap.example.com') expect(status.reload.account_id).to eq account.id diff --git a/spec/services/suspend_account_service_spec.rb b/spec/services/suspend_account_service_spec.rb index 7c72a4776b..4a2f494e0c 100644 --- a/spec/services/suspend_account_service_spec.rb +++ b/spec/services/suspend_account_service_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -RSpec.describe SuspendAccountService, :sidekiq_inline do +RSpec.describe SuspendAccountService, :inline_jobs do shared_examples 'common behavior' do subject { described_class.new.call(account) } diff --git a/spec/services/un_emoji_react_service_spec.rb b/spec/services/un_emoji_react_service_spec.rb index d435d02366..d7debc064c 100644 --- a/spec/services/un_emoji_react_service_spec.rb +++ b/spec/services/un_emoji_react_service_spec.rb @@ -90,7 +90,7 @@ RSpec.describe UnEmojiReactService, type: :service do stub_request(:post, 'https://author.foo.bar/inbox') end - it 'react with emoji', :sidekiq_inline do + it 'react with emoji', :inline_jobs do expect(subject.count).to eq 0 expect(a_request(:post, 'https://author.foo.bar/inbox').with(body: hash_including({ type: 'Undo', @@ -107,7 +107,7 @@ RSpec.describe UnEmojiReactService, type: :service do stub_request(:post, 'https://foo.bar/inbox') end - it 'react with emoji', :sidekiq_inline do + it 'react with emoji', :inline_jobs do expect(subject.count).to eq 0 expect(a_request(:post, 'https://foo.bar/inbox').with(body: hash_including({ type: 'Undo', @@ -127,7 +127,7 @@ RSpec.describe UnEmojiReactService, type: :service do stub_request(:post, 'https://foo.bar/inbox') end - it 'react with emoji', :sidekiq_inline do + it 'react with emoji', :inline_jobs do expect(subject.count).to eq 0 expect(a_request(:post, 'https://foo.bar/inbox').with(body: hash_including({ type: 'Undo', @@ -145,7 +145,7 @@ RSpec.describe UnEmojiReactService, type: :service do stub_request(:post, 'https://foo.bar/inbox') end - it 'react with emoji', :sidekiq_inline do + it 'react with emoji', :inline_jobs do expect(subject.count).to eq 0 expect(a_request(:post, 'https://foo.bar/inbox').with(body: hash_including({ type: 'Undo', @@ -163,7 +163,7 @@ RSpec.describe UnEmojiReactService, type: :service do stub_request(:post, 'https://foo.bar/inbox') end - it 'react with emoji', :sidekiq_inline do + it 'react with emoji', :inline_jobs do expect(subject.count).to eq 0 expect(a_request(:post, 'https://foo.bar/inbox').with(body: hash_including({ type: 'Undo', diff --git a/spec/services/unallow_domain_service_spec.rb b/spec/services/unallow_domain_service_spec.rb index caec3d596f..4bf6c54043 100644 --- a/spec/services/unallow_domain_service_spec.rb +++ b/spec/services/unallow_domain_service_spec.rb @@ -13,7 +13,7 @@ RSpec.describe UnallowDomainService do let!(:already_banned_account) { Fabricate(:account, username: 'badguy', domain: bad_domain, suspended: true, silenced: true) } let!(:domain_allow) { Fabricate(:domain_allow, domain: bad_domain) } - context 'with limited federation mode', :sidekiq_inline do + context 'with limited federation mode', :inline_jobs do before do allow(Rails.configuration.x).to receive(:limited_federation_mode).and_return(true) end diff --git a/spec/services/unblock_service_spec.rb b/spec/services/unblock_service_spec.rb index 4c9fcb9aee..6132e74415 100644 --- a/spec/services/unblock_service_spec.rb +++ b/spec/services/unblock_service_spec.rb @@ -33,7 +33,7 @@ RSpec.describe UnblockService do expect(sender.blocking?(bob)).to be false end - it 'sends an unblock activity', :sidekiq_inline do + it 'sends an unblock activity', :inline_jobs do expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once end end diff --git a/spec/services/unfollow_service_spec.rb b/spec/services/unfollow_service_spec.rb index bba17a8d27..0c206c4b98 100644 --- a/spec/services/unfollow_service_spec.rb +++ b/spec/services/unfollow_service_spec.rb @@ -20,7 +20,7 @@ RSpec.describe UnfollowService do end end - describe 'remote ActivityPub', :sidekiq_inline do + describe 'remote ActivityPub', :inline_jobs do let(:bob) { Fabricate(:account, username: 'bob', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') } before do @@ -38,7 +38,7 @@ RSpec.describe UnfollowService do end end - describe 'remote ActivityPub (reverse)', :sidekiq_inline do + describe 'remote ActivityPub (reverse)', :inline_jobs do let(:bob) { Fabricate(:account, username: 'bob', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') } before do diff --git a/spec/services/unsuspend_account_service_spec.rb b/spec/services/unsuspend_account_service_spec.rb index 79a4441d3e..8d4882c37f 100644 --- a/spec/services/unsuspend_account_service_spec.rb +++ b/spec/services/unsuspend_account_service_spec.rb @@ -45,7 +45,7 @@ RSpec.describe UnsuspendAccountService do remote_follower.follow!(account) end - it 'merges back into feeds of local followers and sends update', :sidekiq_inline do + it 'merges back into feeds of local followers and sends update', :inline_jobs do subject expect_feeds_merged diff --git a/spec/services/update_account_service_spec.rb b/spec/services/update_account_service_spec.rb index f07b1a7c02..3720e85532 100644 --- a/spec/services/update_account_service_spec.rb +++ b/spec/services/update_account_service_spec.rb @@ -5,7 +5,7 @@ require 'rails_helper' RSpec.describe UpdateAccountService do subject { described_class.new } - describe 'switching form locked to unlocked accounts', :sidekiq_inline do + describe 'switching form locked to unlocked accounts', :inline_jobs do let(:account) { Fabricate(:account, locked: true) } let(:alice) { Fabricate(:account) } let(:bob) { Fabricate(:account) } diff --git a/spec/services/update_status_service_spec.rb b/spec/services/update_status_service_spec.rb index dbd5a0fd7f..81b91ad1cd 100644 --- a/spec/services/update_status_service_spec.rb +++ b/spec/services/update_status_service_spec.rb @@ -62,7 +62,7 @@ RSpec.describe UpdateStatusService do end end - context 'when content warning changes and has remote user', :sidekiq_inline do + context 'when content warning changes and has remote user', :inline_jobs do let(:remote_follower) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/actor', protocol: :activitypub, inbox_url: 'https://example.com/inbox') } let(:status) { Fabricate(:status, text: 'Foo', spoiler_text: '', account: Fabricate(:user).account) } diff --git a/spec/support/examples/models/concerns/account_avatar.rb b/spec/support/examples/models/concerns/account_avatar.rb index 2c9b5514aa..ab6020d834 100644 --- a/spec/support/examples/models/concerns/account_avatar.rb +++ b/spec/support/examples/models/concerns/account_avatar.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true shared_examples 'AccountAvatar' do |fabricator| - describe 'static avatars', :paperclip_processing do + describe 'static avatars', :attachment_processing do describe 'when GIF' do it 'creates a png static style' do account = Fabricate(fabricator, avatar: attachment_fixture('avatar.gif')) @@ -17,7 +17,7 @@ shared_examples 'AccountAvatar' do |fabricator| end end - describe 'base64-encoded files', :paperclip_processing do + describe 'base64-encoded files', :attachment_processing do let(:base64_attachment) { "data:image/jpeg;base64,#{Base64.encode64(attachment_fixture('attachment.jpg').read)}" } let(:account) { Fabricate(fabricator, avatar: base64_attachment) } diff --git a/spec/support/examples/models/concerns/account_header.rb b/spec/support/examples/models/concerns/account_header.rb index ce09eb006b..43bbdaacf4 100644 --- a/spec/support/examples/models/concerns/account_header.rb +++ b/spec/support/examples/models/concerns/account_header.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true shared_examples 'AccountHeader' do |fabricator| - describe 'base64-encoded files', :paperclip_processing do + describe 'base64-encoded files', :attachment_processing do let(:base64_attachment) { "data:image/jpeg;base64,#{Base64.encode64(attachment_fixture('attachment.jpg').read)}" } let(:account) { Fabricate(fabricator, header: base64_attachment) } diff --git a/spec/system/admin/accounts_spec.rb b/spec/system/admin/accounts_spec.rb index 54d755b914..20813f6be4 100644 --- a/spec/system/admin/accounts_spec.rb +++ b/spec/system/admin/accounts_spec.rb @@ -48,7 +48,7 @@ describe 'Admin::Accounts' do end end - context 'with action of `reject`', :sidekiq_inline do + context 'with action of `reject`', :inline_jobs do it 'rejects and removes the account' do batch_checkbox_for(unapproved_user_account).check diff --git a/spec/system/new_statuses_spec.rb b/spec/system/new_statuses_spec.rb index 6d1cffb2f2..89d0fa9ca3 100644 --- a/spec/system/new_statuses_spec.rb +++ b/spec/system/new_statuses_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -describe 'NewStatuses', :js, :sidekiq_inline, :streaming do +describe 'NewStatuses', :inline_jobs, :js, :streaming do include ProfileStories subject { page } diff --git a/spec/system/ocr_spec.rb b/spec/system/ocr_spec.rb index 4f4941adca..17d18af158 100644 --- a/spec/system/ocr_spec.rb +++ b/spec/system/ocr_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -describe 'OCR', :js, :paperclip_processing, :sidekiq_inline, :streaming do +describe 'OCR', :attachment_processing, :inline_jobs, :js, :streaming do include ProfileStories let(:email) { 'test@example.com' } diff --git a/spec/system/report_interface_spec.rb b/spec/system/report_interface_spec.rb index f82604aae8..e6cc3b1b68 100644 --- a/spec/system/report_interface_spec.rb +++ b/spec/system/report_interface_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -describe 'report interface', :js, :paperclip_processing, :streaming do +describe 'report interface', :attachment_processing, :js, :streaming do include ProfileStories let(:email) { 'admin@example.com' } diff --git a/spec/workers/backup_worker_spec.rb b/spec/workers/backup_worker_spec.rb index 74928c7ca6..db1b50140b 100644 --- a/spec/workers/backup_worker_spec.rb +++ b/spec/workers/backup_worker_spec.rb @@ -14,7 +14,7 @@ describe BackupWorker do let(:backup) { Fabricate(:backup) } let!(:other_backup) { Fabricate(:backup, user: backup.user) } - it 'sends the backup to the service and removes other backups', :sidekiq_inline do + it 'sends the backup to the service and removes other backups', :inline_jobs do emails = capture_emails { worker.perform(backup.id) } expect(service).to have_received(:call).with(backup) diff --git a/spec/workers/feed_insert_worker_spec.rb b/spec/workers/feed_insert_worker_spec.rb index 80115c08d0..c4a32fe0b0 100644 --- a/spec/workers/feed_insert_worker_spec.rb +++ b/spec/workers/feed_insert_worker_spec.rb @@ -73,19 +73,19 @@ describe FeedInsertWorker do end context 'with notification' do - it 'skips notification when unset', :sidekiq_inline do + it 'skips notification when unset', :inline_jobs do subject.perform(status.id, follower.id) expect(notify?(follower, 'status', status.id)).to be false end - it 'pushes notification when read status is set', :sidekiq_inline do + it 'pushes notification when read status is set', :inline_jobs do Fabricate(:follow, account: follower, target_account: status.account, notify: true) subject.perform(status.id, follower.id) expect(notify?(follower, 'status', status.id)).to be true end - it 'skips notification when the account is registered list but not notify', :sidekiq_inline do + it 'skips notification when the account is registered list but not notify', :inline_jobs do follower.follow!(status.account) list = Fabricate(:list, account: follower) Fabricate(:list_account, list: list, account: status.account) @@ -97,7 +97,7 @@ describe FeedInsertWorker do expect(list_status).to be_nil end - it 'pushes notification when the account is registered list', :sidekiq_inline do + it 'pushes notification when the account is registered list', :inline_jobs do follower.follow!(status.account) list = Fabricate(:list, account: follower, notify: true) Fabricate(:list_account, list: list, account: status.account) diff --git a/spec/workers/move_worker_spec.rb b/spec/workers/move_worker_spec.rb index 0513dc42e5..b25992e44b 100644 --- a/spec/workers/move_worker_spec.rb +++ b/spec/workers/move_worker_spec.rb @@ -104,7 +104,7 @@ describe MoveWorker do end shared_examples 'lists handling' do - it 'puts the new account on the list and makes valid lists', :sidekiq_inline do + it 'puts the new account on the list and makes valid lists', :inline_jobs do subject.perform(source_account.id, target_account.id) expect(list.accounts.include?(target_account)).to be true diff --git a/spec/workers/post_process_media_worker_spec.rb b/spec/workers/post_process_media_worker_spec.rb index 828da5244f..1a274623d7 100644 --- a/spec/workers/post_process_media_worker_spec.rb +++ b/spec/workers/post_process_media_worker_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -describe PostProcessMediaWorker, :paperclip_processing do +describe PostProcessMediaWorker, :attachment_processing do let(:worker) { described_class.new } describe '#perform' do diff --git a/streaming/index.js b/streaming/index.js index 94ce534f87..e4a1bd2b4d 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -524,43 +524,27 @@ const startServer = async () => { * @param {any} req * @returns {Promise} */ - const accountFromToken = (token, req) => new Promise((resolve, reject) => { - pgPool.connect((err, client, done) => { - if (err) { - reject(err); - return; - } + const accountFromToken = async (token, req) => { + const result = await pgPool.query('SELECT oauth_access_tokens.id, oauth_access_tokens.resource_owner_id, users.account_id, users.chosen_languages, oauth_access_tokens.scopes, devices.device_id FROM oauth_access_tokens INNER JOIN users ON oauth_access_tokens.resource_owner_id = users.id LEFT OUTER JOIN devices ON oauth_access_tokens.id = devices.access_token_id WHERE oauth_access_tokens.token = $1 AND oauth_access_tokens.revoked_at IS NULL LIMIT 1', [token]); - // @ts-ignore - client.query('SELECT oauth_access_tokens.id, oauth_access_tokens.resource_owner_id, users.account_id, users.chosen_languages, oauth_access_tokens.scopes, devices.device_id FROM oauth_access_tokens INNER JOIN users ON oauth_access_tokens.resource_owner_id = users.id LEFT OUTER JOIN devices ON oauth_access_tokens.id = devices.access_token_id WHERE oauth_access_tokens.token = $1 AND oauth_access_tokens.revoked_at IS NULL LIMIT 1', [token], (err, result) => { - done(); + if (result.rows.length === 0) { + throw new AuthenticationError('Invalid access token'); + } - if (err) { - reject(err); - return; - } + req.accessTokenId = result.rows[0].id; + req.scopes = result.rows[0].scopes.split(' '); + req.accountId = result.rows[0].account_id; + req.chosenLanguages = result.rows[0].chosen_languages; + req.deviceId = result.rows[0].device_id; - if (result.rows.length === 0) { - reject(new AuthenticationError('Invalid access token')); - return; - } - - req.accessTokenId = result.rows[0].id; - req.scopes = result.rows[0].scopes.split(' '); - req.accountId = result.rows[0].account_id; - req.chosenLanguages = result.rows[0].chosen_languages; - req.deviceId = result.rows[0].device_id; - - resolve({ - accessTokenId: result.rows[0].id, - scopes: result.rows[0].scopes.split(' '), - accountId: result.rows[0].account_id, - chosenLanguages: result.rows[0].chosen_languages, - deviceId: result.rows[0].device_id - }); - }); - }); - }); + return { + accessTokenId: result.rows[0].id, + scopes: result.rows[0].scopes.split(' '), + accountId: result.rows[0].account_id, + chosenLanguages: result.rows[0].chosen_languages, + deviceId: result.rows[0].device_id + }; + }; /** * @param {any} req @@ -773,28 +757,15 @@ const startServer = async () => { * @param {any} req * @returns {Promise.} */ - const authorizeListAccess = (listId, req) => new Promise((resolve, reject) => { + const authorizeListAccess = async (listId, req) => { const { accountId } = req; - pgPool.connect((err, client, done) => { - if (err) { - reject(); - return; - } + const result = await pgPool.query('SELECT id, account_id FROM lists WHERE id = $1 AND account_id = $2 LIMIT 1', [listId, accountId]); - // @ts-ignore - client.query('SELECT id, account_id FROM lists WHERE id = $1 LIMIT 1', [listId], (err, result) => { - done(); - - if (err || result.rows.length === 0 || result.rows[0].account_id !== accountId) { - reject(); - return; - } - - resolve(); - }); - }); - }); + if (result.rows.length === 0) { + throw new AuthenticationError('List not found'); + } + }; /** * @param {string} antennaId @@ -1167,7 +1138,7 @@ const startServer = async () => { /** * @param {http.IncomingMessage} req - * @param {WebSocket} ws + * @param {import('ws').WebSocket} ws * @param {string[]} streamName * @returns {function(string, string): void} */ @@ -1399,7 +1370,7 @@ const startServer = async () => { /** * @typedef WebSocketSession - * @property {WebSocket & { isAlive: boolean}} websocket + * @property {import('ws').WebSocket & { isAlive: boolean}} websocket * @property {http.IncomingMessage & ResolvedAccount} request * @property {import('pino').Logger} logger * @property {Object.} subscriptions @@ -1525,7 +1496,7 @@ const startServer = async () => { }; /** - * @param {WebSocket & { isAlive: boolean }} ws + * @param {import('ws').WebSocket & { isAlive: boolean }} ws * @param {http.IncomingMessage & ResolvedAccount} req * @param {import('pino').Logger} log */ diff --git a/yarn.lock b/yarn.lock index 1aab775f2d..826b64696d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -52,45 +52,45 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/compat-data@npm:7.24.7" - checksum: 10c0/dcd93a5632b04536498fbe2be5af1057f635fd7f7090483d8e797878559037e5130b26862ceb359acbae93ed27e076d395ddb4663db6b28a665756ffd02d324f +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/compat-data@npm:7.24.8" + checksum: 10c0/7f465e9d8e44c5b516eeb3001362a3cd9a6df51dd90d3ac9868e1e7fa631ac57fc781cec6700110d4f555ba37fe59c4a71927b445106fe0062e79e79ffe11091 languageName: node linkType: hard "@babel/core@npm:^7.10.4, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.22.1, @babel/core@npm:^7.24.4": - version: 7.24.7 - resolution: "@babel/core@npm:7.24.7" + version: 7.24.9 + resolution: "@babel/core@npm:7.24.9" dependencies: "@ampproject/remapping": "npm:^2.2.0" "@babel/code-frame": "npm:^7.24.7" - "@babel/generator": "npm:^7.24.7" - "@babel/helper-compilation-targets": "npm:^7.24.7" - "@babel/helper-module-transforms": "npm:^7.24.7" - "@babel/helpers": "npm:^7.24.7" - "@babel/parser": "npm:^7.24.7" + "@babel/generator": "npm:^7.24.9" + "@babel/helper-compilation-targets": "npm:^7.24.8" + "@babel/helper-module-transforms": "npm:^7.24.9" + "@babel/helpers": "npm:^7.24.8" + "@babel/parser": "npm:^7.24.8" "@babel/template": "npm:^7.24.7" - "@babel/traverse": "npm:^7.24.7" - "@babel/types": "npm:^7.24.7" + "@babel/traverse": "npm:^7.24.8" + "@babel/types": "npm:^7.24.9" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 10c0/4004ba454d3c20a46ea66264e06c15b82e9f6bdc35f88819907d24620da70dbf896abac1cb4cc4b6bb8642969e45f4d808497c9054a1388a386cf8c12e9b9e0d + checksum: 10c0/e104ec6efbf099f55184933e9ab078eb5821c792ddfef3e9c6561986ec4ff103f5c11e3d7d6e5e8929e50e2c58db1cc80e5b6f14b530335b6622095ec4b4124c languageName: node linkType: hard -"@babel/generator@npm:^7.24.7, @babel/generator@npm:^7.7.2": - version: 7.24.7 - resolution: "@babel/generator@npm:7.24.7" +"@babel/generator@npm:^7.24.8, @babel/generator@npm:^7.24.9, @babel/generator@npm:^7.7.2": + version: 7.24.9 + resolution: "@babel/generator@npm:7.24.9" dependencies: - "@babel/types": "npm:^7.24.7" + "@babel/types": "npm:^7.24.9" "@jridgewell/gen-mapping": "npm:^0.3.5" "@jridgewell/trace-mapping": "npm:^0.3.25" jsesc: "npm:^2.5.1" - checksum: 10c0/06b1f3350baf527a3309e50ffd7065f7aee04dd06e1e7db794ddfde7fe9d81f28df64edd587173f8f9295496a7ddb74b9a185d4bf4de7bb619e6d4ec45c8fd35 + checksum: 10c0/cd1f7edce7717462546c349e15289d1267a3ed627c6f6583fbf51e78eacacc6500ec2f0024f08f1cc7138989e575635b931acf4549f9e728017a22176a9ea6b6 languageName: node linkType: hard @@ -123,16 +123,16 @@ __metadata: languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-compilation-targets@npm:7.24.7" +"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.24.7, @babel/helper-compilation-targets@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-compilation-targets@npm:7.24.8" dependencies: - "@babel/compat-data": "npm:^7.24.7" - "@babel/helper-validator-option": "npm:^7.24.7" - browserslist: "npm:^4.22.2" + "@babel/compat-data": "npm:^7.24.8" + "@babel/helper-validator-option": "npm:^7.24.8" + browserslist: "npm:^4.23.1" lru-cache: "npm:^5.1.1" semver: "npm:^6.3.1" - checksum: 10c0/1d580a9bcacefe65e6bf02ba1dafd7ab278269fef45b5e281d8354d95c53031e019890464e7f9351898c01502dd2e633184eb0bcda49ed2ecd538675ce310f51 + checksum: 10c0/2885c44ef6aaf82b7e4352b30089bb09fbe08ed5ec24eb452c2bdc3c021e2a65ab412f74b3d67ec1398da0356c730b33a2ceca1d67d34c85080d31ca6efa9aec languageName: node linkType: hard @@ -231,9 +231,9 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-module-transforms@npm:7.24.7" +"@babel/helper-module-transforms@npm:^7.24.7, @babel/helper-module-transforms@npm:^7.24.8, @babel/helper-module-transforms@npm:^7.24.9": + version: 7.24.9 + resolution: "@babel/helper-module-transforms@npm:7.24.9" dependencies: "@babel/helper-environment-visitor": "npm:^7.24.7" "@babel/helper-module-imports": "npm:^7.24.7" @@ -242,7 +242,7 @@ __metadata: "@babel/helper-validator-identifier": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/4f311755fcc3b4cbdb689386309cdb349cf0575a938f0b9ab5d678e1a81bbb265aa34ad93174838245f2ac7ff6d5ddbd0104638a75e4e961958ed514355687b6 + checksum: 10c0/e27bca43bc113731ee4f2b33a4c5bf9c7eebf4d64487b814c305cbd5feb272c29fcd3d79634ba03131ade171e5972bc7ede8dbc83ba0deb02f1e62d318c87770 languageName: node linkType: hard @@ -255,10 +255,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": - version: 7.24.7 - resolution: "@babel/helper-plugin-utils@npm:7.24.7" - checksum: 10c0/c3d38cd9b3520757bb4a279255cc3f956fc0ac1c193964bd0816ebd5c86e30710be8e35252227e0c9d9e0f4f56d9b5f916537f2bc588084b0988b4787a967d31 +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.24.8, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": + version: 7.24.8 + resolution: "@babel/helper-plugin-utils@npm:7.24.8" + checksum: 10c0/0376037f94a3bfe6b820a39f81220ac04f243eaee7193774b983e956c1750883ff236b30785795abbcda43fac3ece74750566830c2daa4d6e3870bb0dff34c2d languageName: node linkType: hard @@ -317,10 +317,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-string-parser@npm:7.24.7" - checksum: 10c0/47840c7004e735f3dc93939c77b099bb41a64bf3dda0cae62f60e6f74a5ff80b63e9b7cf77b5ec25a324516381fc994e1f62f922533236a8e3a6af57decb5e1e +"@babel/helper-string-parser@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-string-parser@npm:7.24.8" + checksum: 10c0/6361f72076c17fabf305e252bf6d580106429014b3ab3c1f5c4eb3e6d465536ea6b670cc0e9a637a77a9ad40454d3e41361a2909e70e305116a23d68ce094c08 languageName: node linkType: hard @@ -331,10 +331,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-validator-option@npm:7.24.7" - checksum: 10c0/21aea2b7bc5cc8ddfb828741d5c8116a84cbc35b4a3184ec53124f08e09746f1f67a6f9217850188995ca86059a7942e36d8965a6730784901def777b7e8a436 +"@babel/helper-validator-option@npm:^7.24.7, @babel/helper-validator-option@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-validator-option@npm:7.24.8" + checksum: 10c0/73db93a34ae89201351288bee7623eed81a54000779462a986105b54ffe82069e764afd15171a428b82e7c7a9b5fec10b5d5603b216317a414062edf5c67a21f languageName: node linkType: hard @@ -350,13 +350,13 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helpers@npm:7.24.7" +"@babel/helpers@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helpers@npm:7.24.8" dependencies: "@babel/template": "npm:^7.24.7" - "@babel/types": "npm:^7.24.7" - checksum: 10c0/aa8e230f6668773e17e141dbcab63e935c514b4b0bf1fed04d2eaefda17df68e16b61a56573f7f1d4d1e605ce6cc162b5f7e9fdf159fde1fd9b77c920ae47d27 + "@babel/types": "npm:^7.24.8" + checksum: 10c0/42b8939b0a0bf72d6df9721973eb0fd7cd48f42641c5c9c740916397faa586255c06d36c6e6a7e091860723096281c620f6ffaee0011a3bb254a6f5475d89a12 languageName: node linkType: hard @@ -372,12 +372,12 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/parser@npm:7.24.7" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.24.7, @babel/parser@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/parser@npm:7.24.8" bin: parser: ./bin/babel-parser.js - checksum: 10c0/8b244756872185a1c6f14b979b3535e682ff08cb5a2a5fd97cc36c017c7ef431ba76439e95e419d43000c5b07720495b00cf29a7f0d9a483643d08802b58819b + checksum: 10c0/ce69671de8fa6f649abf849be262707ac700b573b8b1ce1893c66cc6cd76aeb1294a19e8c290b0eadeb2f47d3f413a2e57a281804ffbe76bfb9fa50194cf3c52 languageName: node linkType: hard @@ -755,21 +755,21 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-classes@npm:7.24.7" +"@babel/plugin-transform-classes@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-classes@npm:7.24.8" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.24.7" - "@babel/helper-compilation-targets": "npm:^7.24.7" + "@babel/helper-compilation-targets": "npm:^7.24.8" "@babel/helper-environment-visitor": "npm:^7.24.7" "@babel/helper-function-name": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.8" "@babel/helper-replace-supers": "npm:^7.24.7" "@babel/helper-split-export-declaration": "npm:^7.24.7" globals: "npm:^11.1.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/e51dba7ce8b770d1eee929e098d5a3be3efc3e8b941e22dda7d0097dc4e7be5feabd2da7b707ac06fcac5661b31223c541941dec08ce76c1faa55544d87d06ec + checksum: 10c0/4423da0f747bdb6aab1995d98a74533fa679f637ec20706810dd57fb4ba2b1885ec8cae6a0b2c3f69f27165de6ff6aa2da9c4061c893848736a8267d0c653079 languageName: node linkType: hard @@ -785,14 +785,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-destructuring@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-destructuring@npm:7.24.7" +"@babel/plugin-transform-destructuring@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-destructuring@npm:7.24.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.8" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/929f07a807fb62230bfbf881cfcedf187ac5daf2f1b01da94a75c7a0f6f72400268cf4bcfee534479e43260af8193e42c31ee03c8b0278ba77d0036ed6709c27 + checksum: 10c0/804968c1d5f5072c717505296c1e5d5ec33e90550423de66de82bbcb78157156e8470bbe77a04ab8c710a88a06360a30103cf223ac7eff4829adedd6150de5ce languageName: node linkType: hard @@ -938,16 +938,16 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-modules-commonjs@npm:7.24.7" +"@babel/plugin-transform-modules-commonjs@npm:^7.24.7, @babel/plugin-transform-modules-commonjs@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.24.8" dependencies: - "@babel/helper-module-transforms": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-module-transforms": "npm:^7.24.8" + "@babel/helper-plugin-utils": "npm:^7.24.8" "@babel/helper-simple-access": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/9442292b3daf6a5076cdc3c4c32bf423bda824ccaeb0dd0dc8b3effaa1fecfcb0130ae6e647fef12a5d5ff25bcc99a0d6bfc6d24a7525345e1bcf46fcdf81752 + checksum: 10c0/f1cf552307ebfced20d3907c1dd8be941b277f0364aa655e2b5fee828c84c54065745183104dae86f1f93ea0406db970a463ef7ceaaed897623748e99640e5a7 languageName: node linkType: hard @@ -1062,16 +1062,16 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-optional-chaining@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.24.7" +"@babel/plugin-transform-optional-chaining@npm:^7.24.7, @babel/plugin-transform-optional-chaining@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.24.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.8" "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.7" "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/b9e3649b299e103b0d1767bbdba56574d065ff776e5350403b7bfd4e3982743c0cdb373d33bdbf94fa3c322d155e45d0aad946acf0aa741b870aed22dfec8b8e + checksum: 10c0/4ffbe1aad7dec7c9aa2bf6ceb4b2f91f96815b2784f2879bde80e46934f59d64a12cb2c6262e40897c4754d77d2c35d8a5cfed63044fdebf94978b1ed3d14b17 languageName: node linkType: hard @@ -1279,14 +1279,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-typeof-symbol@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-typeof-symbol@npm:7.24.7" +"@babel/plugin-transform-typeof-symbol@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.24.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.8" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/5649e7260a138681e68b296ab5931e2b1f132f287d6b4131d49b24f9dc20d62902b7e9d63c4d2decd5683b41df35ef4b9b03f58c7f9f65e4c25a6d8bbf04e9e9 + checksum: 10c0/2f570a4fbbdc5fd85f48165a97452826560051e3b8efb48c3bb0a0a33ee8485633439e7b71bfe3ef705583a1df43f854f49125bd759abdedc195b2cf7e60012a languageName: node linkType: hard @@ -1352,13 +1352,13 @@ __metadata: linkType: hard "@babel/preset-env@npm:^7.11.0, @babel/preset-env@npm:^7.12.1, @babel/preset-env@npm:^7.22.4": - version: 7.24.7 - resolution: "@babel/preset-env@npm:7.24.7" + version: 7.24.8 + resolution: "@babel/preset-env@npm:7.24.8" dependencies: - "@babel/compat-data": "npm:^7.24.7" - "@babel/helper-compilation-targets": "npm:^7.24.7" - "@babel/helper-plugin-utils": "npm:^7.24.7" - "@babel/helper-validator-option": "npm:^7.24.7" + "@babel/compat-data": "npm:^7.24.8" + "@babel/helper-compilation-targets": "npm:^7.24.8" + "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-validator-option": "npm:^7.24.8" "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.24.7" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.24.7" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.24.7" @@ -1389,9 +1389,9 @@ __metadata: "@babel/plugin-transform-block-scoping": "npm:^7.24.7" "@babel/plugin-transform-class-properties": "npm:^7.24.7" "@babel/plugin-transform-class-static-block": "npm:^7.24.7" - "@babel/plugin-transform-classes": "npm:^7.24.7" + "@babel/plugin-transform-classes": "npm:^7.24.8" "@babel/plugin-transform-computed-properties": "npm:^7.24.7" - "@babel/plugin-transform-destructuring": "npm:^7.24.7" + "@babel/plugin-transform-destructuring": "npm:^7.24.8" "@babel/plugin-transform-dotall-regex": "npm:^7.24.7" "@babel/plugin-transform-duplicate-keys": "npm:^7.24.7" "@babel/plugin-transform-dynamic-import": "npm:^7.24.7" @@ -1404,7 +1404,7 @@ __metadata: "@babel/plugin-transform-logical-assignment-operators": "npm:^7.24.7" "@babel/plugin-transform-member-expression-literals": "npm:^7.24.7" "@babel/plugin-transform-modules-amd": "npm:^7.24.7" - "@babel/plugin-transform-modules-commonjs": "npm:^7.24.7" + "@babel/plugin-transform-modules-commonjs": "npm:^7.24.8" "@babel/plugin-transform-modules-systemjs": "npm:^7.24.7" "@babel/plugin-transform-modules-umd": "npm:^7.24.7" "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.24.7" @@ -1414,7 +1414,7 @@ __metadata: "@babel/plugin-transform-object-rest-spread": "npm:^7.24.7" "@babel/plugin-transform-object-super": "npm:^7.24.7" "@babel/plugin-transform-optional-catch-binding": "npm:^7.24.7" - "@babel/plugin-transform-optional-chaining": "npm:^7.24.7" + "@babel/plugin-transform-optional-chaining": "npm:^7.24.8" "@babel/plugin-transform-parameters": "npm:^7.24.7" "@babel/plugin-transform-private-methods": "npm:^7.24.7" "@babel/plugin-transform-private-property-in-object": "npm:^7.24.7" @@ -1425,7 +1425,7 @@ __metadata: "@babel/plugin-transform-spread": "npm:^7.24.7" "@babel/plugin-transform-sticky-regex": "npm:^7.24.7" "@babel/plugin-transform-template-literals": "npm:^7.24.7" - "@babel/plugin-transform-typeof-symbol": "npm:^7.24.7" + "@babel/plugin-transform-typeof-symbol": "npm:^7.24.8" "@babel/plugin-transform-unicode-escapes": "npm:^7.24.7" "@babel/plugin-transform-unicode-property-regex": "npm:^7.24.7" "@babel/plugin-transform-unicode-regex": "npm:^7.24.7" @@ -1434,11 +1434,11 @@ __metadata: babel-plugin-polyfill-corejs2: "npm:^0.4.10" babel-plugin-polyfill-corejs3: "npm:^0.10.4" babel-plugin-polyfill-regenerator: "npm:^0.6.1" - core-js-compat: "npm:^3.31.0" + core-js-compat: "npm:^3.37.1" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/c6714346f3ccc1271eaa90051c75b8bb57b20ef57408ab68740e2f3552693ae0ee5a4bcce3a00211d40e4947af1f7b8ab422066b953f0095461937fb72d11274 + checksum: 10c0/a6f29498ec58989845a61f9c10b1b4e80586f1810a33db461d597cdb0ad2cd847381a993038b09f727512a08b2c1a33a330a5d4e6d65463ee98a1b4302d52ec6 languageName: node linkType: hard @@ -1503,11 +1503,11 @@ __metadata: linkType: hard "@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.23.7, @babel/runtime@npm:^7.24.1, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": - version: 7.24.7 - resolution: "@babel/runtime@npm:7.24.7" + version: 7.24.8 + resolution: "@babel/runtime@npm:7.24.8" dependencies: regenerator-runtime: "npm:^0.14.0" - checksum: 10c0/b6fa3ec61a53402f3c1d75f4d808f48b35e0dfae0ec8e2bb5c6fc79fb95935da75766e0ca534d0f1c84871f6ae0d2ebdd950727cfadb745a2cdbef13faef5513 + checksum: 10c0/f24b30af6b3ecae19165b3b032f9bc37b2d1769677bd63b69a6f81061967cfc847aa822518402ea6616b1d301d7eb46986b99c9f69cdb5880834fca2e6b34881 languageName: node linkType: hard @@ -1522,32 +1522,32 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:7, @babel/traverse@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/traverse@npm:7.24.7" +"@babel/traverse@npm:7, @babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/traverse@npm:7.24.8" dependencies: "@babel/code-frame": "npm:^7.24.7" - "@babel/generator": "npm:^7.24.7" + "@babel/generator": "npm:^7.24.8" "@babel/helper-environment-visitor": "npm:^7.24.7" "@babel/helper-function-name": "npm:^7.24.7" "@babel/helper-hoist-variables": "npm:^7.24.7" "@babel/helper-split-export-declaration": "npm:^7.24.7" - "@babel/parser": "npm:^7.24.7" - "@babel/types": "npm:^7.24.7" + "@babel/parser": "npm:^7.24.8" + "@babel/types": "npm:^7.24.8" debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: 10c0/a5135e589c3f1972b8877805f50a084a04865ccb1d68e5e1f3b94a8841b3485da4142e33413d8fd76bc0e6444531d3adf1f59f359c11ffac452b743d835068ab + checksum: 10c0/67a5cc35824455cdb54fb9e196a44b3186283e29018a9c2331f51763921e18e891b3c60c283615a27540ec8eb4c8b89f41c237b91f732a7aa518b2eb7a0d434d languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": - version: 7.24.7 - resolution: "@babel/types@npm:7.24.7" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.0.0-beta.49, @babel/types@npm:^7.12.11, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.24.9, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.24.9 + resolution: "@babel/types@npm:7.24.9" dependencies: - "@babel/helper-string-parser": "npm:^7.24.7" + "@babel/helper-string-parser": "npm:^7.24.8" "@babel/helper-validator-identifier": "npm:^7.24.7" to-fast-properties: "npm:^2.0.0" - checksum: 10c0/d9ecbfc3eb2b05fb1e6eeea546836ac30d990f395ef3fe3f75ced777a222c3cfc4489492f72e0ce3d9a5a28860a1ce5f81e66b88cf5088909068b3ff4fab72c1 + checksum: 10c0/4970b3481cab39c5c3fdb7c28c834df5c7049f3c7f43baeafe121bb05270ebf0da7c65b097abf314877f213baa591109c82204f30d66cdd46c22ece4a2f32415 languageName: node linkType: hard @@ -1558,13 +1558,13 @@ __metadata: languageName: node linkType: hard -"@csstools/cascade-layer-name-parser@npm:^1.0.12": - version: 1.0.12 - resolution: "@csstools/cascade-layer-name-parser@npm:1.0.12" +"@csstools/cascade-layer-name-parser@npm:^1.0.13": + version: 1.0.13 + resolution: "@csstools/cascade-layer-name-parser@npm:1.0.13" peerDependencies: - "@csstools/css-parser-algorithms": ^2.7.0 - "@csstools/css-tokenizer": ^2.3.2 - checksum: 10c0/5f92aefcbb3f4b660cf7b0db54f6a4ba21a32fa1b64ea4f050a6370233152d4f561ecf5c8e98ca231e73c16e0d9f75b20b0a65153e18b14957658c81e0f68213 + "@csstools/css-parser-algorithms": ^2.7.1 + "@csstools/css-tokenizer": ^2.4.1 + checksum: 10c0/a6412fc8601af1baadc8195934aa668d3476e799891c9d0883390f31ec8678e9b565ac14d919bec633bbc086657ac12aa4cd852c718851a2d34517ee6856ff8e languageName: node linkType: hard @@ -1575,52 +1575,52 @@ __metadata: languageName: node linkType: hard -"@csstools/css-calc@npm:^1.2.3": - version: 1.2.3 - resolution: "@csstools/css-calc@npm:1.2.3" +"@csstools/css-calc@npm:^1.2.4": + version: 1.2.4 + resolution: "@csstools/css-calc@npm:1.2.4" peerDependencies: - "@csstools/css-parser-algorithms": ^2.7.0 - "@csstools/css-tokenizer": ^2.3.2 - checksum: 10c0/fb34767ea9638b837167bcecaf945bcc0c5e8f0d811067c4e8c7a57bc8f0955f61107b1ed5e017b95c54acacc8088473e5497a9986bee95b37ec92999e792871 + "@csstools/css-parser-algorithms": ^2.7.1 + "@csstools/css-tokenizer": ^2.4.1 + checksum: 10c0/6233746eb642797b7fbc2cf6e7651e95700b294e78e3c29e8730c3236bb92cf62903efb6e54639e8f877683c40646e137c95e615c4450809b21b61a6192888ca languageName: node linkType: hard -"@csstools/css-color-parser@npm:^2.0.3": - version: 2.0.3 - resolution: "@csstools/css-color-parser@npm:2.0.3" +"@csstools/css-color-parser@npm:^2.0.4": + version: 2.0.4 + resolution: "@csstools/css-color-parser@npm:2.0.4" dependencies: "@csstools/color-helpers": "npm:^4.2.1" - "@csstools/css-calc": "npm:^1.2.3" + "@csstools/css-calc": "npm:^1.2.4" peerDependencies: - "@csstools/css-parser-algorithms": ^2.7.0 - "@csstools/css-tokenizer": ^2.3.2 - checksum: 10c0/d8860e6b9c65de4f90d4c21e4d66471fd858434cf63af80f812a900371343b753b86a256627e8bd024cb8903a6a0181d2d9c0c65ab5d78cf29d084a761e2adba + "@csstools/css-parser-algorithms": ^2.7.1 + "@csstools/css-tokenizer": ^2.4.1 + checksum: 10c0/e009a2f34b6c328daad54262deb86b71c6a7a9a1da1db8ad39cf719641e1a728ed8ddbd23613d519d26deee33b89ba12cb15a6928718c1b3cc5e24ac1ed02f47 languageName: node linkType: hard -"@csstools/css-parser-algorithms@npm:^2.6.3, @csstools/css-parser-algorithms@npm:^2.7.0": - version: 2.7.0 - resolution: "@csstools/css-parser-algorithms@npm:2.7.0" +"@csstools/css-parser-algorithms@npm:^2.6.3, @csstools/css-parser-algorithms@npm:^2.7.1": + version: 2.7.1 + resolution: "@csstools/css-parser-algorithms@npm:2.7.1" peerDependencies: - "@csstools/css-tokenizer": ^2.3.2 - checksum: 10c0/fb84fefdf37c41d170f81b687bf1ee1847a970e51cc1fe3a320e3eaf225383ae9a3c4eb6208b83357dfe18c5114353d780e0c65f05d86d6435e5a9ad9334c834 + "@csstools/css-tokenizer": ^2.4.1 + checksum: 10c0/7d29bef6f5790ddb67d922ad232253bf910e4fa5293f5e4a5ed8b920ae9bd4e8171942df7d8943af23b42fd4e9fb460181394d20c97da9562e6ce98a875e8c47 languageName: node linkType: hard -"@csstools/css-tokenizer@npm:^2.3.1, @csstools/css-tokenizer@npm:^2.3.2": - version: 2.3.2 - resolution: "@csstools/css-tokenizer@npm:2.3.2" - checksum: 10c0/f7d0d8b3e9e2dcdc6547a387253a09dbbacaaffb5c8718bcd7f15dddeefdd441b73fc5f9fad3f03fabef3b37ec4b62be7ff79caab366427fa90eaf54cd8fc452 +"@csstools/css-tokenizer@npm:^2.3.1, @csstools/css-tokenizer@npm:^2.4.1": + version: 2.4.1 + resolution: "@csstools/css-tokenizer@npm:2.4.1" + checksum: 10c0/fe71cee85ec7372da07083d088b6a704f43e5d3d2d8071c4b8a86fae60408b559a218a43f8625bf2f0be5c7f90c8f3ad20a1aae1921119a1c02b51c310cc2b6b languageName: node linkType: hard -"@csstools/media-query-list-parser@npm:^2.1.11, @csstools/media-query-list-parser@npm:^2.1.12": - version: 2.1.12 - resolution: "@csstools/media-query-list-parser@npm:2.1.12" +"@csstools/media-query-list-parser@npm:^2.1.11, @csstools/media-query-list-parser@npm:^2.1.13": + version: 2.1.13 + resolution: "@csstools/media-query-list-parser@npm:2.1.13" peerDependencies: - "@csstools/css-parser-algorithms": ^2.7.0 - "@csstools/css-tokenizer": ^2.3.2 - checksum: 10c0/7395cc710d8f54670c1e7a418a88dcf1ae726316272294ec645f6d79a8e931f5d390ba7ed5d0141d29ad7280cd447b8773143dc7676659413de79228130e1a65 + "@csstools/css-parser-algorithms": ^2.7.1 + "@csstools/css-tokenizer": ^2.4.1 + checksum: 10c0/8bf72342c15581b8f658633436d83c26a214056f6b960ff121b940271f4b1b5b07e9cc3990a73e684fb72319592f0c392408b4f0e08bbe242b2065aa456e2733 languageName: node linkType: hard @@ -1636,46 +1636,60 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-color-function@npm:^3.0.17": - version: 3.0.17 - resolution: "@csstools/postcss-color-function@npm:3.0.17" +"@csstools/postcss-color-function@npm:^3.0.19": + version: 3.0.19 + resolution: "@csstools/postcss-color-function@npm:3.0.19" dependencies: - "@csstools/css-color-parser": "npm:^2.0.3" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/6d347fc9fe65cb897c275c129103576e551b74a7c47a1a4dc8160da2fad7752bf51e3cfbff339f86b39c723efac33643168d2dfaac4d3624d072875d18a65a4b + checksum: 10c0/067e33d7dfc32b56fe63d4f97464a3eaf27dde720961e44feab6076bd2c172dd4c1bad16aa37a922dcbba470756bd6a13e728d9e71eab6937d48d83873cd1879 languageName: node linkType: hard -"@csstools/postcss-color-mix-function@npm:^2.0.17": - version: 2.0.17 - resolution: "@csstools/postcss-color-mix-function@npm:2.0.17" +"@csstools/postcss-color-mix-function@npm:^2.0.19": + version: 2.0.19 + resolution: "@csstools/postcss-color-mix-function@npm:2.0.19" dependencies: - "@csstools/css-color-parser": "npm:^2.0.3" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/ba9a406ebe4caba6709878ee26debb06780be5cbf4e6ab7e902d79ca6e21ec6a8409b9dc0a5ef36fc4bf54bf2bd8f9642b72da8d7939145f99dc40fedd2be9d2 + checksum: 10c0/e967d93672a065806dc78da0153f8b4f5087f7c3ddfe361eba4942780760d47b317124913c9b0dda7f9bfff1253f77d1b6debd8a6a2aa3a6c80e263101da5e8c languageName: node linkType: hard -"@csstools/postcss-exponential-functions@npm:^1.0.8": - version: 1.0.8 - resolution: "@csstools/postcss-exponential-functions@npm:1.0.8" +"@csstools/postcss-content-alt-text@npm:^1.0.0": + version: 1.0.0 + resolution: "@csstools/postcss-content-alt-text@npm:1.0.0" dependencies: - "@csstools/css-calc": "npm:^1.2.3" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" + "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/6b049801fc1275b34f43ffbb915f447a54cbff7bf48ab0705c3ad1ffde055cb876c4dc24e7a9162cd65e219457328e298a673f6176446493db17cf7af6f90dc0 + checksum: 10c0/0c2c64857ac652989d00c3d2ba49d0cd1cc245193cba6724d2f5841aa990ee6a07267cfebc6fabde6a6246616df60373006d17c5ea9b904129fbfd826dc10a8d + languageName: node + linkType: hard + +"@csstools/postcss-exponential-functions@npm:^1.0.9": + version: 1.0.9 + resolution: "@csstools/postcss-exponential-functions@npm:1.0.9" + dependencies: + "@csstools/css-calc": "npm:^1.2.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + peerDependencies: + postcss: ^8.4 + checksum: 10c0/eaec29ef6ec201786c606176235dced4af1922d5ac56c6b0993ad2e7d87464a32702d9b28cae9a76e8527f741b50cbc31d4c646f45d02dc69d520f241b3e7878 languageName: node linkType: hard @@ -1691,59 +1705,59 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-gamut-mapping@npm:^1.0.10": - version: 1.0.10 - resolution: "@csstools/postcss-gamut-mapping@npm:1.0.10" +"@csstools/postcss-gamut-mapping@npm:^1.0.11": + version: 1.0.11 + resolution: "@csstools/postcss-gamut-mapping@npm:1.0.11" dependencies: - "@csstools/css-color-parser": "npm:^2.0.3" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" peerDependencies: postcss: ^8.4 - checksum: 10c0/6c2dab6a84f81904bed89cb584bd9bc6a904b49a4fa315b17be65c7d68baefe592561ee439660d5602b7481bac3be9a93189dc45404764524495400f34c6b6e6 + checksum: 10c0/29e755013f1d1de34eb62a931ed410d2830ca3dfc81476cb3c72d9d3260b85a9adedc51aa548550c6e308f3f9640c489e6953db40e9cac9835d0421d5b14ef1f languageName: node linkType: hard -"@csstools/postcss-gradients-interpolation-method@npm:^4.0.18": - version: 4.0.18 - resolution: "@csstools/postcss-gradients-interpolation-method@npm:4.0.18" +"@csstools/postcss-gradients-interpolation-method@npm:^4.0.20": + version: 4.0.20 + resolution: "@csstools/postcss-gradients-interpolation-method@npm:4.0.20" dependencies: - "@csstools/css-color-parser": "npm:^2.0.3" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/23c431068ac205392b4953dbce411e208e79e221ba8030c5e23c0b82e8fd53bc3bc4f2cdc47050f5d91a4ac69cb80f4f1853b213aa8072fa60a6cb6ff0621e04 + checksum: 10c0/6588825a72a1471e2d6036c8cf7dbad2bf05f369d96dbdd68ff5ce7ff91803b8ee1146f5f1bf6f3ab6299944549da872914664c3f9e8ae5a31847f76f0085c74 languageName: node linkType: hard -"@csstools/postcss-hwb-function@npm:^3.0.16": - version: 3.0.16 - resolution: "@csstools/postcss-hwb-function@npm:3.0.16" +"@csstools/postcss-hwb-function@npm:^3.0.18": + version: 3.0.18 + resolution: "@csstools/postcss-hwb-function@npm:3.0.18" dependencies: - "@csstools/css-color-parser": "npm:^2.0.3" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/4deca8831a69038aff719a77df92c53578bb28e23cc61dc4ea7b1d912b1b685683a9c6232396c2616948ac2e8488ad1e2009c9c8ed30c493d97ba8ad37b6418d + checksum: 10c0/e9d76b0b2f9c54920124ca1804b49e3f5b26e003729418b5ef4b340ff1baa4779da1c02be618888fdbcc2d0747182352efbbd3ffe128e2417928c35c25443789 languageName: node linkType: hard -"@csstools/postcss-ic-unit@npm:^3.0.6": - version: 3.0.6 - resolution: "@csstools/postcss-ic-unit@npm:3.0.6" +"@csstools/postcss-ic-unit@npm:^3.0.7": + version: 3.0.7 + resolution: "@csstools/postcss-ic-unit@npm:3.0.7" dependencies: - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/a4b962327d433419fdcfdcf620ce6a5cf09aa3c93029ad08b035df1e2bc35caae31de49f1d14218de0656fced35c0d2e07e5ff7b8099c29dbfb40395fc283234 + checksum: 10c0/2add905b75860c64d7174886fecfc76d86e3818f42f003f4bbfc0604cc7f0f31c6dbd1651e6b9512fea876190d80033578ae49e813b64b17c8cf3b1f03d8e146 languageName: node linkType: hard @@ -1768,17 +1782,17 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-light-dark-function@npm:^1.0.6": - version: 1.0.6 - resolution: "@csstools/postcss-light-dark-function@npm:1.0.6" +"@csstools/postcss-light-dark-function@npm:^1.0.8": + version: 1.0.8 + resolution: "@csstools/postcss-light-dark-function@npm:1.0.8" dependencies: - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/6b2c64860d789cd3e3ce875c01259333911f6e32a751a7475604de8022c13abcb578e5cb941b51bd3a2022bee883df3f6b64800c6e3559b06da283d968aeb615 + checksum: 10c0/78fa6d799d38f14af1b32b534eedbec9478033e1fbc5a4e820f2421e865673d010b69b391546686ceb408ead64d79bb4eba2a4fb1fc9f0de70ff21e3ff8477c6 languageName: node linkType: hard @@ -1820,42 +1834,42 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-logical-viewport-units@npm:^2.0.10": - version: 2.0.10 - resolution: "@csstools/postcss-logical-viewport-units@npm:2.0.10" +"@csstools/postcss-logical-viewport-units@npm:^2.0.11": + version: 2.0.11 + resolution: "@csstools/postcss-logical-viewport-units@npm:2.0.11" dependencies: - "@csstools/css-tokenizer": "npm:^2.3.2" + "@csstools/css-tokenizer": "npm:^2.4.1" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/fe142b11e0e8ccab4667cc5db90b45e67b7d11eaf5c038e91d867e1b18a315ef0859114185aeb48fdc1ce05986be8b644d6157fe9e19da7281f7023c99eb8877 + checksum: 10c0/20207e9b7fc3ab52df5fcd06fde71fca4fd22bd6bd451cfc2ec6ea69994708b7fc5381e203dc4367293a8de00b1eca7a3ebe89cfa9b933d2f2cb8e3ac4d5aa86 languageName: node linkType: hard -"@csstools/postcss-media-minmax@npm:^1.1.7": - version: 1.1.7 - resolution: "@csstools/postcss-media-minmax@npm:1.1.7" +"@csstools/postcss-media-minmax@npm:^1.1.8": + version: 1.1.8 + resolution: "@csstools/postcss-media-minmax@npm:1.1.8" dependencies: - "@csstools/css-calc": "npm:^1.2.3" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" - "@csstools/media-query-list-parser": "npm:^2.1.12" + "@csstools/css-calc": "npm:^1.2.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/media-query-list-parser": "npm:^2.1.13" peerDependencies: postcss: ^8.4 - checksum: 10c0/a02943a17b540cbd909b55bbb1f8c9331badc51b613279bbdb7127c9921a5d0675bb41675a3b4d0f15e9586120e5a96d9b9786b63b2c594fbb3a238e860c6ad8 + checksum: 10c0/7d666905282c7a89387dbce84f3429bad04870e0de264c5b1ce3e6f042b8eb72d585a18b2d7ac5e1a8c7f6785892da3cc7f6ea0b48069b06e9d383bdbc149b4a languageName: node linkType: hard -"@csstools/postcss-media-queries-aspect-ratio-number-values@npm:^2.0.10": - version: 2.0.10 - resolution: "@csstools/postcss-media-queries-aspect-ratio-number-values@npm:2.0.10" +"@csstools/postcss-media-queries-aspect-ratio-number-values@npm:^2.0.11": + version: 2.0.11 + resolution: "@csstools/postcss-media-queries-aspect-ratio-number-values@npm:2.0.11" dependencies: - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" - "@csstools/media-query-list-parser": "npm:^2.1.12" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/media-query-list-parser": "npm:^2.1.13" peerDependencies: postcss: ^8.4 - checksum: 10c0/d7879e72df98d9fe2e5d85a64837e7a73c2df1aea8659d65516f0acb070317edd353531882f0bdfd81510703d1da30d6da861052a0bda85fde1f9eab94b1e467 + checksum: 10c0/b4023a1951b7661196332852ce714a4e2fb4f1a67164ec0944e28a009b389e59c67e9de790920fcd082b122276414dd39c12ae12a4566e59e1bbcc794560a870 languageName: node linkType: hard @@ -1882,44 +1896,44 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-oklab-function@npm:^3.0.17": - version: 3.0.17 - resolution: "@csstools/postcss-oklab-function@npm:3.0.17" +"@csstools/postcss-oklab-function@npm:^3.0.19": + version: 3.0.19 + resolution: "@csstools/postcss-oklab-function@npm:3.0.19" dependencies: - "@csstools/css-color-parser": "npm:^2.0.3" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/ff27a4b6fd8490439aa0f3c91ffa2a42a8cf539d7306d9329cef7ca59f28317cee40253f402d19a18c196471fd39a05842d2974d92f1b131dc748074d91ac4ee + checksum: 10c0/2909f76ba408c9f60b61c479994c96200b0e1d3dbf524d5ae6dc5ca1e21d38caf974595e0d071c3900dbe3568376928085dd811aa24ea3e715bcd9de26fb0fa9 languageName: node linkType: hard -"@csstools/postcss-progressive-custom-properties@npm:^3.2.0": - version: 3.2.0 - resolution: "@csstools/postcss-progressive-custom-properties@npm:3.2.0" +"@csstools/postcss-progressive-custom-properties@npm:^3.3.0": + version: 3.3.0 + resolution: "@csstools/postcss-progressive-custom-properties@npm:3.3.0" dependencies: postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/829880844fbbeef1c67e0b380057e574659b4caed38c8414c17d7eb4a0cc727afa1cd74a889bc7ca79c819ecae757810356706901cf6bb677a36ca123915cbb7 + checksum: 10c0/6c9987d65049a70b5090dcfe42fde9ab2b3cb88911a81bb6651ed81c8baf99502ff2cbec0cb3e022426fa994b558b4bf33fd791ccdcdf683dde75b4865d34f39 languageName: node linkType: hard -"@csstools/postcss-relative-color-syntax@npm:^2.0.17": - version: 2.0.17 - resolution: "@csstools/postcss-relative-color-syntax@npm:2.0.17" +"@csstools/postcss-relative-color-syntax@npm:^2.0.19": + version: 2.0.19 + resolution: "@csstools/postcss-relative-color-syntax@npm:2.0.19" dependencies: - "@csstools/css-color-parser": "npm:^2.0.3" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/46226351b3825323e3496dcee44ff354cd3ccc9241d837659e1311f428f0b4dc878d9bb762cbb8f63243b7af346728ab7a46c311f9dc38bb609147523c698eab + checksum: 10c0/f0aff764f4889ff664b6fa94ddfa5a22daf39354aa2d2ac0eab893eb3ed841b7d2a72131393334d6a5379445fc80f92ab5bd63d4dc3b43746bc7c9055da46591 languageName: node linkType: hard @@ -1934,16 +1948,16 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-stepped-value-functions@npm:^3.0.9": - version: 3.0.9 - resolution: "@csstools/postcss-stepped-value-functions@npm:3.0.9" +"@csstools/postcss-stepped-value-functions@npm:^3.0.10": + version: 3.0.10 + resolution: "@csstools/postcss-stepped-value-functions@npm:3.0.10" dependencies: - "@csstools/css-calc": "npm:^1.2.3" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" + "@csstools/css-calc": "npm:^1.2.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" peerDependencies: postcss: ^8.4 - checksum: 10c0/bafe80947abc8613903f1f3f1939ece9780696774f15960aef229733e40e483dc2830145426d49c4f6d0b1dabb35f812c8a2dda0d0dcddc930321e36b5c6ca0b + checksum: 10c0/f9ebe50fb884d002aa40070196a827816f635b891fd2147ae5ddf1ad6df5bddbb50783d6786897bb3dffa33052565e38289392040cf4454aaa179ab00353117d languageName: node linkType: hard @@ -1959,16 +1973,16 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-trigonometric-functions@npm:^3.0.9": - version: 3.0.9 - resolution: "@csstools/postcss-trigonometric-functions@npm:3.0.9" +"@csstools/postcss-trigonometric-functions@npm:^3.0.10": + version: 3.0.10 + resolution: "@csstools/postcss-trigonometric-functions@npm:3.0.10" dependencies: - "@csstools/css-calc": "npm:^1.2.3" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" + "@csstools/css-calc": "npm:^1.2.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" peerDependencies: postcss: ^8.4 - checksum: 10c0/7a439d31a63d35986dab634d9e415f7ce7c32a2d3d382052b5b730a259a12e44c5f1b14e318d79086253e3d5d4f7d942d0e7317d92eb3421dd08824eebec45fb + checksum: 10c0/31adcc66510d9788ccb0669d2761517a6135b13692007d8e4334bc0e8d3515dfecfbdcd04e060d0c09a0f5fc2f12db92221b9d53e92b65b044c89cde9a3424cb languageName: node linkType: hard @@ -3376,8 +3390,8 @@ __metadata: linkType: hard "@testing-library/dom@npm:^10.2.0": - version: 10.2.0 - resolution: "@testing-library/dom@npm:10.2.0" + version: 10.3.1 + resolution: "@testing-library/dom@npm:10.3.1" dependencies: "@babel/code-frame": "npm:^7.10.4" "@babel/runtime": "npm:^7.12.5" @@ -3387,7 +3401,7 @@ __metadata: dom-accessibility-api: "npm:^0.5.9" lz-string: "npm:^1.5.0" pretty-format: "npm:^27.0.2" - checksum: 10c0/de582dfbeb632436547a0ca5851b5a714a4a17f8e96ab3dc4fb4e454eef52c912b648b7cb6e9fdf477f3eeef97e698f3250f0ce50846f39d04677a44169209f2 + checksum: 10c0/e898475cd4932225c2962bf9f94353d7d88462c8912881af8e9866cee714c967b21badb0895ec8626123759cddc6663bc40300b1d1bf789957a603086eda6329 languageName: node linkType: hard @@ -5681,7 +5695,7 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.0.0, browserslist@npm:^4.22.2, browserslist@npm:^4.23.0, browserslist@npm:^4.23.1": +"browserslist@npm:^4.0.0, browserslist@npm:^4.23.0, browserslist@npm:^4.23.1": version: 4.23.1 resolution: "browserslist@npm:4.23.1" dependencies: @@ -6397,12 +6411,12 @@ __metadata: languageName: node linkType: hard -"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.36.1": - version: 3.36.1 - resolution: "core-js-compat@npm:3.36.1" +"core-js-compat@npm:^3.36.1, core-js-compat@npm:^3.37.1": + version: 3.37.1 + resolution: "core-js-compat@npm:3.37.1" dependencies: browserslist: "npm:^4.23.0" - checksum: 10c0/70fba18a4095cd8ac04e5ba8cee251e328935859cf2851c1f67770068ea9f9fe71accb1b7de17cd3c9a28d304a4c41712bd9aa895110ebb6e3be71b666b029d1 + checksum: 10c0/4e2da9c900f2951a57947af7aeef4d16f2c75d7f7e966c0d0b62953f65225003ade5e84d3ae98847f65b24c109c606821d9dc925db8ca418fb761e7c81963c2a languageName: node linkType: hard @@ -6754,10 +6768,10 @@ __metadata: languageName: node linkType: hard -"cssdb@npm:^8.0.0": - version: 8.0.0 - resolution: "cssdb@npm:8.0.0" - checksum: 10c0/d9a31b760214624352000b16a8f7194c357f66b6c445e663ab58dd03b6f0f53efaaca6d6f96200d666e205894d2d1c346664ad993d9522ff9fc1c331804a8d62 +"cssdb@npm:^8.1.0": + version: 8.1.0 + resolution: "cssdb@npm:8.1.0" + checksum: 10c0/1fa1f1566c7e9964f5c71e443583eaba16a90933a3ef6803815c4281d084b75da948c415bade33d7085894fe0929c082fcb3135bf4400048cfff40d227ebd5dd languageName: node linkType: hard @@ -6770,16 +6784,16 @@ __metadata: languageName: node linkType: hard -"cssnano-preset-default@npm:^7.0.3": - version: 7.0.3 - resolution: "cssnano-preset-default@npm:7.0.3" +"cssnano-preset-default@npm:^7.0.4": + version: 7.0.4 + resolution: "cssnano-preset-default@npm:7.0.4" dependencies: 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.1" - postcss-convert-values: "npm:^7.0.1" + postcss-convert-values: "npm:^7.0.2" postcss-discard-comments: "npm:^7.0.1" postcss-discard-duplicates: "npm:^7.0.0" postcss-discard-empty: "npm:^7.0.0" @@ -6806,7 +6820,7 @@ __metadata: postcss-unique-selectors: "npm:^7.0.1" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/ab3e51003efed6542a12d43c10ca693ab26138a1d035697b9be8f07e084e37a78617cbb8028b0a7e7841302ec151f4ecf35cbd763efe291846b62c35ea4c0bb4 + checksum: 10c0/0083821e778bdf7b8aa9589408a01a717be730f73584e7b81756a6fcf87af05b8f17342025e666572a8d573cc30783f2d817b0f7ad63670398bc3135b017ccad languageName: node linkType: hard @@ -6820,14 +6834,14 @@ __metadata: linkType: hard "cssnano@npm:^7.0.0": - version: 7.0.3 - resolution: "cssnano@npm:7.0.3" + version: 7.0.4 + resolution: "cssnano@npm:7.0.4" dependencies: - cssnano-preset-default: "npm:^7.0.3" + cssnano-preset-default: "npm:^7.0.4" lilconfig: "npm:^3.1.2" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/4cbcd1e0ebe0bd83196cc5b16b3a60d3ebc98326c79b2f71df597bb73c8e3ee1f42b89159d7a038acc398251184d648d9dd516f4194e46746f3af6fa74b4aec7 + checksum: 10c0/3939a0b37b11cb4bae92f7916517c7ba21257551f92517b49a640d5df32e855fb7e73321f4be44d2c2de578309c05d711cdcb1976e95607b1b7f92bd4cbd1350 languageName: node linkType: hard @@ -9023,8 +9037,8 @@ __metadata: linkType: hard "glob@npm:^10.2.2, glob@npm:^10.2.6, glob@npm:^10.3.10": - version: 10.4.2 - resolution: "glob@npm:10.4.2" + version: 10.4.5 + resolution: "glob@npm:10.4.5" dependencies: foreground-child: "npm:^3.1.0" jackspeak: "npm:^3.1.2" @@ -9034,7 +9048,7 @@ __metadata: path-scurry: "npm:^1.11.1" bin: glob: dist/esm/bin.mjs - checksum: 10c0/2c7296695fa75a935f3ad17dc62e4e170a8bb8752cf64d328be8992dd6ad40777939003754e10e9741ff8fbe43aa52fba32d6930d0ffa0e3b74bc3fb5eebaa2f + checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e languageName: node linkType: hard @@ -13314,18 +13328,18 @@ __metadata: languageName: node linkType: hard -"postcss-color-functional-notation@npm:^6.0.12": - version: 6.0.12 - resolution: "postcss-color-functional-notation@npm:6.0.12" +"postcss-color-functional-notation@npm:^6.0.14": + version: 6.0.14 + resolution: "postcss-color-functional-notation@npm:6.0.14" dependencies: - "@csstools/css-color-parser": "npm:^2.0.3" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/2e8faecd2609e1b4eb8c1cab21ecca5e746916795df20e6997d66eb61c29fbb01d3e75fef3e0b3e1c181918a2186570441b81779b1fc429d6d8823fbfa164231 + checksum: 10c0/fdc5188e19c3923da32fe08d50e55d0b3ca1cedf99f46331baa0a4bbd73a1fc6b4447b0346ab16049032b56ab84b98b4758a0ede7c237637e35a4cc60caac141 languageName: node linkType: hard @@ -13367,58 +13381,58 @@ __metadata: languageName: node linkType: hard -"postcss-convert-values@npm:^7.0.1": - version: 7.0.1 - resolution: "postcss-convert-values@npm:7.0.1" +"postcss-convert-values@npm:^7.0.2": + version: 7.0.2 + resolution: "postcss-convert-values@npm:7.0.2" dependencies: browserslist: "npm:^4.23.1" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4.31 - checksum: 10c0/612f025f179f0f2ad7365db8c0b423614dcb8e1e4061875a4691a39dede0bca758d1a8f9f5c8b08e12af053e9e884f65ca5626ccc723d5b3f420650d67fe3046 + checksum: 10c0/beb59faf6aae97e6d3c233c5e6ed06cc60d65c49eec576036e3d0da1a831a1e827e3d41f5e81d016440b4f0bdf1406268ae069c4d5b38a6667b310c3da079d22 languageName: node linkType: hard -"postcss-custom-media@npm:^10.0.7": - version: 10.0.7 - resolution: "postcss-custom-media@npm:10.0.7" +"postcss-custom-media@npm:^10.0.8": + version: 10.0.8 + resolution: "postcss-custom-media@npm:10.0.8" dependencies: - "@csstools/cascade-layer-name-parser": "npm:^1.0.12" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" - "@csstools/media-query-list-parser": "npm:^2.1.12" + "@csstools/cascade-layer-name-parser": "npm:^1.0.13" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/media-query-list-parser": "npm:^2.1.13" peerDependencies: postcss: ^8.4 - checksum: 10c0/4171385ab9370806861dcf7597e53fd6aa1862e77b475c9c565c95bfcc2b950f920f8da26a6dbec42e257388bca97c274635662b5e81fe3905b5e37babe06569 + checksum: 10c0/673ca0058a2f2357a83b33ce00bbeee7cda92621c08472fa55d7ac7ae56f5f8f979132528d537f2dedf715d35a8f9b14b2f0ab6b45423d49e2554c19aab3c827 languageName: node linkType: hard -"postcss-custom-properties@npm:^13.3.11": - version: 13.3.11 - resolution: "postcss-custom-properties@npm:13.3.11" +"postcss-custom-properties@npm:^13.3.12": + version: 13.3.12 + resolution: "postcss-custom-properties@npm:13.3.12" dependencies: - "@csstools/cascade-layer-name-parser": "npm:^1.0.12" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" + "@csstools/cascade-layer-name-parser": "npm:^1.0.13" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" "@csstools/utilities": "npm:^1.0.0" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/4aa95628aa5d5b6df4dfeedbc3891b9666db88d75930cadc14d2fbba0a1b72f4e3cc3d83b5a0c0b8ce44f85b4fda6ebd7fe7792a1abc0a14d7d63b9f170d299c + checksum: 10c0/6af9f6ac94a6ac887749cd38d4586349f6aca29269ebfdb837019a3ba0130032f0ff4899b431b5c348f4ac79a7b16fb7300a256514a6a68e32a63489c18a70e7 languageName: node linkType: hard -"postcss-custom-selectors@npm:^7.1.11": - version: 7.1.11 - resolution: "postcss-custom-selectors@npm:7.1.11" +"postcss-custom-selectors@npm:^7.1.12": + version: 7.1.12 + resolution: "postcss-custom-selectors@npm:7.1.12" dependencies: - "@csstools/cascade-layer-name-parser": "npm:^1.0.12" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" + "@csstools/cascade-layer-name-parser": "npm:^1.0.13" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" postcss-selector-parser: "npm:^6.1.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/f37d2e34239e868b35b7970ec97a7a8f657a9f92ed2b221af44f19949f7c3aedcecd0abb5fa1acb120c5ceffdf7a20869338956a37d7bfc37a83d8088f5d3dd2 + checksum: 10c0/78a7930e4f97c42b544f00c06272264432d47f9df777684b57673bb971b7ab49d5d6fb9289a5a869125e7e50dcd0cad65cf8846501253084b73a42ffab41b2c5 languageName: node linkType: hard @@ -13471,16 +13485,16 @@ __metadata: languageName: node linkType: hard -"postcss-double-position-gradients@npm:^5.0.6": - version: 5.0.6 - resolution: "postcss-double-position-gradients@npm:5.0.6" +"postcss-double-position-gradients@npm:^5.0.7": + version: 5.0.7 + resolution: "postcss-double-position-gradients@npm:5.0.7" dependencies: - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/9b24b13043fe506c0ddd94e707fe4f21f4f9a6c05ca49a4f45e23412951fd6a4cfa0095002d10b322ca8be60df0badae3715a27eefdeb7bf8da4fdd1ecd5d7a2 + checksum: 10c0/52d96a34aa3e2e251edeaa2d4c2dd106c687f7910ec18266693656c0edd003384b927c855cecac07f52b5c7bdccd140abdc7e27082ce4c3755e3a966206a2cb9 languageName: node linkType: hard @@ -13536,18 +13550,18 @@ __metadata: languageName: node linkType: hard -"postcss-lab-function@npm:^6.0.17": - version: 6.0.17 - resolution: "postcss-lab-function@npm:6.0.17" +"postcss-lab-function@npm:^6.0.19": + version: 6.0.19 + resolution: "postcss-lab-function@npm:6.0.19" dependencies: - "@csstools/css-color-parser": "npm:^2.0.3" - "@csstools/css-parser-algorithms": "npm:^2.7.0" - "@csstools/css-tokenizer": "npm:^2.3.2" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/a331f188b02cc8beb315150232b6b58bc5793e8d61585973d352a9b4d370b908ff354ccf9ea1ba20a956fd37ea4ada918ea975c8d4f69e850d26edf0106436e8 + checksum: 10c0/d9a91fb57dcbe967260df86e22ca335a5444f1f34d128fa7b5dbf2522772f2138ad708f1f20f0a59035d66ed736e82972ca7f1b669a157534a17ee8898af1921 languageName: node linkType: hard @@ -13868,60 +13882,61 @@ __metadata: linkType: hard "postcss-preset-env@npm:^9.5.2": - version: 9.5.15 - resolution: "postcss-preset-env@npm:9.5.15" + version: 9.6.0 + resolution: "postcss-preset-env@npm:9.6.0" dependencies: "@csstools/postcss-cascade-layers": "npm:^4.0.6" - "@csstools/postcss-color-function": "npm:^3.0.17" - "@csstools/postcss-color-mix-function": "npm:^2.0.17" - "@csstools/postcss-exponential-functions": "npm:^1.0.8" + "@csstools/postcss-color-function": "npm:^3.0.19" + "@csstools/postcss-color-mix-function": "npm:^2.0.19" + "@csstools/postcss-content-alt-text": "npm:^1.0.0" + "@csstools/postcss-exponential-functions": "npm:^1.0.9" "@csstools/postcss-font-format-keywords": "npm:^3.0.2" - "@csstools/postcss-gamut-mapping": "npm:^1.0.10" - "@csstools/postcss-gradients-interpolation-method": "npm:^4.0.18" - "@csstools/postcss-hwb-function": "npm:^3.0.16" - "@csstools/postcss-ic-unit": "npm:^3.0.6" + "@csstools/postcss-gamut-mapping": "npm:^1.0.11" + "@csstools/postcss-gradients-interpolation-method": "npm:^4.0.20" + "@csstools/postcss-hwb-function": "npm:^3.0.18" + "@csstools/postcss-ic-unit": "npm:^3.0.7" "@csstools/postcss-initial": "npm:^1.0.1" "@csstools/postcss-is-pseudo-class": "npm:^4.0.8" - "@csstools/postcss-light-dark-function": "npm:^1.0.6" + "@csstools/postcss-light-dark-function": "npm:^1.0.8" "@csstools/postcss-logical-float-and-clear": "npm:^2.0.1" "@csstools/postcss-logical-overflow": "npm:^1.0.1" "@csstools/postcss-logical-overscroll-behavior": "npm:^1.0.1" "@csstools/postcss-logical-resize": "npm:^2.0.1" - "@csstools/postcss-logical-viewport-units": "npm:^2.0.10" - "@csstools/postcss-media-minmax": "npm:^1.1.7" - "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^2.0.10" + "@csstools/postcss-logical-viewport-units": "npm:^2.0.11" + "@csstools/postcss-media-minmax": "npm:^1.1.8" + "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^2.0.11" "@csstools/postcss-nested-calc": "npm:^3.0.2" "@csstools/postcss-normalize-display-values": "npm:^3.0.2" - "@csstools/postcss-oklab-function": "npm:^3.0.17" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" - "@csstools/postcss-relative-color-syntax": "npm:^2.0.17" + "@csstools/postcss-oklab-function": "npm:^3.0.19" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" + "@csstools/postcss-relative-color-syntax": "npm:^2.0.19" "@csstools/postcss-scope-pseudo-class": "npm:^3.0.1" - "@csstools/postcss-stepped-value-functions": "npm:^3.0.9" + "@csstools/postcss-stepped-value-functions": "npm:^3.0.10" "@csstools/postcss-text-decoration-shorthand": "npm:^3.0.7" - "@csstools/postcss-trigonometric-functions": "npm:^3.0.9" + "@csstools/postcss-trigonometric-functions": "npm:^3.0.10" "@csstools/postcss-unset-value": "npm:^3.0.1" autoprefixer: "npm:^10.4.19" browserslist: "npm:^4.23.1" css-blank-pseudo: "npm:^6.0.2" css-has-pseudo: "npm:^6.0.5" css-prefers-color-scheme: "npm:^9.0.1" - cssdb: "npm:^8.0.0" + cssdb: "npm:^8.1.0" postcss-attribute-case-insensitive: "npm:^6.0.3" postcss-clamp: "npm:^4.1.0" - postcss-color-functional-notation: "npm:^6.0.12" + postcss-color-functional-notation: "npm:^6.0.14" postcss-color-hex-alpha: "npm:^9.0.4" postcss-color-rebeccapurple: "npm:^9.0.3" - postcss-custom-media: "npm:^10.0.7" - postcss-custom-properties: "npm:^13.3.11" - postcss-custom-selectors: "npm:^7.1.11" + postcss-custom-media: "npm:^10.0.8" + postcss-custom-properties: "npm:^13.3.12" + postcss-custom-selectors: "npm:^7.1.12" postcss-dir-pseudo-class: "npm:^8.0.1" - postcss-double-position-gradients: "npm:^5.0.6" + postcss-double-position-gradients: "npm:^5.0.7" postcss-focus-visible: "npm:^9.0.1" postcss-focus-within: "npm:^8.0.1" postcss-font-variant: "npm:^5.0.0" postcss-gap-properties: "npm:^5.0.1" postcss-image-set-function: "npm:^6.0.3" - postcss-lab-function: "npm:^6.0.17" + postcss-lab-function: "npm:^6.0.19" postcss-logical: "npm:^7.0.1" postcss-nesting: "npm:^12.1.5" postcss-opacity-percentage: "npm:^2.0.0" @@ -13933,7 +13948,7 @@ __metadata: postcss-selector-not: "npm:^7.0.2" peerDependencies: postcss: ^8.4 - checksum: 10c0/e2ee0b5d7dbaddb82ff6d51b5882120862d6be184973ae3d55642923183ab441d421d5f9810fe02e680a70dbc85b20b1c2eb02c68f167dcaf3ef80a71dd40e78 + checksum: 10c0/caa91ba4d3b897d43ab2669b3edf40b24ef32c88e23b113be8956412e64b28deed6ba229c331848fcbc0d143bfde155173fb1e1ada9ccae5037b2ee8f7e554b7 languageName: node linkType: hard @@ -15514,15 +15529,15 @@ __metadata: linkType: hard "sass@npm:^1.62.1": - version: 1.77.6 - resolution: "sass@npm:1.77.6" + version: 1.77.8 + resolution: "sass@npm:1.77.8" dependencies: chokidar: "npm:>=3.0.0 <4.0.0" immutable: "npm:^4.0.0" source-map-js: "npm:>=0.6.2 <2.0.0" bin: sass: sass.js - checksum: 10c0/fe5a393c0aa29eda9f83c06be9b94788b61fe8bad0616ee6e3a25d21ab504f430d40c0064fdca89b02b8e426411ae6dcd906c91f2e48c263575c3d392b6daeb1 + checksum: 10c0/2bfd62794070352c804f949e69bd8bb5b4ec846deeb924251b2c3f7b503170fb1ae186f513f0166907749eb34e0277dee747edcb78c886fb471aac01be1e864c languageName: node linkType: hard @@ -17349,22 +17364,22 @@ __metadata: linkType: hard "typescript@npm:5, typescript@npm:^5.0.4": - version: 5.5.2 - resolution: "typescript@npm:5.5.2" + version: 5.5.3 + resolution: "typescript@npm:5.5.3" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/8ca39b27b5f9bd7f32db795045933ab5247897660627251e8254180b792a395bf061ea7231947d5d7ffa5cb4cc771970fd4ef543275f9b559f08c9325cccfce3 + checksum: 10c0/f52c71ccbc7080b034b9d3b72051d563601a4815bf3e39ded188e6ce60813f75dbedf11ad15dd4d32a12996a9ed8c7155b46c93a9b9c9bad1049766fe614bbdd languageName: node linkType: hard "typescript@patch:typescript@npm%3A5#optional!builtin, typescript@patch:typescript@npm%3A^5.0.4#optional!builtin": - version: 5.5.2 - resolution: "typescript@patch:typescript@npm%3A5.5.2#optional!builtin::version=5.5.2&hash=379a07" + version: 5.5.3 + resolution: "typescript@patch:typescript@npm%3A5.5.3#optional!builtin::version=5.5.3&hash=379a07" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/a7b7ede75dc7fc32a76d0d0af6b91f5fbd8620890d84c906f663d8783bf3de6d7bd50f0430b8bb55eac88a38934af847ff709e7156e5138b95ae94cbd5f73e5b + checksum: 10c0/911c7811d61f57f07df79c4a35f56a0f426a65426a020e5fcd792f66559f399017205f5f10255329ab5a3d8c2d1f1d19530aeceffda70758a521fae1d469432e languageName: node linkType: hard