diff --git a/.github/renovate.json5 b/.github/renovate.json5 index a7998ddfdc..dab99829a1 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -99,6 +99,16 @@ matchUpdateTypes: ['patch', 'minor'], groupName: 'eslint (non-major)', }, + { + // Group actions/*-artifact in the same PR + matchManagers: ['github-actions'], + matchPackageNames: [ + 'actions/download-artifact', + 'actions/upload-artifact', + ], + matchUpdateTypes: ['major'], + groupName: 'artifact actions (major)', + }, { // Update @types/* packages every week, with one grouped PR matchPackagePrefixes: '@types/', diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml index 3be2a3d490..29646f28e8 100644 --- a/.haml-lint_todo.yml +++ b/.haml-lint_todo.yml @@ -1,33 +1,21 @@ # This configuration was generated by # `haml-lint --auto-gen-config` -# on 2023-10-26 09:32:34 -0400 using Haml-Lint version 0.51.0. +# on 2023-12-15 11:02:19 -0500 using Haml-Lint version 0.52.0. # The point is for the user to remove these configuration records # one by one as the lints are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of Haml-Lint, may require this file to be generated again. linters: - # Offense count: 16 + # Offense count: 11 LineLength: exclude: - - 'app/views/admin/account_actions/new.html.haml' - - 'app/views/admin/accounts/index.html.haml' - - 'app/views/admin/ip_blocks/new.html.haml' - 'app/views/admin/roles/_form.html.haml' - - 'app/views/admin/settings/discovery/show.html.haml' - 'app/views/auth/registrations/edit.html.haml' - 'app/views/auth/registrations/new.html.haml' - - 'app/views/filters/_filter_fields.html.haml' - 'app/views/media/player.html.haml' - 'app/views/settings/applications/_fields.html.haml' - 'app/views/settings/imports/index.html.haml' - 'app/views/settings/preferences/appearance/show.html.haml' - 'app/views/settings/preferences/notifications/show.html.haml' - 'app/views/settings/preferences/other/show.html.haml' - - # Offense count: 9 - RuboCop: - exclude: - - 'app/views/admin/accounts/_buttons.html.haml' - - 'app/views/admin/accounts/_local_account.html.haml' - - 'app/views/admin/roles/_form.html.haml' diff --git a/.rubocop.yml b/.rubocop.yml index 2221604224..61cb1164b4 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -109,6 +109,17 @@ Rails/SkipsModelValidations: Exclude: - 'db/*migrate/**/*' +# Reason: We want to preserve the ability to migrate from arbitrary old versions, +# and cannot guarantee that every installation has run every migration as they upgrade. +# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsunusedignoredcolumns +Rails/UnusedIgnoredColumns: + Enabled: false + +# Reason: Prevailing style choice +# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsnegateinclude +Rails/NegateInclude: + Enabled: false + # Reason: Some single letter camel case files shouldn't be split # https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecfilepath RSpec/FilePath: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index d9b2ec8144..030f311101 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -119,23 +119,6 @@ Rails/LexicallyScopedActionFilter: - 'app/controllers/auth/passwords_controller.rb' - 'app/controllers/auth/registrations_controller.rb' -# This cop supports unsafe autocorrection (--autocorrect-all). -Rails/NegateInclude: - Exclude: - - 'app/controllers/concerns/signature_verification.rb' - - 'app/helpers/jsonld_helper.rb' - - 'app/lib/activitypub/activity/create.rb' - - 'app/lib/activitypub/activity/move.rb' - - 'app/lib/feed_manager.rb' - - 'app/lib/link_details_extractor.rb' - - 'app/models/concerns/attachmentable.rb' - - 'app/models/concerns/remotable.rb' - - 'app/models/custom_filter.rb' - - 'app/services/activitypub/process_status_update_service.rb' - - 'app/services/fetch_link_card_service.rb' - - 'app/workers/web/push_notification_worker.rb' - - 'lib/paperclip/color_extractor.rb' - Rails/OutputSafety: Exclude: - 'config/initializers/simple_form.rb' @@ -196,19 +179,6 @@ Rails/UniqueValidationWithoutIndex: - 'app/models/identity.rb' - 'app/models/webauthn_credential.rb' -# Configuration parameters: Include. -# Include: app/models/**/*.rb -Rails/UnusedIgnoredColumns: - Exclude: - - 'app/models/account.rb' - - 'app/models/account_stat.rb' - - 'app/models/admin/action_log.rb' - - 'app/models/custom_filter.rb' - - 'app/models/email_domain_block.rb' - - 'app/models/report.rb' - - 'app/models/status_edit.rb' - - 'app/models/user.rb' - # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle. # SupportedStyles: exists, where @@ -426,15 +396,6 @@ Style/RedundantFetchBlock: - 'config/initializers/paperclip.rb' - 'config/puma.rb' -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowMultipleReturnValues. -Style/RedundantReturn: - Exclude: - - 'app/controllers/api/v1/directories_controller.rb' - - 'app/controllers/auth/confirmations_controller.rb' - - 'app/lib/ostatus/tag_manager.rb' - - 'app/models/form/import.rb' - # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength. # AllowedMethods: present?, blank?, presence, try, try! @@ -455,11 +416,6 @@ Style/SingleArgumentDig: Exclude: - 'lib/webpacker/manifest_extensions.rb' -# This cop supports safe autocorrection (--autocorrect). -Style/StderrPuts: - Exclude: - - 'config/boot.rb' - # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: Mode. Style/StringConcatenation: @@ -478,13 +434,6 @@ Style/StringLiterals: - 'config/initializers/webauthn.rb' - 'config/routes.rb' -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments. -# AllowedMethods: define_method, mail, respond_to -Style/SymbolProc: - Exclude: - - 'config/initializers/3_omniauth.rb' - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, AllowSafeAssignment. # SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex diff --git a/Gemfile.lock b/Gemfile.lock index ab24f5dca1..3b33402b22 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -515,7 +515,7 @@ GEM openssl (> 2.0) orm_adapter (0.5.0) ox (2.14.17) - parallel (1.23.0) + parallel (1.24.0) parser (3.2.2.4) ast (~> 2.4.1) racc @@ -679,10 +679,10 @@ GEM rubocop (~> 1.41) rubocop-factory_bot (2.24.0) rubocop (~> 1.33) - rubocop-performance (1.19.1) - rubocop (>= 1.7.0, < 2.0) - rubocop-ast (>= 0.4.0) - rubocop-rails (2.22.2) + rubocop-performance (1.20.0) + rubocop (>= 1.48.1, < 2.0) + rubocop-ast (>= 1.30.0, < 2.0) + rubocop-rails (2.23.0) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.33.0, < 2.0) diff --git a/app/controllers/api/v1/accounts/notes_controller.rb b/app/controllers/api/v1/accounts/notes_controller.rb index 032e807d11..6d115631a2 100644 --- a/app/controllers/api/v1/accounts/notes_controller.rb +++ b/app/controllers/api/v1/accounts/notes_controller.rb @@ -25,6 +25,6 @@ class Api::V1::Accounts::NotesController < Api::BaseController end def relationships_presenter - AccountRelationshipsPresenter.new([@account.id], current_user.account_id) + AccountRelationshipsPresenter.new([@account], current_user.account_id) end end diff --git a/app/controllers/api/v1/accounts/pins_controller.rb b/app/controllers/api/v1/accounts/pins_controller.rb index 73f845c614..0eb13c048c 100644 --- a/app/controllers/api/v1/accounts/pins_controller.rb +++ b/app/controllers/api/v1/accounts/pins_controller.rb @@ -25,6 +25,6 @@ class Api::V1::Accounts::PinsController < Api::BaseController end def relationships_presenter - AccountRelationshipsPresenter.new([@account.id], current_user.account_id) + AccountRelationshipsPresenter.new([@account], current_user.account_id) end end diff --git a/app/controllers/api/v1/accounts/relationships_controller.rb b/app/controllers/api/v1/accounts/relationships_controller.rb index e5ae5b007b..d43832177a 100644 --- a/app/controllers/api/v1/accounts/relationships_controller.rb +++ b/app/controllers/api/v1/accounts/relationships_controller.rb @@ -5,7 +5,7 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController before_action :require_user! def index - @accounts = Account.where(id: account_ids).select('id') + @accounts = Account.where(id: account_ids).select(:id, :domain) @accounts.merge!(Account.without_suspended) unless truthy_param?(:with_suspended) render json: @accounts, each_serializer: REST::RelationshipSerializer, relationships: relationships end diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index be251b4259..23fc85b475 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -88,7 +88,7 @@ class Api::V1::AccountsController < Api::BaseController end def relationships(**options) - AccountRelationshipsPresenter.new([@account.id], current_user.account_id, **options) + AccountRelationshipsPresenter.new([@account], current_user.account_id, **options) end def account_params diff --git a/app/controllers/api/v1/directories_controller.rb b/app/controllers/api/v1/directories_controller.rb index 35c504a7ff..e79b20ce42 100644 --- a/app/controllers/api/v1/directories_controller.rb +++ b/app/controllers/api/v1/directories_controller.rb @@ -12,7 +12,7 @@ class Api::V1::DirectoriesController < Api::BaseController private def require_enabled! - return not_found unless Setting.profile_directory + not_found unless Setting.profile_directory end def set_accounts diff --git a/app/controllers/api/v1/follow_requests_controller.rb b/app/controllers/api/v1/follow_requests_controller.rb index 7c197ce6ba..ee717ebbcc 100644 --- a/app/controllers/api/v1/follow_requests_controller.rb +++ b/app/controllers/api/v1/follow_requests_controller.rb @@ -25,11 +25,11 @@ class Api::V1::FollowRequestsController < Api::BaseController private def account - Account.find(params[:id]) + @account ||= Account.find(params[:id]) end def relationships(**options) - AccountRelationshipsPresenter.new([params[:id]], current_user.account_id, **options) + AccountRelationshipsPresenter.new([account], current_user.account_id, **options) end def load_accounts diff --git a/app/controllers/auth/confirmations_controller.rb b/app/controllers/auth/confirmations_controller.rb index 5e6589ad48..5d476d0440 100644 --- a/app/controllers/auth/confirmations_controller.rb +++ b/app/controllers/auth/confirmations_controller.rb @@ -63,7 +63,7 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController end def captcha_user_bypass? - return true if @confirmation_user.nil? || @confirmation_user.confirmed? + @confirmation_user.nil? || @confirmation_user.confirmed? end def set_pack diff --git a/app/controllers/relationships_controller.rb b/app/controllers/relationships_controller.rb index f83098f731..e6e7c24752 100644 --- a/app/controllers/relationships_controller.rb +++ b/app/controllers/relationships_controller.rb @@ -34,7 +34,7 @@ class RelationshipsController < ApplicationController end def set_relationships - @relationships = AccountRelationshipsPresenter.new(@accounts.pluck(:id), current_user.account_id) + @relationships = AccountRelationshipsPresenter.new(@accounts, current_user.account_id) end def form_account_batch_params diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 2b22f2f75b..daa27195e9 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -110,7 +110,7 @@ module ApplicationHelper def can?(action, record) return false if record.nil? - policy(record).public_send("#{action}?") + policy(record).public_send(:"#{action}?") end def fa_icon(icon, attributes = {}) diff --git a/app/lib/ostatus/tag_manager.rb b/app/lib/ostatus/tag_manager.rb index 7d81316227..21b3d3aa58 100644 --- a/app/lib/ostatus/tag_manager.rb +++ b/app/lib/ostatus/tag_manager.rb @@ -52,7 +52,7 @@ class OStatus::TagManager ActivityPub::TagManager.instance.uri_to_local_id(tag) else matches = Regexp.new("objectId=([\\d]+):objectType=#{expected_type}").match(tag) - return matches[1] unless matches.nil? + matches[1] unless matches.nil? end end diff --git a/app/models/account.rb b/app/models/account.rb index 5b23eb9cbb..9408d84ad4 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -455,8 +455,8 @@ class Account < ApplicationRecord end def inverse_alias(key, original_key) - define_method("#{key}=") do |value| - public_send("#{original_key}=", !ActiveModel::Type::Boolean.new.cast(value)) + define_method(:"#{key}=") do |value| + public_send(:"#{original_key}=", !ActiveModel::Type::Boolean.new.cast(value)) end define_method(key) do diff --git a/app/models/account_domain_block.rb b/app/models/account_domain_block.rb index af1e6a68dc..db2e37184f 100644 --- a/app/models/account_domain_block.rb +++ b/app/models/account_domain_block.rb @@ -18,16 +18,12 @@ class AccountDomainBlock < ApplicationRecord belongs_to :account validates :domain, presence: true, uniqueness: { scope: :account_id }, domain: true - after_commit :remove_blocking_cache - after_commit :remove_relationship_cache + after_commit :invalidate_domain_blocking_cache private - def remove_blocking_cache + def invalidate_domain_blocking_cache Rails.cache.delete("exclude_domains_for:#{account_id}") - end - - def remove_relationship_cache - Rails.cache.delete_matched("relationship:#{account_id}:*") + Rails.cache.delete(['exclude_domains', account_id, domain]) end end diff --git a/app/models/concerns/account/interactions.rb b/app/models/concerns/account/interactions.rb index 0ea26e628d..4ddec9bf49 100644 --- a/app/models/concerns/account/interactions.rb +++ b/app/models/concerns/account/interactions.rb @@ -60,12 +60,6 @@ module Account::Interactions end end - def domain_blocking_map(target_account_ids, account_id) - accounts_map = Account.where(id: target_account_ids).select('id, domain').each_with_object({}) { |a, h| h[a.id] = a.domain } - blocked_domains = domain_blocking_map_by_domain(accounts_map.values.compact, account_id) - accounts_map.reduce({}) { |h, (id, domain)| h.merge(id => blocked_domains[domain]) } - end - def domain_blocking_map_by_domain(target_domains, account_id) follow_mapping(AccountDomainBlock.where(account_id: account_id, domain: target_domains), :domain) end diff --git a/app/models/concerns/relationship_cacheable.rb b/app/models/concerns/relationship_cacheable.rb index 0d9359f7e7..c32a8d62c6 100644 --- a/app/models/concerns/relationship_cacheable.rb +++ b/app/models/concerns/relationship_cacheable.rb @@ -10,7 +10,7 @@ module RelationshipCacheable private def remove_relationship_cache - Rails.cache.delete("relationship:#{account_id}:#{target_account_id}") - Rails.cache.delete("relationship:#{target_account_id}:#{account_id}") + Rails.cache.delete(['relationship', account_id, target_account_id]) + Rails.cache.delete(['relationship', target_account_id, account_id]) end end diff --git a/app/models/concerns/remotable.rb b/app/models/concerns/remotable.rb index bd8b6f4eb9..6118e204a1 100644 --- a/app/models/concerns/remotable.rb +++ b/app/models/concerns/remotable.rb @@ -7,7 +7,7 @@ module Remotable def remotable_attachment(attachment_name, limit, suppress_errors: true, download_on_assign: true, attribute_name: nil) attribute_name ||= :"#{attachment_name}_remote_url" - define_method("download_#{attachment_name}!") do |url = nil| + define_method(:"download_#{attachment_name}!") do |url = nil| url ||= self[attribute_name] return if url.blank? @@ -24,29 +24,29 @@ module Remotable Request.new(:get, url).perform do |response| raise Mastodon::UnexpectedResponseError, response unless (200...300).cover?(response.code) - public_send("#{attachment_name}=", ResponseWithLimit.new(response, limit)) + public_send(:"#{attachment_name}=", ResponseWithLimit.new(response, limit)) end rescue Mastodon::UnexpectedResponseError, HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError => e Rails.logger.debug { "Error fetching remote #{attachment_name}: #{e}" } - public_send("#{attachment_name}=", nil) if public_send("#{attachment_name}_file_name").present? + public_send(:"#{attachment_name}=", nil) if public_send(:"#{attachment_name}_file_name").present? raise e unless suppress_errors rescue Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError, Paperclip::Error, Mastodon::DimensionsValidationError, Mastodon::StreamValidationError => e Rails.logger.debug { "Error fetching remote #{attachment_name}: #{e}" } - public_send("#{attachment_name}=", nil) if public_send("#{attachment_name}_file_name").present? + public_send(:"#{attachment_name}=", nil) if public_send(:"#{attachment_name}_file_name").present? end nil end - define_method("#{attribute_name}=") do |url| - return if self[attribute_name] == url && public_send("#{attachment_name}_file_name").present? + define_method(:"#{attribute_name}=") do |url| + return if self[attribute_name] == url && public_send(:"#{attachment_name}_file_name").present? self[attribute_name] = url if has_attribute?(attribute_name) - public_send("download_#{attachment_name}!", url) if download_on_assign + public_send(:"download_#{attachment_name}!", url) if download_on_assign end - alias_method("reset_#{attachment_name}!", "download_#{attachment_name}!") + alias_method(:"reset_#{attachment_name}!", "download_#{attachment_name}!") end end end diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb index 41014fb418..095733673e 100644 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@ -100,7 +100,7 @@ class Form::AdminSettings KEYS.each do |key| define_method(key) do - return instance_variable_get("@#{key}") if instance_variable_defined?("@#{key}") + return instance_variable_get(:"@#{key}") if instance_variable_defined?(:"@#{key}") stored_value = if UPLOAD_KEYS.include?(key) SiteUpload.where(var: key).first_or_initialize(var: key) @@ -110,12 +110,12 @@ class Form::AdminSettings Setting.public_send(key) end - instance_variable_set("@#{key}", stored_value) + instance_variable_set(:"@#{key}", stored_value) end end UPLOAD_KEYS.each do |key| - define_method("#{key}=") do |file| + define_method(:"#{key}=") do |file| value = public_send(key) value.file = file rescue Mastodon::DimensionsValidationError => e @@ -130,13 +130,13 @@ class Form::AdminSettings return false unless errors.empty? && valid? KEYS.each do |key| - next if PSEUDO_KEYS.include?(key) || !instance_variable_defined?("@#{key}") + next if PSEUDO_KEYS.include?(key) || !instance_variable_defined?(:"@#{key}") if UPLOAD_KEYS.include?(key) public_send(key).save else setting = Setting.where(var: key).first_or_initialize(var: key) - setting.update(value: typecast_value(key, instance_variable_get("@#{key}"))) + setting.update(value: typecast_value(key, instance_variable_get(:"@#{key}"))) end end end @@ -163,9 +163,9 @@ class Form::AdminSettings def validate_site_uploads UPLOAD_KEYS.each do |key| - next unless instance_variable_defined?("@#{key}") + next unless instance_variable_defined?(:"@#{key}") - upload = instance_variable_get("@#{key}") + upload = instance_variable_get(:"@#{key}") next if upload.valid? upload.errors.each do |error| diff --git a/app/models/form/import.rb b/app/models/form/import.rb index 29a2975c7b..712acf3706 100644 --- a/app/models/form/import.rb +++ b/app/models/form/import.rb @@ -43,14 +43,19 @@ class Form::Import validate :validate_data def guessed_type - return :muting if csv_headers_match?('Hide notifications') - return :following if csv_headers_match?('Show boosts') || csv_headers_match?('Notify on new posts') || csv_headers_match?('Languages') - return :following if file_name_matches?('follows') || file_name_matches?('following_accounts') - return :blocking if file_name_matches?('blocks') || file_name_matches?('blocked_accounts') - return :muting if file_name_matches?('mutes') || file_name_matches?('muted_accounts') - return :domain_blocking if file_name_matches?('domain_blocks') || file_name_matches?('blocked_domains') - return :bookmarks if file_name_matches?('bookmarks') - return :lists if file_name_matches?('lists') + if csv_headers_match?('Hide notifications') || file_name_matches?('mutes') || file_name_matches?('muted_accounts') + :muting + elsif csv_headers_match?('Show boosts') || csv_headers_match?('Notify on new posts') || csv_headers_match?('Languages') || file_name_matches?('follows') || file_name_matches?('following_accounts') + :following + elsif file_name_matches?('blocks') || file_name_matches?('blocked_accounts') + :blocking + elsif file_name_matches?('domain_blocks') || file_name_matches?('blocked_domains') + :domain_blocking + elsif file_name_matches?('bookmarks') + :bookmarks + elsif file_name_matches?('lists') + :lists + end end # Whether the uploaded CSV file seems to correspond to a different import type than the one selected diff --git a/app/presenters/account_relationships_presenter.rb b/app/presenters/account_relationships_presenter.rb index 5d2b5435dd..8482ef54da 100644 --- a/app/presenters/account_relationships_presenter.rb +++ b/app/presenters/account_relationships_presenter.rb @@ -5,8 +5,9 @@ class AccountRelationshipsPresenter :muting, :requested, :requested_by, :domain_blocking, :endorsed, :account_note - def initialize(account_ids, current_account_id, **options) - @account_ids = account_ids.map { |a| a.is_a?(Account) ? a.id : a.to_i } + def initialize(accounts, current_account_id, **options) + @accounts = accounts.to_a + @account_ids = @accounts.pluck(:id) @current_account_id = current_account_id @following = cached[:following].merge(Account.following_map(@uncached_account_ids, @current_account_id)) @@ -16,10 +17,11 @@ class AccountRelationshipsPresenter @muting = cached[:muting].merge(Account.muting_map(@uncached_account_ids, @current_account_id)) @requested = cached[:requested].merge(Account.requested_map(@uncached_account_ids, @current_account_id)) @requested_by = cached[:requested_by].merge(Account.requested_by_map(@uncached_account_ids, @current_account_id)) - @domain_blocking = cached[:domain_blocking].merge(Account.domain_blocking_map(@uncached_account_ids, @current_account_id)) @endorsed = cached[:endorsed].merge(Account.endorsed_map(@uncached_account_ids, @current_account_id)) @account_note = cached[:account_note].merge(Account.account_note_map(@uncached_account_ids, @current_account_id)) + @domain_blocking = domain_blocking_map + cache_uncached! @following.merge!(options[:following_map] || {}) @@ -36,6 +38,31 @@ class AccountRelationshipsPresenter private + def domain_blocking_map + target_domains = @accounts.pluck(:domain).compact.uniq + blocks_by_domain = {} + + # Fetch from cache + cache_keys = target_domains.map { |domain| domain_cache_key(domain) } + Rails.cache.read_multi(*cache_keys).each do |key, blocking| + blocks_by_domain[key.last] = blocking + end + + uncached_domains = target_domains - blocks_by_domain.keys + + # Read uncached values from database + AccountDomainBlock.where(account_id: @current_account_id, domain: uncached_domains).pluck(:domain).each do |domain| + blocks_by_domain[domain] = true + end + + # Write database reads to cache + to_cache = uncached_domains.to_h { |domain| [domain_cache_key(domain), blocks_by_domain[domain]] } + Rails.cache.write_multi(to_cache, expires_in: 1.day) + + # Return formatted value + @accounts.each_with_object({}) { |account, h| h[account.id] = blocks_by_domain[account.domain] } + end + def cached return @cached if defined?(@cached) @@ -47,28 +74,23 @@ class AccountRelationshipsPresenter muting: {}, requested: {}, requested_by: {}, - domain_blocking: {}, endorsed: {}, account_note: {}, } - @uncached_account_ids = [] + @uncached_account_ids = @account_ids.uniq - @account_ids.each do |account_id| - maps_for_account = Rails.cache.read("relationship:#{@current_account_id}:#{account_id}") - - if maps_for_account.is_a?(Hash) - @cached.deep_merge!(maps_for_account) - else - @uncached_account_ids << account_id - end + cache_ids = @account_ids.map { |account_id| relationship_cache_key(account_id) } + Rails.cache.read_multi(*cache_ids).each do |key, maps_for_account| + @cached.deep_merge!(maps_for_account) + @uncached_account_ids.delete(key.last) end @cached end def cache_uncached! - @uncached_account_ids.each do |account_id| + to_cache = @uncached_account_ids.to_h do |account_id| maps_for_account = { following: { account_id => following[account_id] }, followed_by: { account_id => followed_by[account_id] }, @@ -77,12 +99,21 @@ class AccountRelationshipsPresenter muting: { account_id => muting[account_id] }, requested: { account_id => requested[account_id] }, requested_by: { account_id => requested_by[account_id] }, - domain_blocking: { account_id => domain_blocking[account_id] }, endorsed: { account_id => endorsed[account_id] }, account_note: { account_id => account_note[account_id] }, } - Rails.cache.write("relationship:#{@current_account_id}:#{account_id}", maps_for_account, expires_in: 1.day) + [relationship_cache_key(account_id), maps_for_account] end + + Rails.cache.write_multi(to_cache, expires_in: 1.day) + end + + def domain_cache_key(domain) + ['exclude_domains', @current_account_id, domain] + end + + def relationship_cache_key(account_id) + ['relationship', @current_account_id, account_id] end end diff --git a/app/views/admin/accounts/_buttons.html.haml b/app/views/admin/accounts/_buttons.html.haml index 6eb141abc9..2aaca8962c 100644 --- a/app/views/admin/accounts/_buttons.html.haml +++ b/app/views/admin/accounts/_buttons.html.haml @@ -6,8 +6,8 @@ %p.muted-hint= deletion_request.present? ? t('admin.accounts.suspension_reversible_hint_html', date: content_tag(:strong, l(deletion_request.due_at.to_date))) : t('admin.accounts.suspension_irreversible') = link_to t('admin.accounts.undo_suspension'), unsuspend_admin_account_path(account.id), method: :post, class: 'button' if can?(:unsuspend, account) = link_to t('admin.accounts.redownload'), redownload_admin_account_path(account.id), method: :post, class: 'button' if can?(:redownload, account) && account.suspension_origin_remote? - - if deletion_request.present? - = link_to t('admin.accounts.delete'), admin_account_path(account.id), method: :delete, class: 'button button--destructive', data: { confirm: t('admin.accounts.are_you_sure') } if can?(:destroy, account) + - if deletion_request.present? && can?(:destroy, account) + = link_to t('admin.accounts.delete'), admin_account_path(account.id), method: :delete, class: 'button button--destructive', data: { confirm: t('admin.accounts.are_you_sure') } - else .action-buttons %div @@ -15,8 +15,8 @@ = link_to t('admin.accounts.warn'), new_admin_account_action_path(account.id, type: 'none'), class: 'button' if can?(:warn, account) - if account.user_disabled? = link_to t('admin.accounts.enable'), enable_admin_account_path(account.id), method: :post, class: 'button' if can?(:enable, account.user) - - else - = link_to t('admin.accounts.disable'), new_admin_account_action_path(account.id, type: 'disable'), class: 'button' if can?(:disable, account.user) + - elsif can?(:disable, account.user) + = link_to t('admin.accounts.disable'), new_admin_account_action_path(account.id, type: 'disable'), class: 'button' - if account.sensitized? = link_to t('admin.accounts.undo_sensitized'), unsensitive_admin_account_path(account.id), method: :post, class: 'button' if can?(:unsensitive, account) - elsif !account.local? || account.user_approved? @@ -29,13 +29,13 @@ - if account.user_pending? = link_to t('admin.accounts.approve'), approve_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button' if can?(:approve, account.user) = link_to t('admin.accounts.reject'), reject_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:reject, account.user) - - unless account.user_confirmed? - = link_to t('admin.accounts.confirm'), admin_account_confirmation_path(account.id), method: :post, class: 'button' if can?(:confirm, account.user) - - if !account.local? || account.user_approved? - = link_to t('admin.accounts.perform_full_suspension'), new_admin_account_action_path(account.id, type: 'suspend'), class: 'button' if can?(:suspend, account) + - if !account.user_confirmed? && can?(:confirm, account.user) + = link_to t('admin.accounts.confirm'), admin_account_confirmation_path(account.id), method: :post, class: 'button' + - if (!account.local? || account.user_approved?) && can?(:suspend, account) + = link_to t('admin.accounts.perform_full_suspension'), new_admin_account_action_path(account.id, type: 'suspend'), class: 'button' %div - if account.local? - - if !account.memorial? && account.user_approved? - = link_to t('admin.accounts.memorialize'), memorialize_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:memorialize, account) - - else - = link_to t('admin.accounts.redownload'), redownload_admin_account_path(account.id), method: :post, class: 'button' if can?(:redownload, account) + - if !account.memorial? && account.user_approved? && can?(:memorialize, account) + = link_to t('admin.accounts.memorialize'), memorialize_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' + - elsif can?(:redownload, account) + = link_to t('admin.accounts.redownload'), redownload_admin_account_path(account.id), method: :post, class: 'button' diff --git a/app/views/admin/accounts/_local_account.html.haml b/app/views/admin/accounts/_local_account.html.haml index 4b361fc8d1..82197cda43 100644 --- a/app/views/admin/accounts/_local_account.html.haml +++ b/app/views/admin/accounts/_local_account.html.haml @@ -47,8 +47,8 @@ - else = t 'admin.accounts.security_measures.only_password' %td - - if account.user&.two_factor_enabled? - = table_link_to 'unlock', t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(account.user.id), method: :delete if can?(:disable_2fa, account.user) + - if account.user&.two_factor_enabled? && can?(:disable_2fa, account.user) + = table_link_to 'unlock', t('admin.accounts.disable_two_factor_authentication'), admin_user_two_factor_authentication_path(account.user.id), method: :delete - if can?(:reset_password, account.user) %tr %td diff --git a/config/boot.rb b/config/boot.rb index 3e44cbe581..717de85f20 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true unless ENV.key?('RAILS_ENV') - STDERR.puts 'ERROR: Missing RAILS_ENV environment variable, please set it to "production", "development", or "test".' + warn 'ERROR: Missing RAILS_ENV environment variable, please set it to "production", "development", or "test".' exit 1 end diff --git a/config/initializers/3_omniauth.rb b/config/initializers/3_omniauth.rb index d316c3b73a..aa8ba1a056 100644 --- a/config/initializers/3_omniauth.rb +++ b/config/initializers/3_omniauth.rb @@ -79,7 +79,7 @@ Devise.setup do |config| oidc_options[:client_auth_method] = ENV['OIDC_CLIENT_AUTH_METHOD'] if ENV['OIDC_CLIENT_AUTH_METHOD'] # OPTIONAL (default: basic) scope_string = ENV['OIDC_SCOPE'] if ENV['OIDC_SCOPE'] # NEED scopes = scope_string.split(',') - oidc_options[:scope] = scopes.map { |x| x.to_sym } + oidc_options[:scope] = scopes.map(&:to_sym) oidc_options[:response_type] = ENV['OIDC_RESPONSE_TYPE'] if ENV['OIDC_RESPONSE_TYPE'] # OPTIONAL (default: code) oidc_options[:response_mode] = ENV['OIDC_RESPONSE_MODE'] if ENV['OIDC_RESPONSE_MODE'] # OPTIONAL (default: query) oidc_options[:display] = ENV['OIDC_DISPLAY'] if ENV['OIDC_DISPLAY'] # OPTIONAL (default: page) diff --git a/spec/fabricators/custom_emoji_category_fabricator.rb b/spec/fabricators/custom_emoji_category_fabricator.rb new file mode 100644 index 0000000000..af41c97227 --- /dev/null +++ b/spec/fabricators/custom_emoji_category_fabricator.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +Fabricator(:custom_emoji_category) do + name { sequence(:name) { |i| "name_#{i}" } } +end diff --git a/spec/models/concerns/remotable_spec.rb b/spec/models/concerns/remotable_spec.rb index 9f6aeb7fb4..097e6bf006 100644 --- a/spec/models/concerns/remotable_spec.rb +++ b/spec/models/concerns/remotable_spec.rb @@ -178,11 +178,11 @@ RSpec.describe Remotable do allow(foo).to receive(:public_send) foo.hoge_remote_url = url - expect(foo).to have_received(:public_send).with("download_#{hoge}!", url) + expect(foo).to have_received(:public_send).with(:"download_#{hoge}!", url) allow(foo).to receive(:public_send) foo.download_hoge!(url) - expect(foo).to have_received(:public_send).with("#{hoge}=", response_with_limit) + expect(foo).to have_received(:public_send).with(:"#{hoge}=", response_with_limit) end end end diff --git a/spec/models/form/custom_emoji_batch_spec.rb b/spec/models/form/custom_emoji_batch_spec.rb new file mode 100644 index 0000000000..abeada5d50 --- /dev/null +++ b/spec/models/form/custom_emoji_batch_spec.rb @@ -0,0 +1,118 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe Form::CustomEmojiBatch do + describe '#save' do + subject { described_class.new({ current_account: account }.merge(options)) } + + let(:options) { {} } + let(:account) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')).account } + + context 'with empty custom_emoji_ids' do + let(:options) { { custom_emoji_ids: [] } } + + it 'does nothing if custom_emoji_ids is empty' do + expect(subject.save).to be_nil + end + end + + describe 'the update action' do + let(:custom_emoji) { Fabricate(:custom_emoji, category: Fabricate(:custom_emoji_category)) } + let(:custom_emoji_category) { Fabricate(:custom_emoji_category) } + + context 'without anything to change' do + let(:options) { { action: 'update' } } + + it 'silently exits without updating any custom emojis' do + expect { subject.save }.to_not change(Admin::ActionLog, :count) + end + end + + context 'with a category_id' do + let(:options) { { action: 'update', custom_emoji_ids: [custom_emoji.id], category_id: custom_emoji_category.id } } + + it 'updates the category of the emoji' do + subject.save + + expect(custom_emoji.reload.category).to eq(custom_emoji_category) + end + end + + context 'with a category_name' do + let(:options) { { action: 'update', custom_emoji_ids: [custom_emoji.id], category_name: custom_emoji_category.name } } + + it 'updates the category of the emoji' do + subject.save + + expect(custom_emoji.reload.category).to eq(custom_emoji_category) + end + end + end + + describe 'the list action' do + let(:custom_emoji) { Fabricate(:custom_emoji, visible_in_picker: false) } + let(:options) { { action: 'list', custom_emoji_ids: [custom_emoji.id] } } + + it 'updates the picker visibility of the emoji' do + subject.save + + expect(custom_emoji.reload.visible_in_picker).to be(true) + end + end + + describe 'the unlist action' do + let(:custom_emoji) { Fabricate(:custom_emoji, visible_in_picker: true) } + let(:options) { { action: 'unlist', custom_emoji_ids: [custom_emoji.id] } } + + it 'updates the picker visibility of the emoji' do + subject.save + + expect(custom_emoji.reload.visible_in_picker).to be(false) + end + end + + describe 'the enable action' do + let(:custom_emoji) { Fabricate(:custom_emoji, disabled: true) } + let(:options) { { action: 'enable', custom_emoji_ids: [custom_emoji.id] } } + + it 'updates the disabled value of the emoji' do + subject.save + + expect(custom_emoji.reload).to_not be_disabled + end + end + + describe 'the disable action' do + let(:custom_emoji) { Fabricate(:custom_emoji, visible_in_picker: false) } + let(:options) { { action: 'disable', custom_emoji_ids: [custom_emoji.id] } } + + it 'updates the disabled value of the emoji' do + subject.save + + expect(custom_emoji.reload).to be_disabled + end + end + + describe 'the copy action' do + let(:custom_emoji) { Fabricate(:custom_emoji) } + let(:options) { { action: 'copy', custom_emoji_ids: [custom_emoji.id] } } + + it 'makes a copy of the emoji' do + expect { subject.save } + .to change(CustomEmoji, :count).by(1) + end + end + + describe 'the delete action' do + let(:custom_emoji) { Fabricate(:custom_emoji) } + let(:options) { { action: 'delete', custom_emoji_ids: [custom_emoji.id] } } + + it 'destroys the emoji' do + subject.save + + expect { custom_emoji.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + end + end +end diff --git a/spec/presenters/account_relationships_presenter_spec.rb b/spec/presenters/account_relationships_presenter_spec.rb index 5b05ac8001..282cae4f06 100644 --- a/spec/presenters/account_relationships_presenter_spec.rb +++ b/spec/presenters/account_relationships_presenter_spec.rb @@ -5,19 +5,18 @@ require 'rails_helper' RSpec.describe AccountRelationshipsPresenter do describe '.initialize' do before do - allow(Account).to receive(:following_map).with(account_ids, current_account_id).and_return(default_map) - allow(Account).to receive(:followed_by_map).with(account_ids, current_account_id).and_return(default_map) - allow(Account).to receive(:blocking_map).with(account_ids, current_account_id).and_return(default_map) - allow(Account).to receive(:muting_map).with(account_ids, current_account_id).and_return(default_map) - allow(Account).to receive(:requested_map).with(account_ids, current_account_id).and_return(default_map) - allow(Account).to receive(:requested_by_map).with(account_ids, current_account_id).and_return(default_map) - allow(Account).to receive(:domain_blocking_map).with(account_ids, current_account_id).and_return(default_map) + allow(Account).to receive(:following_map).with(accounts.pluck(:id), current_account_id).and_return(default_map) + allow(Account).to receive(:followed_by_map).with(accounts.pluck(:id), current_account_id).and_return(default_map) + allow(Account).to receive(:blocking_map).with(accounts.pluck(:id), current_account_id).and_return(default_map) + allow(Account).to receive(:muting_map).with(accounts.pluck(:id), current_account_id).and_return(default_map) + allow(Account).to receive(:requested_map).with(accounts.pluck(:id), current_account_id).and_return(default_map) + allow(Account).to receive(:requested_by_map).with(accounts.pluck(:id), current_account_id).and_return(default_map) end - let(:presenter) { described_class.new(account_ids, current_account_id, **options) } + let(:presenter) { described_class.new(accounts, current_account_id, **options) } let(:current_account_id) { Fabricate(:account).id } - let(:account_ids) { [Fabricate(:account).id] } - let(:default_map) { { 1 => true } } + let(:accounts) { [Fabricate(:account)] } + let(:default_map) { { accounts[0].id => true } } context 'when options are not set' do let(:options) { {} } @@ -29,7 +28,33 @@ RSpec.describe AccountRelationshipsPresenter do blocking: default_map, muting: default_map, requested: default_map, - domain_blocking: default_map + domain_blocking: { accounts[0].id => nil } + ) + end + end + + context 'with a warm cache' do + let(:options) { {} } + + before do + described_class.new(accounts, current_account_id, **options) + + allow(Account).to receive(:following_map).with([], current_account_id).and_return({}) + allow(Account).to receive(:followed_by_map).with([], current_account_id).and_return({}) + allow(Account).to receive(:blocking_map).with([], current_account_id).and_return({}) + allow(Account).to receive(:muting_map).with([], current_account_id).and_return({}) + allow(Account).to receive(:requested_map).with([], current_account_id).and_return({}) + allow(Account).to receive(:requested_by_map).with([], current_account_id).and_return({}) + end + + it 'sets returns expected values' do + expect(presenter).to have_attributes( + following: default_map, + followed_by: default_map, + blocking: default_map, + muting: default_map, + requested: default_map, + domain_blocking: { accounts[0].id => nil } ) end end @@ -86,7 +111,7 @@ RSpec.describe AccountRelationshipsPresenter do let(:options) { { domain_blocking_map: { 7 => true } } } it 'sets @domain_blocking merged with default_map and options[:domain_blocking_map]' do - expect(presenter.domain_blocking).to eq default_map.merge(options[:domain_blocking_map]) + expect(presenter.domain_blocking).to eq({ accounts[0].id => nil }.merge(options[:domain_blocking_map])) end end end diff --git a/spec/requests/omniauth_callbacks_spec.rb b/spec/requests/omniauth_callbacks_spec.rb index 27aa5ec506..0d37c41140 100644 --- a/spec/requests/omniauth_callbacks_spec.rb +++ b/spec/requests/omniauth_callbacks_spec.rb @@ -4,7 +4,7 @@ require 'rails_helper' describe 'OmniAuth callbacks' do shared_examples 'omniauth provider callbacks' do |provider| - subject { post send "user_#{provider}_omniauth_callback_path" } + subject { post send :"user_#{provider}_omniauth_callback_path" } context 'with full information in response' do before do diff --git a/yarn.lock b/yarn.lock index f1d1618ca9..6fa57e6373 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1744,10 +1744,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.55.0": - version: 8.55.0 - resolution: "@eslint/js@npm:8.55.0" - checksum: 88ab9fc57a651becd2b32ec40a3958db27fae133b1ae77bebd733aa5bbd00a92f325bb02f20ad680d31c731fa49b22f060a4777dd52eb3e27da013d940bd978d +"@eslint/js@npm:8.56.0": + version: 8.56.0 + resolution: "@eslint/js@npm:8.56.0" + checksum: 60b3a1cf240e2479cec9742424224465dc50e46d781da1b7f5ef240501b2d1202c225bd456207faac4b34a64f4765833345bc4ddffd00395e1db40fa8c426f5a languageName: node linkType: hard @@ -3355,11 +3355,11 @@ __metadata: linkType: hard "@types/react-dom@npm:^18.0.0, @types/react-dom@npm:^18.2.4": - version: 18.2.17 - resolution: "@types/react-dom@npm:18.2.17" + version: 18.2.18 + resolution: "@types/react-dom@npm:18.2.18" dependencies: "@types/react": "npm:*" - checksum: 33b53078ed7e9e0cfc4dc691e938f7db1cc06353bc345947b41b581c3efe2b980c9e4eb6460dbf5ddc521dd91959194c970221a2bd4bfad9d23ebce338e12938 + checksum: 74dba11a1b8156f3a763f3fca1fb4ec1dcd349153279b8bf79210024a69f994bf2cf0728198c047f8130c5318420ea56281b0a4ef84c8ae943cd9a0cac705220 languageName: node linkType: hard @@ -3485,13 +3485,13 @@ __metadata: linkType: hard "@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7": - version: 18.2.43 - resolution: "@types/react@npm:18.2.43" + version: 18.2.45 + resolution: "@types/react@npm:18.2.45" dependencies: "@types/prop-types": "npm:*" "@types/scheduler": "npm:*" csstype: "npm:^3.0.2" - checksum: 10477a50fbd3c0cc5b8a2ade679f442717f68fb27c8460b2aa1d3256cd18c48f742bbe5b9ee37a8c4c5f832ffa37b3a23c09fd96dd880a8e3182d8929c05e803 + checksum: 4cc650c47ffb88baac29fb7a74e842e4af4a55f437086ef70250fdc75f0a5f2fcf8adc272d05ab2e00b1de6e14613296881271caee037dadf9130fdeb498c59e languageName: node linkType: hard @@ -3672,14 +3672,14 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^6.0.0": - version: 6.13.2 - resolution: "@typescript-eslint/eslint-plugin@npm:6.13.2" + version: 6.14.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.14.0" dependencies: "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:6.13.2" - "@typescript-eslint/type-utils": "npm:6.13.2" - "@typescript-eslint/utils": "npm:6.13.2" - "@typescript-eslint/visitor-keys": "npm:6.13.2" + "@typescript-eslint/scope-manager": "npm:6.14.0" + "@typescript-eslint/type-utils": "npm:6.14.0" + "@typescript-eslint/utils": "npm:6.14.0" + "@typescript-eslint/visitor-keys": "npm:6.14.0" debug: "npm:^4.3.4" graphemer: "npm:^1.4.0" ignore: "npm:^5.2.4" @@ -3692,44 +3692,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 531a4406d872738d165c6a66cb26e976523c94053b022a8210dc9fd10e91b79b705bc0fcc77145e9744e4108b53bdba55e02a10dc17757b22be92aff57849384 + checksum: 6360efb0e142ed91de5e9bddcd041f769feeedd256332733be08f7a74c8ae637cbfb78c6b85d747c73231bbb95cef95ed2d2854ab7d43aebfbedb3a191f447f1 languageName: node linkType: hard "@typescript-eslint/parser@npm:^6.0.0": - version: 6.13.2 - resolution: "@typescript-eslint/parser@npm:6.13.2" + version: 6.14.0 + resolution: "@typescript-eslint/parser@npm:6.14.0" dependencies: - "@typescript-eslint/scope-manager": "npm:6.13.2" - "@typescript-eslint/types": "npm:6.13.2" - "@typescript-eslint/typescript-estree": "npm:6.13.2" - "@typescript-eslint/visitor-keys": "npm:6.13.2" + "@typescript-eslint/scope-manager": "npm:6.14.0" + "@typescript-eslint/types": "npm:6.14.0" + "@typescript-eslint/typescript-estree": "npm:6.14.0" + "@typescript-eslint/visitor-keys": "npm:6.14.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 2c62b8cd8a37eb2ea59cd00e559f51a9f57af746e2040e872af3c58ddd3f4071ad7b7009789bdeb0e0d4ee0343bfe96ee77288020f3ae22d08e1674203f5e156 + checksum: 0344f7f640374e7e5a5b50e9c90fbd161611b3f455132e541ef9116eef7bd3acf364db64bd38d4b6b4fe148414494620c9df660f8ddce036019c38ae8e146585 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.13.2": - version: 6.13.2 - resolution: "@typescript-eslint/scope-manager@npm:6.13.2" +"@typescript-eslint/scope-manager@npm:6.14.0": + version: 6.14.0 + resolution: "@typescript-eslint/scope-manager@npm:6.14.0" dependencies: - "@typescript-eslint/types": "npm:6.13.2" - "@typescript-eslint/visitor-keys": "npm:6.13.2" - checksum: 9b159e5bb10dfb5953e71488200b4126378fc7e987ce7d90946aea9ec40cd66c7ada92399657c5d9794189b764ca6f4eb38a8dcb9e4c5aa50ab6000a39636b9c + "@typescript-eslint/types": "npm:6.14.0" + "@typescript-eslint/visitor-keys": "npm:6.14.0" + checksum: 8c59a215af3d7d24d8d0b21c28a858263de471650829f288a941e0eb8af8a054798da5c7594b7f39370219718270c18464b5edb96f451457e5f080a33ba57c2c languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.13.2": - version: 6.13.2 - resolution: "@typescript-eslint/type-utils@npm:6.13.2" +"@typescript-eslint/type-utils@npm:6.14.0": + version: 6.14.0 + resolution: "@typescript-eslint/type-utils@npm:6.14.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:6.13.2" - "@typescript-eslint/utils": "npm:6.13.2" + "@typescript-eslint/typescript-estree": "npm:6.14.0" + "@typescript-eslint/utils": "npm:6.14.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.0.1" peerDependencies: @@ -3737,23 +3737,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 1ca97c78abdf479aea0c54e869fda2ae2f69de1974cc063062ce7b5b16c7fdf497ea15c50a29dd5941ea1b6b77e8f1213a5c272a747e334ac69ede083f327468 + checksum: 836a6e84be5a245b07c76968c98e2f3bae064767dde720080fe8f33e226188510778dbca4199b7e42ef675ec3fd6d0ab522ec1c77d6e2a9b50e8e275fe7c72c9 languageName: node linkType: hard -"@typescript-eslint/types@npm:6.13.2": - version: 6.13.2 - resolution: "@typescript-eslint/types@npm:6.13.2" - checksum: 029918ca5b1442bb4bc435773504ce32191e2c3e2fde8d4176bb6513f03e3dfa2aa9724b2d22b1640656d666b97f7a7ebfeaf67b881d5e07250828fa83e3ebe8 +"@typescript-eslint/types@npm:6.14.0": + version: 6.14.0 + resolution: "@typescript-eslint/types@npm:6.14.0" + checksum: d59306a7a441982a4dcee7d775928fd5086aba9331f7a238f915723a0dc785df0e43af562a30a7c2f1b056a1e49fd64863a8d2450d31706193add0ade87334a4 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.13.2": - version: 6.13.2 - resolution: "@typescript-eslint/typescript-estree@npm:6.13.2" +"@typescript-eslint/typescript-estree@npm:6.14.0": + version: 6.14.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.14.0" dependencies: - "@typescript-eslint/types": "npm:6.13.2" - "@typescript-eslint/visitor-keys": "npm:6.13.2" + "@typescript-eslint/types": "npm:6.14.0" + "@typescript-eslint/visitor-keys": "npm:6.14.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" @@ -3762,34 +3762,34 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 1c4c59dce0c51fdfee34d9f418e64fe28e3ec1a97661efc8a3d2780bdff36aff38de9090d356a968f394fa6d4e9c058936ce9cd260d4c44a52761ecd74915bce + checksum: 767c3309987b8ad053a2403605a9bd7c4eb3283dece864a741a7531a1c28eea4d85acaa4613141b64e194f9f6c4cbc5bc762c9b9f3a67c6202aa8cbb18b180d2 languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.13.2, @typescript-eslint/utils@npm:^6.5.0": - version: 6.13.2 - resolution: "@typescript-eslint/utils@npm:6.13.2" +"@typescript-eslint/utils@npm:6.14.0, @typescript-eslint/utils@npm:^6.5.0": + version: 6.14.0 + resolution: "@typescript-eslint/utils@npm:6.14.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" "@types/json-schema": "npm:^7.0.12" "@types/semver": "npm:^7.5.0" - "@typescript-eslint/scope-manager": "npm:6.13.2" - "@typescript-eslint/types": "npm:6.13.2" - "@typescript-eslint/typescript-estree": "npm:6.13.2" + "@typescript-eslint/scope-manager": "npm:6.14.0" + "@typescript-eslint/types": "npm:6.14.0" + "@typescript-eslint/typescript-estree": "npm:6.14.0" semver: "npm:^7.5.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: 84969be91e7949868eaaa289288c9d71927f0e427b572501b0991d8d62b40a4234f7287c35b35d276ccbb53e9ea5457b8250fcf4941e60e6b9ba4065fbfba416 + checksum: 72689b2897b89e1bd1c71c1c2ae436d0ccfbcfffabf3be4378de74ad8138b2ecdbeeda7c1720e2f1754569e773f2fc7216f704335e1e56c38c7601ee1d190aeb languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.13.2": - version: 6.13.2 - resolution: "@typescript-eslint/visitor-keys@npm:6.13.2" +"@typescript-eslint/visitor-keys@npm:6.14.0": + version: 6.14.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.14.0" dependencies: - "@typescript-eslint/types": "npm:6.13.2" + "@typescript-eslint/types": "npm:6.14.0" eslint-visitor-keys: "npm:^3.4.1" - checksum: c173bc1fcc42c3075a5ee094e7f3bf0279d98315c25ff49e20d02d79022b1d0402accfa113b070afb4d52a6f6d180594b67baa8b6a784eabdf82b54dd1ff454c + checksum: 0e2363f9f1986ebdb41507c54a666fa1c336eb6beb383dc342a10844d3c42c89067b21c3f158851fa6f0825e1e451a5470b5454fde70a6fc33b4b0259462d954 languageName: node linkType: hard @@ -6097,12 +6097,12 @@ __metadata: languageName: node linkType: hard -"css-declaration-sorter@npm:^6.3.1": - version: 6.4.0 - resolution: "css-declaration-sorter@npm:6.4.0" +"css-declaration-sorter@npm:^7.0.0": + version: 7.1.1 + resolution: "css-declaration-sorter@npm:7.1.1" peerDependencies: postcss: ^8.0.9 - checksum: aef4d5927e576bae04349457be0607af44525cf5f4b28a91843c7b7f28fcbb302ba149385bb0e2172380556994e31680c5177b42d03502c417789b139e20cbc2 + checksum: bea446e441bafde21c3c7b3f7639559311da12eea140db7ee3c61e4f41df455b7b098df107f99bc0cca32a5020841cc94bf8a2d5efb1b383e51f9de478c4816e languageName: node linkType: hard @@ -6235,63 +6235,72 @@ __metadata: languageName: node linkType: hard -"cssnano-preset-default@npm:^6.0.1": - version: 6.0.1 - resolution: "cssnano-preset-default@npm:6.0.1" - dependencies: - css-declaration-sorter: "npm:^6.3.1" - cssnano-utils: "npm:^4.0.0" - postcss-calc: "npm:^9.0.0" - postcss-colormin: "npm:^6.0.0" - postcss-convert-values: "npm:^6.0.0" - postcss-discard-comments: "npm:^6.0.0" - postcss-discard-duplicates: "npm:^6.0.0" - postcss-discard-empty: "npm:^6.0.0" - postcss-discard-overridden: "npm:^6.0.0" - postcss-merge-longhand: "npm:^6.0.0" - postcss-merge-rules: "npm:^6.0.1" - postcss-minify-font-values: "npm:^6.0.0" - postcss-minify-gradients: "npm:^6.0.0" - postcss-minify-params: "npm:^6.0.0" - postcss-minify-selectors: "npm:^6.0.0" - postcss-normalize-charset: "npm:^6.0.0" - postcss-normalize-display-values: "npm:^6.0.0" - postcss-normalize-positions: "npm:^6.0.0" - postcss-normalize-repeat-style: "npm:^6.0.0" - postcss-normalize-string: "npm:^6.0.0" - postcss-normalize-timing-functions: "npm:^6.0.0" - postcss-normalize-unicode: "npm:^6.0.0" - postcss-normalize-url: "npm:^6.0.0" - postcss-normalize-whitespace: "npm:^6.0.0" - postcss-ordered-values: "npm:^6.0.0" - postcss-reduce-initial: "npm:^6.0.0" - postcss-reduce-transforms: "npm:^6.0.0" - postcss-svgo: "npm:^6.0.0" - postcss-unique-selectors: "npm:^6.0.0" +"cssnano-preset-default@npm:^6.0.2": + version: 6.0.2 + resolution: "cssnano-preset-default@npm:6.0.2" + dependencies: + css-declaration-sorter: "npm:^7.0.0" + cssnano-utils: "npm:^4.0.1" + postcss-calc: "npm:^9.0.1" + postcss-colormin: "npm:^6.0.1" + postcss-convert-values: "npm:^6.0.1" + postcss-discard-comments: "npm:^6.0.1" + postcss-discard-duplicates: "npm:^6.0.1" + postcss-discard-empty: "npm:^6.0.1" + postcss-discard-overridden: "npm:^6.0.1" + postcss-merge-longhand: "npm:^6.0.1" + postcss-merge-rules: "npm:^6.0.2" + postcss-minify-font-values: "npm:^6.0.1" + postcss-minify-gradients: "npm:^6.0.1" + postcss-minify-params: "npm:^6.0.1" + postcss-minify-selectors: "npm:^6.0.1" + postcss-normalize-charset: "npm:^6.0.1" + postcss-normalize-display-values: "npm:^6.0.1" + postcss-normalize-positions: "npm:^6.0.1" + postcss-normalize-repeat-style: "npm:^6.0.1" + postcss-normalize-string: "npm:^6.0.1" + postcss-normalize-timing-functions: "npm:^6.0.1" + postcss-normalize-unicode: "npm:^6.0.1" + postcss-normalize-url: "npm:^6.0.1" + postcss-normalize-whitespace: "npm:^6.0.1" + postcss-ordered-values: "npm:^6.0.1" + postcss-reduce-initial: "npm:^6.0.1" + postcss-reduce-transforms: "npm:^6.0.1" + postcss-svgo: "npm:^6.0.1" + postcss-unique-selectors: "npm:^6.0.1" peerDependencies: - postcss: ^8.2.15 - checksum: 401a8d0712cca6577df52cf4aac234ff4a946f0f51c0d09e7c518fff389706cff54d702ff22762e834b23401a89b836aef113e69cc66fa5dfa1f361bdd932495 + postcss: ^8.4.31 + checksum: c6f97674704c3a2a2473440549eac38ac722feebabbd39f2d4d1b8fae7f137f8fd0dfb88929e1ff737d54008de583c39e96f9dc450f2d71f8be6fc3bac2840a3 languageName: node linkType: hard -"cssnano-utils@npm:^4.0.0": - version: 4.0.0 - resolution: "cssnano-utils@npm:4.0.0" +"cssnano-utils@npm:^4.0.1": + version: 4.0.1 + resolution: "cssnano-utils@npm:4.0.1" peerDependencies: - postcss: ^8.2.15 - checksum: ca5cb2be5ec8ea624c28f5f54c00a440557afd3c2b25cb568517db44d230833743f3db30729126efe4d7fc616a42718dd76255bbefcb7d3cc7e3ff5989d907b3 + postcss: ^8.4.31 + checksum: 20513a393402f283c85c450ece43d1a6a06a9906b524481043ac203a86888a4ca5cbef878c615a58fdd82a9e870ce62c6f3fea9f51814034a084d8980e17cf96 languageName: node linkType: hard "cssnano@npm:^6.0.1": - version: 6.0.1 - resolution: "cssnano@npm:6.0.1" + version: 6.0.2 + resolution: "cssnano@npm:6.0.2" dependencies: - cssnano-preset-default: "npm:^6.0.1" - lilconfig: "npm:^2.1.0" + cssnano-preset-default: "npm:^6.0.2" + lilconfig: "npm:^3.0.0" peerDependencies: - postcss: ^8.2.15 - checksum: b73a3a257dd32201ce504cb34b08f1259c8a260b063f58d33e03283149d94ee2ba938d7f9beae1413f0f34e06828759575ade6ae95fa01d199f291e1d4f6d2c2 + postcss: ^8.4.31 + checksum: 5f4146a6c8937d24b0d1d33e3acd85db7913c7558cc80b23169f86c9a552d091a26e0af6adcc535f8355561872f797a917b9353e38fe935bbaf08ec2b66f5ff8 + languageName: node + linkType: hard + +"csso@npm:5.0.5": + version: 5.0.5 + resolution: "csso@npm:5.0.5" + dependencies: + css-tree: "npm:~2.2.0" + checksum: ab4beb1e97dd7e207c10e9925405b45f15a6cd1b4880a8686ad573aa6d476aed28b4121a666cffd26c37a26179f7b54741f7c257543003bfb244d06a62ad569b languageName: node linkType: hard @@ -6304,15 +6313,6 @@ __metadata: languageName: node linkType: hard -"csso@npm:^5.0.5": - version: 5.0.5 - resolution: "csso@npm:5.0.5" - dependencies: - css-tree: "npm:~2.2.0" - checksum: ab4beb1e97dd7e207c10e9925405b45f15a6cd1b4880a8686ad573aa6d476aed28b4121a666cffd26c37a26179f7b54741f7c257543003bfb244d06a62ad569b - languageName: node - linkType: hard - "cssom@npm:^0.5.0": version: 0.5.0 resolution: "cssom@npm:0.5.0" @@ -7359,8 +7359,8 @@ __metadata: linkType: hard "eslint-plugin-import@npm:~2.29.0": - version: 2.29.0 - resolution: "eslint-plugin-import@npm:2.29.0" + version: 2.29.1 + resolution: "eslint-plugin-import@npm:2.29.1" dependencies: array-includes: "npm:^3.1.7" array.prototype.findlastindex: "npm:^1.2.3" @@ -7378,16 +7378,16 @@ __metadata: object.groupby: "npm:^1.0.1" object.values: "npm:^1.1.7" semver: "npm:^6.3.1" - tsconfig-paths: "npm:^3.14.2" + tsconfig-paths: "npm:^3.15.0" peerDependencies: eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: 761a4e1fbc2cd318e62350bed4c448f8b11ed83091d6bb7776f096556363a09debd9922b39fd2714c895edc9aaea82e08e684eb632283f880c58a91e4bae6733 + checksum: 5f35dfbf4e8e67f741f396987de9504ad125c49f4144508a93282b4ea0127e052bde65ab6def1f31b6ace6d5d430be698333f75bdd7dca3bc14226c92a083196 languageName: node linkType: hard "eslint-plugin-jsdoc@npm:^46.1.0": - version: 46.9.0 - resolution: "eslint-plugin-jsdoc@npm:46.9.0" + version: 46.9.1 + resolution: "eslint-plugin-jsdoc@npm:46.9.1" dependencies: "@es-joy/jsdoccomment": "npm:~0.41.0" are-docs-informative: "npm:^0.0.2" @@ -7397,10 +7397,10 @@ __metadata: esquery: "npm:^1.5.0" is-builtin-module: "npm:^3.2.1" semver: "npm:^7.5.4" - spdx-expression-parse: "npm:^3.0.1" + spdx-expression-parse: "npm:^4.0.0" peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: 4566b0f9bda54b446c813cf5ea93ae6d5866cbc4d448cb957b9ce2563f934d3ed2ed4e665e5a870750860a57137a1714c38599c35c60be16dce0f8e5a75b6ff6 + checksum: d15d68797e85bb7b6fdcfc1170653683c16ab1d62c2e9c537101e774cb3231913e2bc4781f2bb808d074adce5699e5b545e450c6801b637c6434587d226ad6ac languageName: node linkType: hard @@ -7521,13 +7521,13 @@ __metadata: linkType: hard "eslint@npm:^8.41.0": - version: 8.55.0 - resolution: "eslint@npm:8.55.0" + version: 8.56.0 + resolution: "eslint@npm:8.56.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" "@eslint-community/regexpp": "npm:^4.6.1" "@eslint/eslintrc": "npm:^2.1.4" - "@eslint/js": "npm:8.55.0" + "@eslint/js": "npm:8.56.0" "@humanwhocodes/config-array": "npm:^0.11.13" "@humanwhocodes/module-importer": "npm:^1.0.1" "@nodelib/fs.walk": "npm:^1.2.8" @@ -7564,7 +7564,7 @@ __metadata: text-table: "npm:^0.2.0" bin: eslint: bin/eslint.js - checksum: d28c0b60f19bb7d355cb8393e77b018c8f548dba3f820b799c89bb2e0c436ee26084e700c5e57e1e97e7972ec93065277849141b82e7b0c0d02c2dc1e553a2a1 + checksum: 2be598f7da1339d045ad933ffd3d4742bee610515cd2b0d9a2b8b729395a01d4e913552fff555b559fccaefd89d7b37632825789d1b06470608737ae69ab43fb languageName: node linkType: hard @@ -7900,20 +7900,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.1": - version: 3.3.1 - resolution: "fast-glob@npm:3.3.1" - dependencies: - "@nodelib/fs.stat": "npm:^2.0.2" - "@nodelib/fs.walk": "npm:^1.2.3" - glob-parent: "npm:^5.1.2" - merge2: "npm:^1.3.0" - micromatch: "npm:^4.0.4" - checksum: b68431128fb6ce4b804c5f9622628426d990b66c75b21c0d16e3d80e2d1398bf33f7e1724e66a2e3f299285dcf5b8d745b122d0304e7dd66f5231081f33ec67c - languageName: node - linkType: hard - -"fast-glob@npm:^3.3.2": +"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.1, fast-glob@npm:^3.3.2": version: 3.3.2 resolution: "fast-glob@npm:3.3.2" dependencies: @@ -9093,14 +9080,7 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.2.0, ignore@npm:^5.2.4": - version: 5.2.4 - resolution: "ignore@npm:5.2.4" - checksum: 7c7cd90edd9fea6e037f9b9da4b01bf0a86b198ce78345f9bbd983929d68ff14830be31111edc5d70c264921f4962404d75b7262b4d9cc3bc12381eccbd03096 - languageName: node - linkType: hard - -"ignore@npm:^5.3.0": +"ignore@npm:^5.2.0, ignore@npm:^5.2.4, ignore@npm:^5.3.0": version: 5.3.0 resolution: "ignore@npm:5.3.0" checksum: dc06bea5c23aae65d0725a957a0638b57e235ae4568dda51ca142053ed2c352de7e3bc93a69b2b32ac31966a1952e9a93c5ef2e2ab7c6b06aef9808f6b55b571 @@ -10871,20 +10851,13 @@ __metadata: languageName: node linkType: hard -"lilconfig@npm:3.0.0": +"lilconfig@npm:3.0.0, lilconfig@npm:^3.0.0": version: 3.0.0 resolution: "lilconfig@npm:3.0.0" checksum: 7f5ee7a658dc016cacf146815e8d88b06f06f4402823b8b0934e305a57a197f55ccc9c5cd4fb5ea1b2b821c8ccaf2d54abd59602a4931af06eabda332388d3e6 languageName: node linkType: hard -"lilconfig@npm:^2.1.0": - version: 2.1.0 - resolution: "lilconfig@npm:2.1.0" - checksum: 64645641aa8d274c99338e130554abd6a0190533c0d9eb2ce7ebfaf2e05c7d9961f3ffe2bfa39efd3b60c521ba3dd24fa236fe2775fc38501bf82bf49d4678b8 - languageName: node - linkType: hard - "lines-and-columns@npm:^1.1.6": version: 1.2.4 resolution: "lines-and-columns@npm:1.2.4" @@ -12717,7 +12690,7 @@ __metadata: languageName: node linkType: hard -"postcss-calc@npm:^9.0.0": +"postcss-calc@npm:^9.0.1": version: 9.0.1 resolution: "postcss-calc@npm:9.0.1" dependencies: @@ -12729,65 +12702,65 @@ __metadata: languageName: node linkType: hard -"postcss-colormin@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-colormin@npm:6.0.0" +"postcss-colormin@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-colormin@npm:6.0.1" dependencies: browserslist: "npm:^4.21.4" caniuse-api: "npm:^3.0.0" colord: "npm:^2.9.1" postcss-value-parser: "npm:^4.2.0" peerDependencies: - postcss: ^8.2.15 - checksum: b05763b68f7f23333f408734f13be4bde641934ecbde25ac7d7fa648ab5e826716bffac0193067b317e861c6dabad81db9c012e865a83f81b6bce5c7e25c0fdd + postcss: ^8.4.31 + checksum: b0056812b3436b05b6b84284a1ebe68a72299f23e7eeb0b7b40a775978d06a1cbe235f3665e3f694f5de76fe7d9b93db607536d07697b31a59fd4e8705e5b64d languageName: node linkType: hard -"postcss-convert-values@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-convert-values@npm:6.0.0" +"postcss-convert-values@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-convert-values@npm:6.0.1" dependencies: browserslist: "npm:^4.21.4" postcss-value-parser: "npm:^4.2.0" peerDependencies: - postcss: ^8.2.15 - checksum: 8c20d31a39e0ddf7db4fde0da62e293279b5ee84c36919f2e5760650fa6f2984f1a40bfdbe8d1f7829bd37b17e5e589535f0aaaf71d4df29ad203cef830b9d7a + postcss: ^8.4.31 + checksum: 53b951d7475206969c63b8427a2dea0ccba0a7cb08122e5f05aee8d12b09c870c070b101c9f8eceda76ff4d0fd9e5fa9385e83f143d658bb729dbb6a3583b872 languageName: node linkType: hard -"postcss-discard-comments@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-discard-comments@npm:6.0.0" +"postcss-discard-comments@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-discard-comments@npm:6.0.1" peerDependencies: - postcss: ^8.2.15 - checksum: c8792cd99c7696b21917d55937e02fb854a82ee308edf7564f18ad19bec4abf4756ba234e17f7d129d6b0dbaf6253bcddc435b1aeee190d4d26dcc2448f5453a + postcss: ^8.4.31 + checksum: 5e9128ffb8c005081bb0521f5a23cf090e8513d928ed39935504ffde2e335a62a7e1a749c5c7bc2d03f06a8667900d19dd7eed19dfa4273043b5fd760476260d languageName: node linkType: hard -"postcss-discard-duplicates@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-discard-duplicates@npm:6.0.0" +"postcss-discard-duplicates@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-discard-duplicates@npm:6.0.1" peerDependencies: - postcss: ^8.2.15 - checksum: 5fb0de3b187b09538a8c10f25bcc3e7b0865337a96a0599f8213864f0d52812f6c90142d170258293a30484b95e096dee28fc8fddb302016f93d4a8d269bb18f + postcss: ^8.4.31 + checksum: b9ea10a3c7528bb1630613c11756f809a95da634822d943fa91b28f2a37787e7cdb9ff96deed9776e2c3753d35e42c8afd5074b630930df7b5150573d4beda23 languageName: node linkType: hard -"postcss-discard-empty@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-discard-empty@npm:6.0.0" +"postcss-discard-empty@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-discard-empty@npm:6.0.1" peerDependencies: - postcss: ^8.2.15 - checksum: 5dfe01f93ee2bb85e71f7832498bd051b772b9c724a5630f749237b07a14b47c2b2800b4215ab4cf0d8cba29552725b40334f3ef9d349f7aacf410ad351715dc + postcss: ^8.4.31 + checksum: 6b95e588a3e8fb262e56bd313060daf29d7c9d44184bb6c4c5858ae81d6cd2907b15b3e3023b6621d50a67cfc10e6077920ff1e908892b207dee29477376498f languageName: node linkType: hard -"postcss-discard-overridden@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-discard-overridden@npm:6.0.0" +"postcss-discard-overridden@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-discard-overridden@npm:6.0.1" peerDependencies: - postcss: ^8.2.15 - checksum: 3a0c91241a95a887ef10227c761fb2c48870966bda5530de635002e485abc2743dfbfdc96e3b6a21f10c6231f0cfbe1a0eae0a01a89629d64a711eab3ee008c6 + postcss: ^8.4.31 + checksum: 22f9d56e53b90bc0f8e6d1c24d6da6c7c1a9d757644a128a7a4263a5479aaa8eca4ce3bfe9db10358051635ed40e8778a68c3f1831b7163eae10ced001db4a87 languageName: node linkType: hard @@ -12814,77 +12787,77 @@ __metadata: languageName: node linkType: hard -"postcss-merge-longhand@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-merge-longhand@npm:6.0.0" +"postcss-merge-longhand@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-merge-longhand@npm:6.0.1" dependencies: postcss-value-parser: "npm:^4.2.0" - stylehacks: "npm:^6.0.0" + stylehacks: "npm:^6.0.1" peerDependencies: - postcss: ^8.2.15 - checksum: 0b67c590d301ab7f087ea7421e1eac0cccd2ff1c146a2dfa16d3f32b770d12a5999b8c6ea177efc443f4fb9df13b941c401365c634533878eef1982ad9d0bb98 + postcss: ^8.4.31 + checksum: 2c0eb81b6c6d3d2af3b129c46d10317b7923f218db1cadcb4723091fb951fe4624638002b65f235151129d4ce9b4775a6ed0d5fa13419c0df580f72e15fa4ad3 languageName: node linkType: hard -"postcss-merge-rules@npm:^6.0.1": - version: 6.0.1 - resolution: "postcss-merge-rules@npm:6.0.1" +"postcss-merge-rules@npm:^6.0.2": + version: 6.0.2 + resolution: "postcss-merge-rules@npm:6.0.2" dependencies: browserslist: "npm:^4.21.4" caniuse-api: "npm:^3.0.0" - cssnano-utils: "npm:^4.0.0" + cssnano-utils: "npm:^4.0.1" postcss-selector-parser: "npm:^6.0.5" peerDependencies: - postcss: ^8.2.15 - checksum: b6a2a196905cd170757aa7b8bc74dab1fc7e2b2ca6a19c6d355fb7c41ff736023b4176c1008a7049f6a1b24a94a30d066c4e51229c1282a941f7fd6056085af7 + postcss: ^8.4.31 + checksum: 138a9921423420116b20e5761a1139392f0bcfcf34264fe11e254917d9c3170e3c0478a1b409e227d22bb0d9820b0168a871a240215d114e9c1e218ee6c132e6 languageName: node linkType: hard -"postcss-minify-font-values@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-minify-font-values@npm:6.0.0" +"postcss-minify-font-values@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-minify-font-values@npm:6.0.1" dependencies: postcss-value-parser: "npm:^4.2.0" peerDependencies: - postcss: ^8.2.15 - checksum: 6b74b1ec19bf76dcae7947c42145cb200b38767680512728f76168ae246db453798760e56111bd28ade9011d3655a79da4b33a93e5349f98fb0c1b22cc65ff36 + postcss: ^8.4.31 + checksum: 15af236245a6d27f1c83c943ef90d144ca043894bbd86f134506a984811a936a06824739984824965c7c3fd5a0ff4ed299f26a33f3b628662aa4fb40d7536fd0 languageName: node linkType: hard -"postcss-minify-gradients@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-minify-gradients@npm:6.0.0" +"postcss-minify-gradients@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-minify-gradients@npm:6.0.1" dependencies: colord: "npm:^2.9.1" - cssnano-utils: "npm:^4.0.0" + cssnano-utils: "npm:^4.0.1" postcss-value-parser: "npm:^4.2.0" peerDependencies: - postcss: ^8.2.15 - checksum: 59046acd470bee151291ba99421846d776c4ed243acb05a005e74f64f92b968d712d35e727f5e4a90e632d6d6aeb3a01083469f50bfdf1fb9ecae7f4ae52d9b8 + postcss: ^8.4.31 + checksum: e700c3f6dc425072ff739fb18bb71c970599e0d909b326f4a5c84e91cf24c4f1ee78e4d161bd4cdf6e25b7d78f1ad082bb885afdd2a150f9b281520fc6359d5c languageName: node linkType: hard -"postcss-minify-params@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-minify-params@npm:6.0.0" +"postcss-minify-params@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-minify-params@npm:6.0.1" dependencies: browserslist: "npm:^4.21.4" - cssnano-utils: "npm:^4.0.0" + cssnano-utils: "npm:^4.0.1" postcss-value-parser: "npm:^4.2.0" peerDependencies: - postcss: ^8.2.15 - checksum: d4d1469b7ad7fe53900eb19c156ec6dcfeaf71641d29ba4df31f47d8fa8ac700df5b8d3e3768e66d695d5356ed348cea901314653046c8e48422962f165a1933 + postcss: ^8.4.31 + checksum: 0b34817f032ec9793fad4d33f3ba5551531073a36c9120d77194a3edeee860132951ed6954913494e5a6752ae8da1bc5cdb2a44fa5f428621afae8edddb0ca80 languageName: node linkType: hard -"postcss-minify-selectors@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-minify-selectors@npm:6.0.0" +"postcss-minify-selectors@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-minify-selectors@npm:6.0.1" dependencies: postcss-selector-parser: "npm:^6.0.5" peerDependencies: - postcss: ^8.2.15 - checksum: 1cdd3bd231cf25f54ab370d959f727dfcbe839a1d97bcfd65add9df73747a45d299a009ff16111bbe78943e8f81dcf5f84ae4106847b23dd3652de7aadc0b297 + postcss: ^8.4.31 + checksum: ffc7ebb286beda2b2aa0ed13abafc89b5ffe232a48d57d3f2b9f69e167e354482a6f5279e9118bed753bf6e82d3cfb21228a6b07acd93d0dc9e01bbf0e7ebc75 languageName: node linkType: hard @@ -12932,136 +12905,136 @@ __metadata: languageName: node linkType: hard -"postcss-normalize-charset@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-normalize-charset@npm:6.0.0" +"postcss-normalize-charset@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-normalize-charset@npm:6.0.1" peerDependencies: - postcss: ^8.2.15 - checksum: 5232eac7f62097b1d349546182af2db7db34989867c147517cd407ab23c8450558a7f858eb8dac130959dae2d02d3460c5afa510e0ffe22221cb218f2bd79adb + postcss: ^8.4.31 + checksum: 8c09eedaf8813123875c65ab35120f14a87d6b9e8d6805fa808e3a714a8f868d15123f34f61e2240d89225f2f5c2bdabbcdf6385ce86b2487370d8994a65a857 languageName: node linkType: hard -"postcss-normalize-display-values@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-normalize-display-values@npm:6.0.0" +"postcss-normalize-display-values@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-normalize-display-values@npm:6.0.1" dependencies: postcss-value-parser: "npm:^4.2.0" peerDependencies: - postcss: ^8.2.15 - checksum: 58163258a52610fa0d2b61bd6e872b9a2b25da1f2209cbf34fad3b62a4139fff9e0e6b298dcd1adfe6ac556098aad8b79c387280f3a949180f8fb12e6b41fecf + postcss: ^8.4.31 + checksum: d08a92c653fb4f2506e029ceb8e3fdae9bc937fb1a7e80ecde759d02f6d15f69211af384d89d8582b160fd129abd9c77c8c64d75379417098ee5a2ba779e33d3 languageName: node linkType: hard -"postcss-normalize-positions@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-normalize-positions@npm:6.0.0" +"postcss-normalize-positions@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-normalize-positions@npm:6.0.1" dependencies: postcss-value-parser: "npm:^4.2.0" peerDependencies: - postcss: ^8.2.15 - checksum: de2ced6cfdf2931d7cbc8f9c96bb12487119dba1b454c7ac01fd19f7afdaa9bf6c63f59624281293379ead5a3d5e883007a3f192f02c40ab41528ccc5a399f5c + postcss: ^8.4.31 + checksum: bb0267b13c92791543f5e9f94b119a0540e08aa46f600acd73a692cd38d07d2d2fddb11148a81adb58e3f65671eebb05ea38d2ded48f3202b2582f1199aa848e languageName: node linkType: hard -"postcss-normalize-repeat-style@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-normalize-repeat-style@npm:6.0.0" +"postcss-normalize-repeat-style@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-normalize-repeat-style@npm:6.0.1" dependencies: postcss-value-parser: "npm:^4.2.0" peerDependencies: - postcss: ^8.2.15 - checksum: 1643132094067709ca7d1fa2beededd28565c83bc8a6c2a4dec879a97e1d425ca1293a8832a45732eef12b52960f024330cfb654a8a222fb7ea768a75989c31e + postcss: ^8.4.31 + checksum: f6e943dbbf9341dd6ce2c9fc6820e8ae2a838d1db84f58f75b1e5c1b8b9d6895d17fb30b320e2189b8747f844713ec687540b5b1d52ccd6c9108d6d35328c659 languageName: node linkType: hard -"postcss-normalize-string@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-normalize-string@npm:6.0.0" +"postcss-normalize-string@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-normalize-string@npm:6.0.1" dependencies: postcss-value-parser: "npm:^4.2.0" peerDependencies: - postcss: ^8.2.15 - checksum: d586ce274451229c6a3d625edef882b342ab7702babb632845c8c201c7bcc08481f282000d19d17edb7b5ef0b1982e715a16ab60990d124e937c4aef3304151e + postcss: ^8.4.31 + checksum: afcdd69522fc3ebafc349c2ef4b62f1e734ade9b6148fd20f2b841477808ac6cf6e5bfbb533c492fdc6bb2184b84be8ebb800a6ae174c4313f87fb0695088cc0 languageName: node linkType: hard -"postcss-normalize-timing-functions@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-normalize-timing-functions@npm:6.0.0" +"postcss-normalize-timing-functions@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-normalize-timing-functions@npm:6.0.1" dependencies: postcss-value-parser: "npm:^4.2.0" peerDependencies: - postcss: ^8.2.15 - checksum: a70742648cec15eea031096f2ad99c21c79228ce4c4ccc9f63c277c07e9e3add96298cc67b0b1797896507248153e0a662f85f490f53147ded7008b459dd5ba3 + postcss: ^8.4.31 + checksum: c1c81d0dcb2f74fbd69cc45b0b6bd6cde390a0c9df602aabbf3eb2149a49da48e808837e811d22a525ffb036e158e63b4b2cf12c94cf28f2c2f6af858876134e languageName: node linkType: hard -"postcss-normalize-unicode@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-normalize-unicode@npm:6.0.0" +"postcss-normalize-unicode@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-normalize-unicode@npm:6.0.1" dependencies: browserslist: "npm:^4.21.4" postcss-value-parser: "npm:^4.2.0" peerDependencies: - postcss: ^8.2.15 - checksum: cd9b06ed09c29ccc0b2cb222044d7ec49fb710fdd6f0878b26d7f3324478d8271a555ba3d82fc8d9fdcf8671a83c499cdfa09c0e73d4dee928adff4042ed8b22 + postcss: ^8.4.31 + checksum: 8057748dade94dc2dd63a3b75a85e394c2e9a7076053886ff08aa9b7729d383f204eda52d882e5361ae1ec493036e90b2e18dcc5f8c9b3a8f1cbfada12bcc05b languageName: node linkType: hard -"postcss-normalize-url@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-normalize-url@npm:6.0.0" +"postcss-normalize-url@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-normalize-url@npm:6.0.1" dependencies: postcss-value-parser: "npm:^4.2.0" peerDependencies: - postcss: ^8.2.15 - checksum: 719a7feee4adf638cc0b4bc204d89485388ca81f0ad0a181a225122f488f956abd29f429d69e5a57fffe93fbd2a22eab7737bd8b55b19979efba26e008b2ec11 + postcss: ^8.4.31 + checksum: 4e3e713a95e01f263feccd041b2b10016a0a09e494c81567f012d1326d9b2d57dc4a68956a820313630370c0ef591bdbb37cc96ed259022559623be179aad436 languageName: node linkType: hard -"postcss-normalize-whitespace@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-normalize-whitespace@npm:6.0.0" +"postcss-normalize-whitespace@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-normalize-whitespace@npm:6.0.1" dependencies: postcss-value-parser: "npm:^4.2.0" peerDependencies: - postcss: ^8.2.15 - checksum: 8421dd5813c1e555d7c2847dd8b71a5138ee2091341ebd1ea686d5b00cd46d249a29027e142289f873ca7f5fc995b51eb68f9693fec6d61cf951c759d109c37d + postcss: ^8.4.31 + checksum: 259c0b7653f033ed14303602a30e458c37dc63ee55f47226b6379a6ea553ca7c9b971d49715b8f3f36a3a06927f6f87d7997c027ad4664af3bca37a5fe30352e languageName: node linkType: hard -"postcss-ordered-values@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-ordered-values@npm:6.0.0" +"postcss-ordered-values@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-ordered-values@npm:6.0.1" dependencies: - cssnano-utils: "npm:^4.0.0" + cssnano-utils: "npm:^4.0.1" postcss-value-parser: "npm:^4.2.0" peerDependencies: - postcss: ^8.2.15 - checksum: b01352b0ea014e0037a5b8b3bd866696924bfb2cf3b47b73547786a1954e6771c04790fbe4c651bf029bafdbfde70f49e611f9ef309e945f753425841f343017 + postcss: ^8.4.31 + checksum: 2e71f035c90b26d7a8d31e1b716f977532367f75bc76de3318b6ba7b2e1ec43c011cc09e741f59f7d93dff427b7d90a35db0b460d2f171a6f0c6e8c938ef30ad languageName: node linkType: hard -"postcss-reduce-initial@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-reduce-initial@npm:6.0.0" +"postcss-reduce-initial@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-reduce-initial@npm:6.0.1" dependencies: browserslist: "npm:^4.21.4" caniuse-api: "npm:^3.0.0" peerDependencies: - postcss: ^8.2.15 - checksum: 7cf6340bde9f70c7d9b20bc3ee53e883bf27ed56fcc3bb2a2c736b311d977098a7c3a6b9e4be4d2c159d0042bf7742bb5af59628cd89cf838968dacc5ae15c80 + postcss: ^8.4.31 + checksum: 3f8f6c26ceeb79ddc285b0e01183fe30e911dd26b3abcdca56568e2bef3747f2b7f22ee3f9117e9752e1e93c10bcd88bd6a2842ca525b54336726292ebd3c3ad languageName: node linkType: hard -"postcss-reduce-transforms@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-reduce-transforms@npm:6.0.0" +"postcss-reduce-transforms@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-reduce-transforms@npm:6.0.1" dependencies: postcss-value-parser: "npm:^4.2.0" peerDependencies: - postcss: ^8.2.15 - checksum: 6da900d22dd8760b8a2ace32013036e3c4c4d9d560c31255eceea54563e3ddb2ca830bc9072fe2a1abacb8c48a008656887fc2f6ba1873e590342ad8e6bc269d + postcss: ^8.4.31 + checksum: de7631302311071d86622166539162e69df506785e3674afab0602c86ed9aa67799e44405b40327f0011d58089d2dc4e2ae481b21812177818e28f9272d350a5 languageName: node linkType: hard @@ -13100,26 +13073,26 @@ __metadata: languageName: node linkType: hard -"postcss-svgo@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-svgo@npm:6.0.0" +"postcss-svgo@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-svgo@npm:6.0.1" dependencies: postcss-value-parser: "npm:^4.2.0" - svgo: "npm:^3.0.2" + svgo: "npm:^3.0.5" peerDependencies: - postcss: ^8.2.15 - checksum: ec567cd5e982e3c0393695628bc508b87dcfe4e4b2049930e79e6c629c349fad19403f0d39d76ceda3e0f15ffd065304e76152f397fae2f3f848cdb847a0b564 + postcss: ^8.4.31 + checksum: 021da9b0d0696fce970f407891a0d6c05e51d1908af435026e0cd5936a75cd8502a7d504cd0e6a33b6f3369fee41f01b848e5bd919aecc3e804ce6308e91a6cc languageName: node linkType: hard -"postcss-unique-selectors@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-unique-selectors@npm:6.0.0" +"postcss-unique-selectors@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-unique-selectors@npm:6.0.1" dependencies: postcss-selector-parser: "npm:^6.0.5" peerDependencies: - postcss: ^8.2.15 - checksum: 63e81a7965ff8874fdf39ef0ae0f12cc21352548733538f52eda73f0ed5a7fab7fda9090facf50395d07873c5a6f02d31a6171fd476c80858b03090ec4c61d31 + postcss: ^8.4.31 + checksum: 637e35775d0ee8fbcf4a81b28d3832c5076de7c0232eb7769d4fbbf783f26793e2ec95e18461ae3b9f5f5cd63c3de9db102464487ba2488d4947aad24dc8841f languageName: node linkType: hard @@ -13284,12 +13257,12 @@ __metadata: linkType: hard "prom-client@npm:^15.0.0": - version: 15.0.0 - resolution: "prom-client@npm:15.0.0" + version: 15.1.0 + resolution: "prom-client@npm:15.1.0" dependencies: "@opentelemetry/api": "npm:^1.4.0" tdigest: "npm:^0.1.1" - checksum: 4d69d4a6e086a80f1e7b5716c53d6be49d99dba8451f2a8117708f581f69648f47df68060cbea1c18e24fc1efe675868f85c5da89d0ef8d6f962a52b5f50c356 + checksum: c10781adbf49225298e44da5396a51a0bd4d0cddc3c7e237ba50e888e12ead26a8f98261f362a442f1bbcdaddd6e7302d5675b37beac67ea9b6f82e4d39fb3cc languageName: node linkType: hard @@ -15149,13 +15122,13 @@ __metadata: languageName: node linkType: hard -"spdx-expression-parse@npm:^3.0.1": - version: 3.0.1 - resolution: "spdx-expression-parse@npm:3.0.1" +"spdx-expression-parse@npm:^4.0.0": + version: 4.0.0 + resolution: "spdx-expression-parse@npm:4.0.0" dependencies: spdx-exceptions: "npm:^2.1.0" spdx-license-ids: "npm:^3.0.0" - checksum: 6f8a41c87759fa184a58713b86c6a8b028250f158159f1d03ed9d1b6ee4d9eefdc74181c8ddc581a341aa971c3e7b79e30b59c23b05d2436d5de1c30bdef7171 + checksum: 965c487e77f4fb173f1c471f3eef4eb44b9f0321adc7f93d95e7620da31faa67d29356eb02523cd7df8a7fc1ec8238773cdbf9e45bd050329d2b26492771b736 languageName: node linkType: hard @@ -15592,15 +15565,15 @@ __metadata: languageName: node linkType: hard -"stylehacks@npm:^6.0.0": - version: 6.0.0 - resolution: "stylehacks@npm:6.0.0" +"stylehacks@npm:^6.0.1": + version: 6.0.1 + resolution: "stylehacks@npm:6.0.1" dependencies: browserslist: "npm:^4.21.4" postcss-selector-parser: "npm:^6.0.4" peerDependencies: - postcss: ^8.2.15 - checksum: 6ce277c816dd826fdc765258d612a160bad03dae52ab51ef1676efae07e96923ebeb6880d6522eefc50d2e81cb90b632615120c73aed190f345e8d836def67b6 + postcss: ^8.4.31 + checksum: 0877016f5b2a06b8ceaf39382b0c33da11ea93268209444f67f29b1ce465994058f305fc3bc90dda21e8664c959561fbb06ba12b82289c3b26ba832c6979d513 languageName: node linkType: hard @@ -15824,19 +15797,20 @@ __metadata: languageName: node linkType: hard -"svgo@npm:^3.0.2": - version: 3.0.2 - resolution: "svgo@npm:3.0.2" +"svgo@npm:^3.0.5": + version: 3.1.0 + resolution: "svgo@npm:3.1.0" dependencies: "@trysound/sax": "npm:0.2.0" commander: "npm:^7.2.0" css-select: "npm:^5.1.0" css-tree: "npm:^2.2.1" - csso: "npm:^5.0.5" + css-what: "npm:^6.1.0" + csso: "npm:5.0.5" picocolors: "npm:^1.0.0" bin: - svgo: bin/svgo - checksum: d682d416dd68cdcbab5e1e77b93d621325480e97dfe87777e845ea9a0ce05d03fc837ce17080af67e787f6b24430b805ff79f4591dda30a0ab4060b6a3ac2adf + svgo: ./bin/svgo + checksum: b3f00b3319dee6ddc53f8b8ac5acef581860e1708c98b492169e096621edc1bdf46e3778099e3dffb5116bf0d4c074a686099843dbc020c73b3ccfae7b6a88f0 languageName: node linkType: hard @@ -16179,15 +16153,15 @@ __metadata: languageName: node linkType: hard -"tsconfig-paths@npm:^3.14.2": - version: 3.14.2 - resolution: "tsconfig-paths@npm:3.14.2" +"tsconfig-paths@npm:^3.15.0": + version: 3.15.0 + resolution: "tsconfig-paths@npm:3.15.0" dependencies: "@types/json5": "npm:^0.0.29" json5: "npm:^1.0.2" minimist: "npm:^1.2.6" strip-bom: "npm:^3.0.0" - checksum: fdc92bb7b18b31c0e76f8ec4f98d07236b09590fd6578e587ad024792c8b2235d65125a8fd007fa47a84400f84ceccbf33f24e5198d953249e7204f4cef3517c + checksum: 5b4f301a2b7a3766a986baf8fc0e177eb80bdba6e396792ff92dc23b5bca8bb279fc96517dcaaef63a3b49bebc6c4c833653ec58155780bc906bdbcf7dda0ef5 languageName: node linkType: hard