diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 1a16472bdb12cd78e5802c572af9a3f771eaf26b..0d0fbfac91647ecad474b420f0ddfbad1133d39e 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -1412,52 +1412,6 @@ Style/RedundantFetchBlock:
     - 'config/initializers/paperclip.rb'
     - 'config/puma.rb'
 
-# This cop supports safe autocorrection (--autocorrect).
-Style/RedundantRegexpCharacterClass:
-  Exclude:
-    - 'app/lib/link_details_extractor.rb'
-    - 'app/lib/tag_manager.rb'
-    - 'app/models/domain_allow.rb'
-    - 'app/models/domain_block.rb'
-    - 'app/services/fetch_oembed_service.rb'
-    - 'config/initializers/rack_attack.rb'
-    - 'lib/tasks/emojis.rake'
-    - 'lib/tasks/mastodon.rake'
-
-# This cop supports safe autocorrection (--autocorrect).
-Style/RedundantRegexpEscape:
-  Exclude:
-    - 'app/lib/webfinger_resource.rb'
-    - 'app/models/account.rb'
-    - 'app/models/tag.rb'
-    - 'app/services/fetch_link_card_service.rb'
-    - 'config/initializers/twitter_regex.rb'
-    - 'lib/paperclip/color_extractor.rb'
-    - 'lib/tasks/mastodon.rake'
-
-# This cop supports safe autocorrection (--autocorrect).
-# Configuration parameters: EnforcedStyle, AllowInnerSlashes.
-# SupportedStyles: slashes, percent_r, mixed
-Style/RegexpLiteral:
-  Exclude:
-    - 'app/lib/link_details_extractor.rb'
-    - 'app/lib/plain_text_formatter.rb'
-    - 'app/lib/tag_manager.rb'
-    - 'app/lib/text_formatter.rb'
-    - 'app/models/account.rb'
-    - 'app/models/domain_allow.rb'
-    - 'app/models/domain_block.rb'
-    - 'app/models/site_upload.rb'
-    - 'app/models/tag.rb'
-    - 'app/services/backup_service.rb'
-    - 'app/services/fetch_oembed_service.rb'
-    - 'app/services/search_service.rb'
-    - 'config/initializers/rack_attack.rb'
-    - 'config/initializers/twitter_regex.rb'
-    - 'config/routes.rb'
-    - 'lib/mastodon/premailer_webpack_strategy.rb'
-    - 'lib/tasks/mastodon.rake'
-
 # This cop supports unsafe autocorrection (--autocorrect-all).
 # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength.
 # AllowedMethods: present?, blank?, presence, try, try!
diff --git a/app/lib/link_details_extractor.rb b/app/lib/link_details_extractor.rb
index dfed69285f4ebcd7c92c946d3b3135f92210c6a4..f0aeec0b3e68f9ac32b3af19652f6e6391a80083 100644
--- a/app/lib/link_details_extractor.rb
+++ b/app/lib/link_details_extractor.rb
@@ -7,15 +7,15 @@ class LinkDetailsExtractor
   # Some publications wrap their JSON-LD data in their <script> tags
   # in commented-out CDATA blocks, they need to be removed before
   # attempting to parse JSON
-  CDATA_JUNK_PATTERN = %r{^[\s]*(
-    (/\*[\s]*<!\[CDATA\[[\s]*\*/) # Block comment style opening
+  CDATA_JUNK_PATTERN = %r{^\s*(
+    (/\*\s*<!\[CDATA\[\s*\*/) # Block comment style opening
     |
-    (//[\s]*<!\[CDATA\[) # Single-line comment style opening
+    (//\s*<!\[CDATA\[) # Single-line comment style opening
     |
-    (/\*[\s]*\]\]>[\s]*\*/) # Block comment style closing
+    (/\*\s*\]\]>\s*\*/) # Block comment style closing
     |
-    (//[\s]*\]\]>) # Single-line comment style closing
-  )[\s]*$}x
+    (//\s*\]\]>) # Single-line comment style closing
+  )\s*$}x
 
   class StructuredData
     SUPPORTED_TYPES = %w(
@@ -204,7 +204,7 @@ class LinkDetailsExtractor
   def host_to_url(str)
     return if str.blank?
 
-    str.start_with?(/https?:\/\//) ? str : "http://#{str}"
+    str.start_with?(%r{https?://}) ? str : "http://#{str}"
   end
 
   def valid_url_or_nil(str, same_origin_only: false)
diff --git a/app/lib/plain_text_formatter.rb b/app/lib/plain_text_formatter.rb
index 61216601807ff1ae520f33cf5e0af044b728f53a..8eac730bec402427b22f9e2c0acfbdcf35e98cc3 100644
--- a/app/lib/plain_text_formatter.rb
+++ b/app/lib/plain_text_formatter.rb
@@ -3,7 +3,7 @@
 class PlainTextFormatter
   include ActionView::Helpers::TextHelper
 
-  NEWLINE_TAGS_RE = /(<br \/>|<br>|<\/p>)+/
+  NEWLINE_TAGS_RE = %r{(<br />|<br>|</p>)+}
 
   attr_reader :text, :local
 
diff --git a/app/lib/tag_manager.rb b/app/lib/tag_manager.rb
index 7fbf4437da3479258d232ee9a0ec3bfe7a926db3..ea096855f0473478641cceaea6fa2204ef07430c 100644
--- a/app/lib/tag_manager.rb
+++ b/app/lib/tag_manager.rb
@@ -7,18 +7,18 @@ class TagManager
   include RoutingHelper
 
   def web_domain?(domain)
-    domain.nil? || domain.gsub(/[\/]/, '').casecmp(Rails.configuration.x.web_domain).zero?
+    domain.nil? || domain.delete('/').casecmp(Rails.configuration.x.web_domain).zero?
   end
 
   def local_domain?(domain)
-    domain.nil? || domain.gsub(/[\/]/, '').casecmp(Rails.configuration.x.local_domain).zero?
+    domain.nil? || domain.delete('/').casecmp(Rails.configuration.x.local_domain).zero?
   end
 
   def normalize_domain(domain)
     return if domain.nil?
 
     uri = Addressable::URI.new
-    uri.host = domain.gsub(/[\/]/, '')
+    uri.host = domain.delete('/')
     uri.normalized_host
   end
 
diff --git a/app/lib/text_formatter.rb b/app/lib/text_formatter.rb
index b7bc8320aea95424b5768dbc6a0618f233651ba2..243e89289125debd317cc14190f7de4200efa86d 100644
--- a/app/lib/text_formatter.rb
+++ b/app/lib/text_formatter.rb
@@ -5,7 +5,7 @@ class TextFormatter
   include ERB::Util
   include RoutingHelper
 
-  URL_PREFIX_REGEX = /\A(https?:\/\/(www\.)?|xmpp:)/
+  URL_PREFIX_REGEX = %r{\A(https?://(www\.)?|xmpp:)}
 
   DEFAULT_REL = %w(nofollow noopener noreferrer).freeze
 
diff --git a/app/lib/webfinger_resource.rb b/app/lib/webfinger_resource.rb
index 7e1a7196d7a51077171959ec1d8ff9e3deebe089..e28723ff825aab05c31dbebc740c9dc57493ccc4 100644
--- a/app/lib/webfinger_resource.rb
+++ b/app/lib/webfinger_resource.rb
@@ -13,7 +13,7 @@ class WebfingerResource
     case resource
     when /\Ahttps?/i
       username_from_url
-    when /\@/
+    when /@/
       username_from_acct
     else
       raise InvalidRequest
diff --git a/app/models/account.rb b/app/models/account.rb
index 062beb98daff0789251e07427b6f4ef0acc1a563..1d24a7ec81207f614788022fc9c4d8432384d794 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -62,9 +62,9 @@ class Account < ApplicationRecord
     trust_level
   )
 
-  USERNAME_RE   = /[a-z0-9_]+([a-z0-9_\.-]+[a-z0-9_]+)?/i
-  MENTION_RE    = /(?<=^|[^\/[:word:]])@((#{USERNAME_RE})(?:@[[:word:]\.\-]+[[:word:]]+)?)/i
-  URL_PREFIX_RE = /\Ahttp(s?):\/\/[^\/]+/
+  USERNAME_RE   = /[a-z0-9_]+([a-z0-9_.-]+[a-z0-9_]+)?/i
+  MENTION_RE    = %r{(?<=^|[^/[:word:]])@((#{USERNAME_RE})(?:@[[:word:].-]+[[:word:]]+)?)}i
+  URL_PREFIX_RE = %r{\Ahttp(s?)://[^/]+}
   USERNAME_ONLY_RE = /\A#{USERNAME_RE}\z/i
 
   include Attachmentable
diff --git a/app/models/domain_allow.rb b/app/models/domain_allow.rb
index 9e746b91575eb97eb25b8aee4b8e87005604e566..ce9597b4d1561a4c1262d698d75f8aff328a579a 100644
--- a/app/models/domain_allow.rb
+++ b/app/models/domain_allow.rb
@@ -35,7 +35,7 @@ class DomainAllow < ApplicationRecord
     def rule_for(domain)
       return if domain.blank?
 
-      uri = Addressable::URI.new.tap { |u| u.host = domain.gsub(/[\/]/, '') }
+      uri = Addressable::URI.new.tap { |u| u.host = domain.delete('/') }
 
       find_by(domain: uri.normalized_host)
     end
diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb
index 06d35d8beef59d966679db8a2fd3f90d2e80e1e5..108dfe3d4580660860550441ee5decb6e39104c3 100644
--- a/app/models/domain_block.rb
+++ b/app/models/domain_block.rb
@@ -67,7 +67,7 @@ class DomainBlock < ApplicationRecord
     def rule_for(domain)
       return if domain.blank?
 
-      uri      = Addressable::URI.new.tap { |u| u.host = domain.strip.gsub(/[\/]/, '') }
+      uri      = Addressable::URI.new.tap { |u| u.host = domain.strip.delete('/') }
       segments = uri.normalized_host.split('.')
       variants = segments.map.with_index { |_, i| segments[i..-1].join('.') }
 
diff --git a/app/models/site_upload.rb b/app/models/site_upload.rb
index e17668110c27fb712bfad5c303ac0d0d2512f632..2335ffac536e5d6770462b67c04d8276785cce02 100644
--- a/app/models/site_upload.rb
+++ b/app/models/site_upload.rb
@@ -43,7 +43,7 @@ class SiteUpload < ApplicationRecord
 
   has_attached_file :file, styles: ->(file) { STYLES[file.instance.var.to_sym] }, convert_options: { all: '-coalesce +profile "!icc,*" +set modify-date +set create-date' }, processors: [:lazy_thumbnail, :blurhash_transcoder, :type_corrector]
 
-  validates_attachment_content_type :file, content_type: /\Aimage\/.*\z/
+  validates_attachment_content_type :file, content_type: %r{\Aimage/.*\z}
   validates :file, presence: true
   validates :var, presence: true, uniqueness: true
 
diff --git a/app/models/tag.rb b/app/models/tag.rb
index 9fb32cd06e69317f0f9446f7713322207052a056..7668f16ceed85c2a536823e9aeaecc3539dc2bd3 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -34,7 +34,7 @@ class Tag < ApplicationRecord
   HASHTAG_LAST_SEQUENCE = '([[:word:]_]*[[:alpha:]][[:word:]_]*)'
   HASHTAG_NAME_PAT = "#{HASHTAG_FIRST_SEQUENCE}|#{HASHTAG_LAST_SEQUENCE}"
 
-  HASHTAG_RE = /(?:^|[^\/\)\w])#(#{HASHTAG_NAME_PAT})/i
+  HASHTAG_RE = %r{(?:^|[^/)\w])#(#{HASHTAG_NAME_PAT})}i
   HASHTAG_NAME_RE = /\A(#{HASHTAG_NAME_PAT})\z/i
   HASHTAG_INVALID_CHARS_RE = /[^[:alnum:]#{HASHTAG_SEPARATORS}]/
 
diff --git a/app/services/backup_service.rb b/app/services/backup_service.rb
index 4cad11fde9321be601d15564aa2f3571e64f3ec1..3ef0366c3c5fc91f0233bbf180d39dde30afbd09 100644
--- a/app/services/backup_service.rb
+++ b/app/services/backup_service.rb
@@ -77,8 +77,8 @@ class BackupService < BaseService
         path = m.file&.path
         next unless path
 
-        path = path.gsub(/\A.*\/system\//, '')
-        path = path.gsub(/\A\/+/, '')
+        path = path.gsub(%r{\A.*/system/}, '')
+        path = path.gsub(%r{\A/+}, '')
         download_to_zip(zipfile, m.file, path)
       end
 
diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb
index 9c56c862ecebf9aee26546401fb5be78d0699dfd..dccd86c1e689e5437e8403f257dfcb306a436fe2 100644
--- a/app/services/fetch_link_card_service.rb
+++ b/app/services/fetch_link_card_service.rb
@@ -7,7 +7,7 @@ class FetchLinkCardService < BaseService
   URL_PATTERN = %r{
     (#{Twitter::TwitterText::Regex[:valid_url_preceding_chars]})                                                                #   $1 preceding chars
     (                                                                                                                           #   $2 URL
-      (https?:\/\/)                                                                                                             #   $3 Protocol (required)
+      (https?://)                                                                                                               #   $3 Protocol (required)
       (#{Twitter::TwitterText::Regex[:valid_domain]})                                                                           #   $4 Domain(s)
       (?::(#{Twitter::TwitterText::Regex[:valid_port_number]}))?                                                                #   $5 Port number (optional)
       (/#{Twitter::TwitterText::Regex[:valid_url_path]}*)?                                                                      #   $6 URL Path and anchor
diff --git a/app/services/fetch_oembed_service.rb b/app/services/fetch_oembed_service.rb
index f922df64c49ab938869f7664033ce2d84cab03e2..1ae592238efc158d13b6b1f28c302fa64e75158d 100644
--- a/app/services/fetch_oembed_service.rb
+++ b/app/services/fetch_oembed_service.rb
@@ -2,7 +2,7 @@
 
 class FetchOEmbedService
   ENDPOINT_CACHE_EXPIRES_IN = 24.hours.freeze
-  URL_REGEX                 = /(=(http[s]?(%3A|:)(\/\/|%2F%2F)))([^&]*)/i
+  URL_REGEX                 = %r{(=(https?(%3A|:)(//|%2F%2F)))([^&]*)}i
 
   attr_reader :url, :options, :format, :endpoint_url
 
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index b1ce5453fbb77c7c223c886df45f5fda5b1b681d..f475f815366fdaf0ccc44c9dead3ae0f672d5bef 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -70,7 +70,7 @@ class SearchService < BaseService
   end
 
   def url_query?
-    @resolve && /\Ahttps?:\/\//.match?(@query)
+    @resolve && %r{\Ahttps?://}.match?(@query)
   end
 
   def url_resource_results
diff --git a/config/initializers/rack_attack.rb b/config/initializers/rack_attack.rb
index 5cc4e9380af24b91bfe7158d6824734b7e741e96..da0b04af115203ecb860d1dcac905c36fd811ebd 100644
--- a/config/initializers/rack_attack.rb
+++ b/config/initializers/rack_attack.rb
@@ -79,7 +79,7 @@ class Rack::Attack
   end
 
   throttle('throttle_api_media', limit: 30, period: 30.minutes) do |req|
-    req.authenticated_user_id if req.post? && req.path.match?(/\A\/api\/v\d+\/media\z/i)
+    req.authenticated_user_id if req.post? && req.path.match?(%r{\A/api/v\d+/media\z}i)
   end
 
   throttle('throttle_media_proxy', limit: 30, period: 10.minutes) do |req|
@@ -98,8 +98,8 @@ class Rack::Attack
     req.throttleable_remote_ip if req.paging_request? && req.unauthenticated?
   end
 
-  API_DELETE_REBLOG_REGEX = /\A\/api\/v1\/statuses\/[\d]+\/unreblog\z/
-  API_DELETE_STATUS_REGEX = /\A\/api\/v1\/statuses\/[\d]+\z/
+  API_DELETE_REBLOG_REGEX = %r{\A/api/v1/statuses/\d+/unreblog\z}
+  API_DELETE_STATUS_REGEX = %r{\A/api/v1/statuses/\d+\z}
 
   throttle('throttle_api_delete', limit: 30, period: 30.minutes) do |req|
     req.authenticated_user_id if (req.post? && req.path.match?(API_DELETE_REBLOG_REGEX)) || (req.delete? && req.path.match?(API_DELETE_STATUS_REGEX))
diff --git a/config/initializers/twitter_regex.rb b/config/initializers/twitter_regex.rb
index e65b05dfdea083437b88fc6a2765eedd27ed1e60..2e80cabcdb0359185e2b3fb2ef5f435f7efd946a 100644
--- a/config/initializers/twitter_regex.rb
+++ b/config/initializers/twitter_regex.rb
@@ -6,8 +6,8 @@ module Twitter::TwitterText
   end
 
   class Regex
-    REGEXEN[:valid_general_url_path_chars] = /[^\p{White_Space}<>\(\)\?]/iou
-    REGEXEN[:valid_url_path_ending_chars] = /[^\p{White_Space}\(\)\?!\*"'「」<>;:=\,\.\$%\[\]~&\|@]|(?:#{REGEXEN[:valid_url_balanced_parens]})/iou
+    REGEXEN[:valid_general_url_path_chars] = /[^\p{White_Space}<>()?]/iou
+    REGEXEN[:valid_url_path_ending_chars] = /[^\p{White_Space}()?!*"'「」<>;:=,.$%\[\]~&|@]|(?:#{REGEXEN[:valid_url_balanced_parens]})/iou
     REGEXEN[:valid_url_balanced_parens] = /
       \(
         (?:
@@ -25,20 +25,20 @@ module Twitter::TwitterText
       \)
     /iox
     UCHARS = '\u{A0}-\u{D7FF}\u{F900}-\u{FDCF}\u{FDF0}-\u{FFEF}\u{10000}-\u{1FFFD}\u{20000}-\u{2FFFD}\u{30000}-\u{3FFFD}\u{40000}-\u{4FFFD}\u{50000}-\u{5FFFD}\u{60000}-\u{6FFFD}\u{70000}-\u{7FFFD}\u{80000}-\u{8FFFD}\u{90000}-\u{9FFFD}\u{A0000}-\u{AFFFD}\u{B0000}-\u{BFFFD}\u{C0000}-\u{CFFFD}\u{D0000}-\u{DFFFD}\u{E1000}-\u{EFFFD}\u{E000}-\u{F8FF}\u{F0000}-\u{FFFFD}\u{100000}-\u{10FFFD}'
-    REGEXEN[:valid_url_query_chars] = /[a-z0-9!?\*'\(\);:&=\+\$\/%#\[\]\-_\.,~|@\^#{UCHARS}]/iou
-    REGEXEN[:valid_url_query_ending_chars] = /[a-z0-9_&=#\/\-#{UCHARS}]/iou
-    REGEXEN[:valid_url_path] = /(?:
+    REGEXEN[:valid_url_query_chars] = %r{[a-z0-9!?*'();:&=+$/%#\[\]\-_.,~|@\^#{UCHARS}]}iou
+    REGEXEN[:valid_url_query_ending_chars] = %r{[a-z0-9_&=#/\-#{UCHARS}]}iou
+    REGEXEN[:valid_url_path] = %r{(?:
       (?:
         #{REGEXEN[:valid_general_url_path_chars]}*
         (?:#{REGEXEN[:valid_url_balanced_parens]} #{REGEXEN[:valid_general_url_path_chars]}*)*
         #{REGEXEN[:valid_url_path_ending_chars]}
-      )|(?:#{REGEXEN[:valid_general_url_path_chars]}+\/)
-    )/iox
+      )|(?:#{REGEXEN[:valid_general_url_path_chars]}+/)
+    )}iox
     REGEXEN[:valid_url] = %r{
       (                                                                                     #   $1 total match
         (#{REGEXEN[:valid_url_preceding_chars]})                                            #   $2 Preceding character
         (                                                                                   #   $3 URL
-          ((?:https?|dat|dweb|ipfs|ipns|ssb|gopher|gemini):\/\/)?                           #   $4 Protocol (optional)
+          ((?:https?|dat|dweb|ipfs|ipns|ssb|gopher|gemini)://)?                             #   $4 Protocol (optional)
           (#{REGEXEN[:valid_domain]})                                                       #   $5 Domain(s)
           (?::(#{REGEXEN[:valid_port_number]}))?                                            #   $6 Port number (optional)
           (/#{REGEXEN[:valid_url_path]}*)?                                                  #   $7 URL Path and anchor
diff --git a/config/routes.rb b/config/routes.rb
index 45b3d90e0b3379ebe1fa212c3651db8d5333da12..55e5cf36a0651ebbdee79fb5882cebb49dc66d6e 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -115,21 +115,21 @@ Rails.application.routes.draw do
 
   get '/:encoded_at(*path)', to: redirect("/@%{path}"), constraints: { encoded_at: /%40/ }
 
-  constraints(username: /[^@\/.]+/) do
+  constraints(username: %r{[^@/.]+}) do
     get '/@:username', to: 'accounts#show', as: :short_account
     get '/@:username/with_replies', to: 'accounts#show', as: :short_account_with_replies
     get '/@:username/media', to: 'accounts#show', as: :short_account_media
     get '/@:username/tagged/:tag', to: 'accounts#show', as: :short_account_tag
   end
 
-  constraints(account_username: /[^@\/.]+/) do
+  constraints(account_username: %r{[^@/.]+}) do
     get '/@:account_username/following', to: 'following_accounts#index'
     get '/@:account_username/followers', to: 'follower_accounts#index'
     get '/@:account_username/:id', to: 'statuses#show', as: :short_account_status
     get '/@:account_username/:id/embed', to: 'statuses#embed', as: :embed_short_account_status
   end
 
-  get '/@:username_with_domain/(*any)', to: 'home#index', constraints: { username_with_domain: /([^\/])+?/ }, format: false
+  get '/@:username_with_domain/(*any)', to: 'home#index', constraints: { username_with_domain: %r{([^/])+?} }, format: false
   get '/settings', to: redirect('/settings/profile')
 
   draw(:settings)
diff --git a/lib/mastodon/premailer_webpack_strategy.rb b/lib/mastodon/premailer_webpack_strategy.rb
index 5c297d4d05e73c81ab7c8bdfbf2715db59afab67..45e87603f01d99a29adb2ff0d4a7a526b14431fa 100644
--- a/lib/mastodon/premailer_webpack_strategy.rb
+++ b/lib/mastodon/premailer_webpack_strategy.rb
@@ -16,7 +16,7 @@ module PremailerWebpackStrategy
             Rails.public_path.join(url).read
           end
 
-    css.gsub(/url\(\//, "url(#{asset_host}/")
+    css.gsub(%r{url\(/}, "url(#{asset_host}/")
   end
 
   module_function :load
diff --git a/lib/paperclip/color_extractor.rb b/lib/paperclip/color_extractor.rb
index 19529fb8a16e94af63b250b4aefa7c04120eb084..d2f7e7c6025bc8fe8f4428003c020c0cfc35e0fd 100644
--- a/lib/paperclip/color_extractor.rb
+++ b/lib/paperclip/color_extractor.rb
@@ -171,7 +171,7 @@ module Paperclip
     end
 
     def palette_from_histogram(result, quantity)
-      frequencies       = result.scan(/([0-9]+)\:/).flatten.map(&:to_f)
+      frequencies       = result.scan(/([0-9]+):/).flatten.map(&:to_f)
       hex_values        = result.scan(/\#([0-9A-Fa-f]{6,8})/).flatten
       total_frequencies = frequencies.sum.to_f
 
diff --git a/lib/tasks/emojis.rake b/lib/tasks/emojis.rake
index fbb2e8d4f3b95fea3accb7f3847202af4b1811ba..c24ea42e7d28d961c501a427efe82692d1e39cb9 100644
--- a/lib/tasks/emojis.rake
+++ b/lib/tasks/emojis.rake
@@ -31,7 +31,7 @@ def gen_border(codepoint, color)
 end
 
 def codepoints_to_filename(codepoints)
-  codepoints.downcase.gsub(/\A[0]+/, '').tr(' ', '-')
+  codepoints.downcase.gsub(/\A0+/, '').tr(' ', '-')
 end
 
 def codepoints_to_unicode(codepoints)
diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake
index 6c0e6692275b436acd86d7d94027c2454c5939a8..19a369079ef004b5bd1603f2cd3b8721e92ba193 100644
--- a/lib/tasks/mastodon.rake
+++ b/lib/tasks/mastodon.rake
@@ -21,7 +21,7 @@ namespace :mastodon do
       env['LOCAL_DOMAIN'] = prompt.ask('Domain name:') do |q|
         q.required true
         q.modify :strip
-        q.validate(/\A[a-z0-9\.\-]+\z/i)
+        q.validate(/\A[a-z0-9.-]+\z/i)
         q.messages[:valid?] = 'Invalid domain. If you intend to use unicode characters, enter punycode here'
       end
 
@@ -240,7 +240,7 @@ namespace :mastodon do
           end
 
           env['S3_PROTOCOL'] = env['S3_ENDPOINT'].start_with?('https') ? 'https' : 'http'
-          env['S3_HOSTNAME'] = env['S3_ENDPOINT'].gsub(/\Ahttps?:\/\//, '')
+          env['S3_HOSTNAME'] = env['S3_ENDPOINT'].gsub(%r{\Ahttps?://}, '')
 
           env['S3_BUCKET'] = prompt.ask('Minio bucket name:') do |q|
             q.required true
@@ -269,7 +269,7 @@ namespace :mastodon do
           end
 
           env['S3_PROTOCOL'] = env['S3_ENDPOINT'].start_with?('https') ? 'https' : 'http'
-          env['S3_HOSTNAME'] = env['S3_ENDPOINT'].gsub(/\Ahttps?:\/\//, '')
+          env['S3_HOSTNAME'] = env['S3_ENDPOINT'].gsub(%r{\Ahttps?://}, '')
 
           env['S3_BUCKET'] = prompt.ask('Storj DCS bucket name:') do |q|
             q.required true
@@ -573,7 +573,7 @@ def dotenv_escape(value)
 
   # As long as the value doesn't include single quotes, we can safely
   # rely on single quotes
-  return "'#{value}'" unless /[']/.match?(value)
+  return "'#{value}'" unless value.include?("'")
 
   # If the value contains the string '\n' or '\r' we simply can't use
   # a double-quoted string, because Dotenv will expand \n or \r no