Возможно, она была раньше, но потом стала ненужной, и ее убрали.
+
+ Вряд ли она была переименована или объединена с другой страницей, хотя этого исключать нельзя.
+ В таком случае, перейдите на главную страницу и воспользуйтесь навигацией.
+
+
<%= link_to "Перейти на главную страницу", root_path %>
diff --git a/app/views/pages/404.html.haml b/app/views/pages/404.html.haml
deleted file mode 100644
index a0ce2c8d..00000000
--- a/app/views/pages/404.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-%h1 Страница не найдена
-%P Возможно, она была раньше, но потом стала не нужной и ее убрали.
-%p Вряд ли она была переименована или объединена с другой страницей, хотя этого исключать нельзя. В таком случае, перейдите на главную страницу и воспользуйтесь навигацией
-%p= link_to "Перейти на главную страницу.", root_path
-
\ No newline at end of file
diff --git a/app/views/pages/_menu.html.erb b/app/views/pages/_menu.html.erb
new file mode 100644
index 00000000..1e75c33d
--- /dev/null
+++ b/app/views/pages/_menu.html.erb
@@ -0,0 +1,11 @@
+
+<% end %>
+<% cache ['v2', @page] do %>
+ <%= @page.rendered_body(self) %>
+<% end %>
+<% content_for :menu do %>
+ <% cache ['v2', @page, 'menu'] do %>
+ <%= @page.meta[:menu] %>
+ <% end %>
+<% end %>
\ No newline at end of file
diff --git a/app/views/static_docs/pages/show.html.haml b/app/views/static_docs/pages/show.html.haml
deleted file mode 100644
index af7600a5..00000000
--- a/app/views/static_docs/pages/show.html.haml
+++ /dev/null
@@ -1,10 +0,0 @@
-- if @page && @page.path == 'index'
- #main_page_banner.well
- = render "shared/rsya", limit: 2
-
-- cache ['v1', @page] do
- = @page.rendered_body(self)
-
-- content_for :menu do
- - cache ['v1', @page, 'menu'] do
- = @page.meta[:menu]
diff --git a/bin/bundle b/bin/bundle
new file mode 100755
index 00000000..f19acf5b
--- /dev/null
+++ b/bin/bundle
@@ -0,0 +1,3 @@
+#!/usr/bin/env ruby
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
+load Gem.bin_path('bundler', 'bundle')
diff --git a/bin/rails b/bin/rails
new file mode 100755
index 00000000..efc03774
--- /dev/null
+++ b/bin/rails
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby
+APP_PATH = File.expand_path("../config/application", __dir__)
+require_relative "../config/boot"
+require "rails/commands"
diff --git a/bin/rake b/bin/rake
new file mode 100755
index 00000000..4fbf10b9
--- /dev/null
+++ b/bin/rake
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby
+require_relative "../config/boot"
+require "rake"
+Rake.application.run
diff --git a/bin/setup b/bin/setup
new file mode 100755
index 00000000..ec47b79b
--- /dev/null
+++ b/bin/setup
@@ -0,0 +1,33 @@
+#!/usr/bin/env ruby
+require "fileutils"
+
+# path to your application root.
+APP_ROOT = File.expand_path("..", __dir__)
+
+def system!(*args)
+ system(*args) || abort("\n== Command #{args} failed ==")
+end
+
+FileUtils.chdir APP_ROOT do
+ # This script is a way to set up or update your development environment automatically.
+ # This script is idempotent, so that you can run it at any time and get an expectable outcome.
+ # Add necessary setup steps to this file.
+
+ puts "== Installing dependencies =="
+ system! "gem install bundler --conservative"
+ system("bundle check") || system!("bundle install")
+
+ # puts "\n== Copying sample files =="
+ # unless File.exist?("config/database.yml")
+ # FileUtils.cp "config/database.yml.sample", "config/database.yml"
+ # end
+
+ puts "\n== Preparing database =="
+ system! "bin/rails db:prepare"
+
+ puts "\n== Removing old logs and tempfiles =="
+ system! "bin/rails log:clear tmp:clear"
+
+ puts "\n== Restarting application server =="
+ system! "bin/rails restart"
+end
diff --git a/bin/update b/bin/update
new file mode 100755
index 00000000..58bfaed5
--- /dev/null
+++ b/bin/update
@@ -0,0 +1,31 @@
+#!/usr/bin/env ruby
+require 'fileutils'
+include FileUtils
+
+# path to your application root.
+APP_ROOT = File.expand_path('..', __dir__)
+
+def system!(*args)
+ system(*args) || abort("\n== Command #{args} failed ==")
+end
+
+chdir APP_ROOT do
+ # This script is a way to update your development environment automatically.
+ # Add necessary update steps to this file.
+
+ puts '== Installing dependencies =='
+ system! 'gem install bundler --conservative'
+ system('bundle check') || system!('bundle install')
+
+ # Install JavaScript dependencies if using Yarn
+ # system('bin/yarn')
+
+ puts "\n== Updating database =="
+ system! 'bin/rails db:migrate'
+
+ puts "\n== Removing old logs and tempfiles =="
+ system! 'bin/rails log:clear tmp:clear'
+
+ puts "\n== Restarting application server =="
+ system! 'bin/rails restart'
+end
diff --git a/bin/yarn b/bin/yarn
new file mode 100755
index 00000000..9fab2c35
--- /dev/null
+++ b/bin/yarn
@@ -0,0 +1,17 @@
+#!/usr/bin/env ruby
+APP_ROOT = File.expand_path('..', __dir__)
+Dir.chdir(APP_ROOT) do
+ yarn = ENV["PATH"].split(File::PATH_SEPARATOR).
+ select { |dir| File.expand_path(dir) != __dir__ }.
+ product(["yarn", "yarn.cmd", "yarn.ps1"]).
+ map { |dir, file| File.expand_path(file, dir) }.
+ find { |file| File.executable?(file) }
+
+ if yarn
+ exec yarn, *ARGV
+ else
+ $stderr.puts "Yarn executable was not detected in the system."
+ $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
+ exit 1
+ end
+end
diff --git a/config.ru b/config.ru
index aa881ea0..4a3c09a6 100644
--- a/config.ru
+++ b/config.ru
@@ -1,4 +1,6 @@
# This file is used by Rack-based servers to start the application.
-require ::File.expand_path('../config/environment', __FILE__)
-run Rusrails::Application
+require_relative "config/environment"
+
+run Rails.application
+Rails.application.load_server
diff --git a/config/application.rb b/config/application.rb
index 061e82a2..0ae41637 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -1,50 +1,24 @@
-require File.expand_path('../boot', __FILE__)
+require_relative "boot"
-require 'rails/all'
+require "rails/all"
-if defined?(Bundler)
- # If you precompile assets before deploying to production, use this line
- Bundler.require(:default, Rails.env)
-
- # If you want your assets lazily compiled in production, use this line
- # Bundler.require(:default, :assets, Rails.env)
-end
+# Require the gems listed in Gemfile, including any gems
+# you've limited to :test, :development, or :production.
+Bundler.require(*Rails.groups)
module Rusrails
class Application < Rails::Application
- # Settings in config/environments/* take precedence over those specified here.
- # Application configuration should go into files in config/initializers
- # -- all .rb files in that directory are automatically loaded.
-
- # Custom directories with classes and modules you want to be autoloadable.
- # config.autoload_paths += %W(#{config.root}/extras)
-
- # Only load the plugins named here, in the order given (default is alphabetical).
- # :all can be used as a placeholder for all plugins not explicitly named.
- # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
-
- # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
- # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
- config.time_zone = 'Moscow'
+ # Initialize configuration defaults for originally generated Rails version.
+ config.load_defaults 7.0
- config.i18n.enforce_available_locales = true
+ # Configuration for the application, engines, and railties goes here.
+ #
+ # These settings can be overridden in specific environments using the files
+ # in config/environments, which are processed later.
+ #
+ # config.time_zone = "Central Time (US & Canada)"
+ # config.eager_load_paths << Rails.root.join("extras")
- # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
- # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
config.i18n.default_locale = :ru
-
- # Configure the default encoding used in templates for Ruby 1.9.
- config.encoding = "utf-8"
-
- # Configure sensitive parameters which will be filtered from the log file.
- config.filter_parameters += [:password]
-
- # Enable the asset pipeline
- config.assets.enabled = true
-
- # Version of your assets, change this if you want to expire all your assets
- config.assets.version = '1.0'
-
- config.assets.precompile += ['sh/*.js']
end
end
diff --git a/config/boot.rb b/config/boot.rb
index 4489e586..988a5ddc 100644
--- a/config/boot.rb
+++ b/config/boot.rb
@@ -1,6 +1,4 @@
-require 'rubygems'
+ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
-# Set up gems listed in the Gemfile.
-ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
-
-require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
+require "bundler/setup" # Set up gems listed in the Gemfile.
+require "bootsnap/setup" # Speed up boot time by caching expensive operations.
diff --git a/config/cable.yml b/config/cable.yml
new file mode 100644
index 00000000..755f2c20
--- /dev/null
+++ b/config/cable.yml
@@ -0,0 +1,10 @@
+development:
+ adapter: async
+
+test:
+ adapter: test
+
+production:
+ adapter: redis
+ url: <%= ENV.fetch("http://github.com/REDIS_URL") { "redis://localhost:6379/1" } %>
+ channel_prefix: rusrails_production
diff --git a/config/deploy.rb b/config/deploy.rb
deleted file mode 100644
index 77409166..00000000
--- a/config/deploy.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-require "bundler/capistrano"
-require 'static_docs/capistrano'
-
-require 'capistrano/ext/multistage'
-set :stages, %w(v32 v40)
-set :default_stage, "v40"
-
-load "config/recipes/base"
-load "config/recipes/nginx"
-load "config/recipes/unicorn"
-load "config/recipes/monit"
-
-server "78.47.229.178", :web, :app, :db, primary: true
-
-set :user, 'admin'
-set(:deploy_to){ "/home/#{user}/apps/#{application}" }
-set :deploy_via, :remote_cache
-set :use_sudo, false
-
-set :scm, :git
-set :repository, "git@github.com:morsbox/rusrails.git"
-
-set :bundle_cmd, '/home/admin/.rbenv/shims/bundle'
-
-default_run_options[:pty] = true
-ssh_options[:forward_agent] = true
-
-namespace :deploy do
- desc "Seed the database with the required data"
- task :seed do
- rake = fetch(:rake, "rake")
- rails_env = fetch(:rails_env, "production")
-
- run "cd #{current_path}; #{rake} RAILS_ENV=#{rails_env} db:seed"
- end
-
- after "deploy:seed", "static_docs:import"
-end
-
-after "deploy", "deploy:cleanup"
diff --git a/config/deploy/v32.rb b/config/deploy/v32.rb
deleted file mode 100644
index 66cd1b28..00000000
--- a/config/deploy/v32.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-require 'thinking_sphinx/capistrano'
-
-set :application, "rusrails_v32"
-set :branch, "v3.2"
-
-set :subdomains, %w(v32.rusrails.ru)
-
-set :unicorn_workers, 1
-
-after "deploy:seed", "thinking_sphinx:rebuild"
diff --git a/config/deploy/v40.rb b/config/deploy/v40.rb
deleted file mode 100644
index 40811076..00000000
--- a/config/deploy/v40.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-load "config/recipes/postgresql"
-
-set :application, "rusrails_v40"
-
-set :branch, "master"
-
-set :subdomains, %w(rusrails.ru www.rusrails.ru edge.rusrails.ru v40.rusrails.ru archive.rusrails.ru)
diff --git a/config/environment.rb b/config/environment.rb
index 044229b5..cac53157 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -1,5 +1,5 @@
-# Load the rails application
-require File.expand_path('../application', __FILE__)
+# Load the Rails application.
+require_relative "application"
-# Initialize the rails application
-Rusrails::Application.initialize!
+# Initialize the Rails application.
+Rails.application.initialize!
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 3e617ee0..8500f459 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -1,32 +1,70 @@
-Rusrails::Application.configure do
- # Settings specified here will take precedence over those in config/application.rb
+require "active_support/core_ext/integer/time"
- # In the development environment your application's code is reloaded on
- # every request. This slows down response time but is perfect for development
- # since you don't have to restart the webserver when you make code changes.
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # In the development environment your application's code is reloaded any time
+ # it changes. This slows down response time but is perfect for development
+ # since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Do not eager load code on boot.
config.eager_load = false
- # Show full error reports and disable caching
- config.consider_all_requests_local = true
- config.action_controller.perform_caching = false
+ # Show full error reports.
+ config.consider_all_requests_local = true
+
+ # Enable server timing
+ config.server_timing = true
+
+ # Enable/disable caching. By default caching is disabled.
+ # Run rails dev:cache to toggle caching.
+ if Rails.root.join("tmp/caching-dev.txt").exist?
+ config.action_controller.perform_caching = true
+ config.action_controller.enable_fragment_cache_logging = true
+
+ config.cache_store = :memory_store
+ config.public_file_server.headers = {
+ "Cache-Control" => "public, max-age=#{2.days.to_i}"
+ }
+ else
+ config.action_controller.perform_caching = false
+
+ config.cache_store = :null_store
+ end
+
+ # Store uploaded files on the local file system (see config/storage.yml for options).
+ config.active_storage.service = :local
- # Don't care if the mailer can't send
+ # Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false
- # Print deprecation notices to the Rails logger
+ config.action_mailer.perform_caching = false
+
+ # Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
- # Only use best-standards-support built into browsers
- config.action_dispatch.best_standards_support = :builtin
+ # Raise exceptions for disallowed deprecations.
+ config.active_support.disallowed_deprecation = :raise
+
+ # Tell Active Support which deprecation messages to disallow.
+ config.active_support.disallowed_deprecation_warnings = []
+
+ # Raise an error on page load if there are pending migrations.
+ config.active_record.migration_error = :page_load
+
+ # Highlight code that triggered database queries in logs.
+ config.active_record.verbose_query_logs = true
+
+ # Suppress logger output for asset requests.
+ config.assets.quiet = true
- config.action_mailer.default_url_options = {host: "rusrails.dev"}
+ # Raises error for missing translations.
+ # config.i18n.raise_on_missing_translations = true
- # Do not compress assets
- config.assets.js_compressor = false
+ # Annotate rendered view with file names.
+ # config.action_view.annotate_rendered_view_with_filenames = true
- # Expands the lines which load the assets
- config.assets.debug = true
+ # Uncomment if you wish to allow Action Cable access from any origin.
+ # config.action_cable.disable_request_forgery_protection = true
end
diff --git a/config/environments/production.rb b/config/environments/production.rb
index d443cd9d..14b529f6 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -1,66 +1,93 @@
-Rusrails::Application.configure do
- # Settings specified here will take precedence over those in config/application.rb
+require "active_support/core_ext/integer/time"
- # The production environment is meant for finished, "live" apps.
- # Code is not reloaded between requests
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # Code is not reloaded between requests.
config.cache_classes = true
# Eager load code on boot. This eager loads most of Rails and
- # your application in memory, allowing both thread web servers
+ # your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
config.eager_load = true
-
- # Full error reports are disabled and caching is turned on
+
+ # Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
- # Specifies the header that your server uses for sending files
- config.action_dispatch.x_sendfile_header = "X-Sendfile"
+ # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
+ # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
+ # config.require_master_key = true
+
+ # Disable serving static files from the `/public` folder by default since
+ # Apache or NGINX already handles this.
+ config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?
+
+ # Compress CSS using a preprocessor.
+ # config.assets.css_compressor = :sass
+
+ # Do not fallback to assets pipeline if a precompiled asset is missed.
+ config.assets.compile = false
- # For nginx:
- # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
+ # Enable serving of images, stylesheets, and JavaScripts from an asset server.
+ # config.asset_host = "http://assets.example.com/"
- # If you have no front-end server that supports something like X-Sendfile,
- # just comment this out and Rails will serve the files
+ # Specifies the header that your server uses for sending files.
+ # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache
+ # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX
- # See everything in the log (default is :info)
- # config.log_level = :debug
+ # Store uploaded files on the local file system (see config/storage.yml for options).
+ config.active_storage.service = :local
- # Use a different logger for distributed setups
- # config.logger = SyslogLogger.new
+ # Mount Action Cable outside main process or domain.
+ # config.action_cable.mount_path = nil
+ # config.action_cable.url = "wss://example.com/cable"
+ # config.action_cable.allowed_request_origins = [ "http://example.com/", /http:\/\/example.*/ ]
- # Use a different cache store in production
+ # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+ # config.force_ssl = true
+
+ # Include generic and useful information about system operation, but avoid logging too much
+ # information to avoid inadvertent exposure of personally identifiable information (PII).
+ config.log_level = :info
+
+ # Prepend all log lines with the following tags.
+ config.log_tags = [ :request_id ]
+
+ # Use a different cache store in production.
# config.cache_store = :mem_cache_store
- # Disable Rails's static asset server
- # In production, Apache or nginx will already do this
- config.serve_static_assets = false
+ # Use a real queuing backend for Active Job (and separate queues per environment).
+ # config.active_job.queue_adapter = :resque
+ # config.active_job.queue_name_prefix = "rusrails_production"
- # Enable serving of images, stylesheets, and javascripts from an asset server
- # config.action_controller.asset_host = "http://assets.example.com/"
+ config.action_mailer.perform_caching = false
- # Disable delivery errors, bad email addresses will be ignored
+ # Ignore bad email addresses and do not raise email delivery errors.
+ # Set this to true and configure the email server for immediate delivery to raise delivery errors.
# config.action_mailer.raise_delivery_errors = false
- # Enable threaded mode
- # config.threadsafe!
-
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
- # the I18n.default_locale when a translation can not be found)
+ # the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true
- # Send deprecation notices to registered listeners
- config.active_support.deprecation = :notify
+ # Don't log any deprecations.
+ config.active_support.report_deprecations = false
- config.action_mailer.default_url_options = {host: "rusrails.ru"}
+ # Use default logging formatter so that PID and timestamp are not suppressed.
+ config.log_formatter = ::Logger::Formatter.new
- # Compress JavaScript and CSS
- config.assets.js_compressor = :uglifier
+ # Use a different logger for distributed setups.
+ # require "syslog/logger"
+ # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name")
- # Don't fallback to assets pipeline
- config.assets.compile = false
+ if ENV["RAILS_LOG_TO_STDOUT"].present?
+ logger = ActiveSupport::Logger.new(STDOUT)
+ logger.formatter = config.log_formatter
+ config.logger = ActiveSupport::TaggedLogging.new(logger)
+ end
- # Generate digests for assets URLs
- config.assets.digest = true
+ # Do not dump schema after migrations.
+ config.active_record.dump_schema_after_migration = false
end
diff --git a/config/environments/test.rb b/config/environments/test.rb
index 2cd5f9ef..6ea4d1e7 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -1,44 +1,60 @@
-Rusrails::Application.configure do
- # Settings specified here will take precedence over those in config/application.rb
+require "active_support/core_ext/integer/time"
- # The test environment is used exclusively to run your application's
- # test suite. You never need to work with it otherwise. Remember that
- # your test database is "scratch space" for the test suite and is wiped
- # and recreated between test runs. Don't rely on the data there!
+# The test environment is used exclusively to run your application's
+# test suite. You never need to work with it otherwise. Remember that
+# your test database is "scratch space" for the test suite and is wiped
+# and recreated between test runs. Don't rely on the data there!
+
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # Turn false under Spring and add config.action_view.cache_template_loading = true.
config.cache_classes = true
- # Do not eager load code on boot. This avoids loading your whole application
- # just for the purpose of running a single test. If you are using a tool that
- # preloads Rails for running tests, you may have to set it to true.
- config.eager_load = false
-
- # Show full error reports and disable caching
+ # Eager loading loads your whole application. When running a single test locally,
+ # this probably isn't necessary. It's a good idea to do in a continuous integration
+ # system, or in some way before deploying your code.
+ config.eager_load = ENV["CI"].present?
+
+ # Configure public file server for tests with Cache-Control for performance.
+ config.public_file_server.enabled = true
+ config.public_file_server.headers = {
+ "Cache-Control" => "public, max-age=#{1.hour.to_i}"
+ }
+
+ # Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
+ config.cache_store = :null_store
- # Raise exceptions instead of rendering exception templates
+ # Raise exceptions instead of rendering exception templates.
config.action_dispatch.show_exceptions = false
- # Disable request forgery protection in test environment
- config.action_controller.allow_forgery_protection = false
+ # Disable request forgery protection in test environment.
+ config.action_controller.allow_forgery_protection = false
+
+ # Store uploaded files on the local file system in a temporary directory.
+ config.active_storage.service = :test
+
+ config.action_mailer.perform_caching = false
# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
- # Use SQL instead of Active Record's schema dumper when creating the test database.
- # This is necessary if your schema can't be completely dumped by the schema dumper,
- # like if you have constraints or database-specific column types
- # config.active_record.schema_format = :sql
-
- # Print deprecation notices to the stderr
+ # Print deprecation notices to the stderr.
config.active_support.deprecation = :stderr
- # Configure static asset server for tests with Cache-Control for performance
- config.serve_static_assets = true
- config.static_cache_control = "public, max-age=3600"
+ # Raise exceptions for disallowed deprecations.
+ config.active_support.disallowed_deprecation = :raise
+
+ # Tell Active Support which deprecation messages to disallow.
+ config.active_support.disallowed_deprecation_warnings = []
+
+ # Raises error for missing translations.
+ # config.i18n.raise_on_missing_translations = true
- # Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets
- config.assets.allow_debugging = true
+ # Annotate rendered view with file names.
+ # config.action_view.annotate_rendered_view_with_filenames = true
end
diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb
new file mode 100644
index 00000000..89d2efab
--- /dev/null
+++ b/config/initializers/application_controller_renderer.rb
@@ -0,0 +1,8 @@
+# Be sure to restart your server when you modify this file.
+
+# ActiveSupport::Reloader.to_prepare do
+# ApplicationController.renderer.defaults.merge!(
+# http_host: 'example.org',
+# https: false
+# )
+# end
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
new file mode 100644
index 00000000..2eeef966
--- /dev/null
+++ b/config/initializers/assets.rb
@@ -0,0 +1,12 @@
+# Be sure to restart your server when you modify this file.
+
+# Version of your assets, change this if you want to expire all your assets.
+Rails.application.config.assets.version = "1.0"
+
+# Add additional assets to the asset load path.
+# Rails.application.config.assets.paths << Emoji.images_path
+
+# Precompile additional assets.
+# application.js, application.css, and all non-JS/CSS in the app/assets
+# folder are already added.
+# Rails.application.config.assets.precompile += %w( admin.js admin.css )
diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb
index 59385cdf..33699c30 100644
--- a/config/initializers/backtrace_silencers.rb
+++ b/config/initializers/backtrace_silencers.rb
@@ -1,7 +1,8 @@
# Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
-# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+# Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) }
-# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
-# Rails.backtrace_cleaner.remove_silencers!
+# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code
+# by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'".
+Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"]
diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb
new file mode 100644
index 00000000..54f47cf1
--- /dev/null
+++ b/config/initializers/content_security_policy.rb
@@ -0,0 +1,25 @@
+# Be sure to restart your server when you modify this file.
+
+# Define an application-wide content security policy.
+# See the Securing Rails Applications Guide for more information:
+# https://guides.rubyonrails.org/security.html#content-security-policy-header
+
+# Rails.application.configure do
+# config.content_security_policy do |policy|
+# policy.default_src :self, :https
+# policy.font_src :self, :https, :data
+# policy.img_src :self, :https, :data
+# policy.object_src :none
+# policy.script_src :self, :https
+# policy.style_src :self, :https
+# # Specify URI for violation reports
+# # policy.report_uri "/csp-violation-report-endpoint"
+# end
+#
+# # Generate session nonces for permitted importmap and inline scripts
+# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
+# config.content_security_policy_nonce_directives = %w(script-src)
+#
+# # Report violations without enforcing the policy.
+# # config.content_security_policy_report_only = true
+# end
diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb
new file mode 100644
index 00000000..5a6a32d3
--- /dev/null
+++ b/config/initializers/cookies_serializer.rb
@@ -0,0 +1,5 @@
+# Be sure to restart your server when you modify this file.
+
+# Specify a serializer for the signed and encrypted cookie jars.
+# Valid options are :json, :marshal, and :hybrid.
+Rails.application.config.action_dispatch.cookies_serializer = :json
diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb
new file mode 100644
index 00000000..adc6568c
--- /dev/null
+++ b/config/initializers/filter_parameter_logging.rb
@@ -0,0 +1,8 @@
+# Be sure to restart your server when you modify this file.
+
+# Configure parameters to be filtered from the log file. Use this to limit dissemination of
+# sensitive information. See the ActiveSupport::ParameterFilter documentation for supported
+# notations and behaviors.
+Rails.application.config.filter_parameters += [
+ :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
+]
diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb
index 9e8b0131..3860f659 100644
--- a/config/initializers/inflections.rb
+++ b/config/initializers/inflections.rb
@@ -1,10 +1,16 @@
# Be sure to restart your server when you modify this file.
-# Add new inflection rules using the following format
-# (all these examples are active by default):
-# ActiveSupport::Inflector.inflections do |inflect|
-# inflect.plural /^(ox)$/i, '\1en'
-# inflect.singular /^(ox)en/i, '\1'
-# inflect.irregular 'person', 'people'
+# Add new inflection rules using the following format. Inflections
+# are locale specific, and you may define rules for as many different
+# locales as you wish. All of these examples are active by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.plural /^(ox)$/i, "\\1en"
+# inflect.singular /^(ox)en/i, "\\1"
+# inflect.irregular "person", "people"
# inflect.uncountable %w( fish sheep )
# end
+
+# These inflection rules are supported but not enabled by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.acronym "RESTful"
+# end
diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb
index 72aca7e4..dc189968 100644
--- a/config/initializers/mime_types.rb
+++ b/config/initializers/mime_types.rb
@@ -2,4 +2,3 @@
# Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf
-# Mime::Type.register_alias "text/html", :iphone
diff --git a/config/initializers/permissions_policy.rb b/config/initializers/permissions_policy.rb
new file mode 100644
index 00000000..00f64d71
--- /dev/null
+++ b/config/initializers/permissions_policy.rb
@@ -0,0 +1,11 @@
+# Define an application-wide HTTP permissions policy. For further
+# information see https://developers.google.com/web/updates/2018/06/feature-policy
+#
+# Rails.application.config.permissions_policy do |f|
+# f.camera :none
+# f.gyroscope :none
+# f.microphone :none
+# f.usb :none
+# f.fullscreen :self
+# f.payment :self, "https://secure.example.com/"
+# end
diff --git a/config/initializers/rails_config.rb b/config/initializers/rails_config.rb
deleted file mode 100644
index 5378de94..00000000
--- a/config/initializers/rails_config.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-RailsConfig.setup do |config|
- config.const_name = "Settings"
-end
\ No newline at end of file
diff --git a/config/initializers/redcloth.rb b/config/initializers/redcloth.rb
deleted file mode 100644
index 04e36ab0..00000000
--- a/config/initializers/redcloth.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require "renderers/textile_extension"
-RedCloth.include TextileExtensions
diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb
index 566718ee..bae186dd 100644
--- a/config/initializers/secret_token.rb
+++ b/config/initializers/secret_token.rb
@@ -4,5 +4,4 @@
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
-Rusrails::Application.config.secret_token = Settings.secret_token
Rusrails::Application.config.secret_key_base = Settings.secret_token
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
index f4e4633f..e3c6148a 100644
--- a/config/initializers/session_store.rb
+++ b/config/initializers/session_store.rb
@@ -1,8 +1,3 @@
# Be sure to restart your server when you modify this file.
-Rusrails::Application.config.session_store :cookie_store, key: '_rusrails_session'
-
-# Use the database for sessions instead of the cookie-based default,
-# which shouldn't be used to store highly confidential information
-# (create the session table with "rails generate session_migration")
-# Rusrails::Application.config.session_store :active_record_store
+Rails.application.config.session_store :cookie_store, key: '_rusrails_session'
diff --git a/config/initializers/static_docs.rb b/config/initializers/static_docs.rb
index 6abd9c80..b4d33eac 100644
--- a/config/initializers/static_docs.rb
+++ b/config/initializers/static_docs.rb
@@ -1,20 +1,14 @@
-Page = StaticDocs::Page
+Rails.application.reloader.to_prepare do
+ Page = StaticDocs::Page
+end
StaticDocs.setup do
source 'source'
renderer :md do |body, page|
- engine = Markdown.new.engine
+ engine = Rusrails::Markdown.new.engine
engine.render(body).html_safe.tap do
page.meta[:menu] = render 'pages/menu', markdown_renderer: engine.renderer
end
end
-
- renderer :textile do |page|
- t = RedCloth.new(page)
- t.hard_breaks = false
- t.lite_mode = false
- t.sanitize_html = false
- t.to_html(:notestuff, :plusplus, :code, :rails_mark).html_safe
- end
end
diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb
new file mode 100644
index 00000000..bbfc3961
--- /dev/null
+++ b/config/initializers/wrap_parameters.rb
@@ -0,0 +1,14 @@
+# Be sure to restart your server when you modify this file.
+
+# This file contains settings for ActionController::ParamsWrapper which
+# is enabled by default.
+
+# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
+ActiveSupport.on_load(:action_controller) do
+ wrap_parameters format: [:json]
+end
+
+# To enable root element in JSON for ActiveRecord objects.
+# ActiveSupport.on_load(:active_record) do
+# self.include_root_in_json = true
+# end
diff --git a/config/locales/en.yml b/config/locales/en.yml
index a747bfa6..cf9b342d 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1,5 +1,33 @@
-# Sample localization file for English. Add more files in this directory for other locales.
-# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
+# Files in the config/locales directory are used for internationalization
+# and are automatically loaded by Rails. If you want to use locales other
+# than English, add the necessary files in this directory.
+#
+# To use the locales, use `I18n.t`:
+#
+# I18n.t 'hello'
+#
+# In views, this is aliased to just `t`:
+#
+# <%= t('hello') %>
+#
+# To use a different locale, set it with `I18n.locale`:
+#
+# I18n.locale = :es
+#
+# This would use the information in config/locales/es.yml.
+#
+# The following keys must be escaped otherwise they will not be retrieved by
+# the default I18n backend:
+#
+# true, false, on, off, yes, no
+#
+# Instead, surround them with single quotes.
+#
+# en:
+# 'true': 'foo'
+#
+# To learn more, please read the Rails Internationalization guide
+# available at https://guides.rubyonrails.org/i18n.html.
en:
hello: "Hello world"
diff --git a/config/puma.rb b/config/puma.rb
new file mode 100644
index 00000000..1e19380d
--- /dev/null
+++ b/config/puma.rb
@@ -0,0 +1,56 @@
+# Puma can serve each request in a thread from an internal thread pool.
+# The `threads` method setting takes two numbers: a minimum and maximum.
+# Any libraries that use thread pools should be configured to match
+# the maximum value specified for Puma. Default is set to 5 threads for minimum
+# and maximum; this matches the default thread size of Active Record.
+#
+threads_count = ENV.fetch("http://github.com/RAILS_MAX_THREADS") { 5 }
+threads threads_count, threads_count
+
+# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
+#
+port ENV.fetch("http://github.com/PORT") { 3000 }
+
+# Specifies the `environment` that Puma will run in.
+#
+environment ENV.fetch("http://github.com/RAILS_ENV") { "development" }
+
+# Specifies the number of `workers` to boot in clustered mode.
+# Workers are forked webserver processes. If using threads and workers together
+# the concurrency of the application would be max `threads` * `workers`.
+# Workers do not work on JRuby or Windows (both of which do not support
+# processes).
+#
+# workers ENV.fetch("http://github.com/WEB_CONCURRENCY") { 2 }
+
+# Use the `preload_app!` method when specifying a `workers` number.
+# This directive tells Puma to first boot the application and load code
+# before forking the application. This takes advantage of Copy On Write
+# process behavior so workers use less memory. If you use this option
+# you need to make sure to reconnect any threads in the `on_worker_boot`
+# block.
+#
+# preload_app!
+
+# If you are preloading your application and using Active Record, it's
+# recommended that you close any connections to the database before workers
+# are forked to prevent connection leakage.
+#
+# before_fork do
+# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord)
+# end
+
+# The code in the `on_worker_boot` will be called if you are using
+# clustered mode by specifying a number of `workers`. After each worker
+# process is booted, this block will be run. If you are using the `preload_app!`
+# option, you will want to use this block to reconnect to any threads
+# or connections that may have been created at application boot, as Ruby
+# cannot share connections between processes.
+#
+# on_worker_boot do
+# ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
+# end
+#
+
+# Allow puma to be restarted by `rails restart` command.
+plugin :tmp_restart
diff --git a/config/recipes/base.rb b/config/recipes/base.rb
deleted file mode 100644
index 7265b3cc..00000000
--- a/config/recipes/base.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-def template(from, to)
- erb = File.read(File.expand_path("../templates/#{from}", __FILE__))
- put ERB.new(erb).result(binding), to
-end
-
-def set_default(name, *args, &block)
- set(name, *args, &block) unless exists?(name)
-end
-
-namespace :deploy do
- desc "Install everything onto the server"
- task :install do
- run "echo 'deb http://apt.postgresql.org/pub/repos/apt/ squeeze-pgdg main' | #{sudo} tee /etc/apt/sources.list.d/pgdg.list"
- run "wget --quiet -O - http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | #{sudo} apt-key add -"
- run "#{sudo} apt-get -y update"
- run "#{sudo} apt-get -y install python-software-properties"
- end
-
- desc 'Symlink all configs into current release'
- task :symlink_configs, roles: :app do
- s = "cd #{shared_path}/config && "
- s << "for i in `find . -type f | sed 's/^\\.\\///'` ; do "
- s << "echo \"create current/config/${i}\" ;"
- s << "rm -f #{release_path}/config/${i} ;"
- s << "ln -snf #{shared_path}/config/${i} #{release_path}/config/${i} ; done"
- run s
- end
-
- after "deploy:finalize_update", "deploy:symlink_configs"
-
-end
diff --git a/config/recipes/monit.rb b/config/recipes/monit.rb
deleted file mode 100644
index 195a4b68..00000000
--- a/config/recipes/monit.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-namespace :monit do
- desc "Setup all Monit configuration"
- task :setup do
- monit_config "monitrc", "/etc/monit/monitrc"
- nginx
- application == 'rusrails_v32' ? mysql : postgresql
- unicorn
- syntax
- force_reload
- end
- after "deploy:setup", "monit:setup"
-
- task(:nginx, roles: :web) { monit_config "nginx" }
- task(:mysql, roles: :db) { monit_config "mysql" }
- task(:postgresql, roles: :db) { monit_config "postgresql" }
- task(:unicorn, roles: :app) { monit_config "unicorn", "/etc/monit/conf.d/unicorn_#{application}.conf" }
-
- %w[start stop restart syntax force_reload].each do |command|
- desc "Run Monit #{command} script"
- task command do
- run "#{sudo} /etc/init.d/monit #{command.gsub(/_/, '-')}"
- end
- end
-end
-
-def monit_config(name, destination = nil)
- destination ||= "/etc/monit/conf.d/#{name}.conf"
- template "monit/#{name}.erb", "/tmp/monit_#{name}"
- run "#{sudo} mv /tmp/monit_#{name} #{destination}"
- run "#{sudo} chown root #{destination}"
- run "#{sudo} chmod 600 #{destination}"
-end
diff --git a/config/recipes/nginx.rb b/config/recipes/nginx.rb
deleted file mode 100644
index 5e846ab4..00000000
--- a/config/recipes/nginx.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-namespace :nginx do
- desc "Install nginx"
- task :install, roles: :web do
- run "#{sudo} apt-get -y install nginx"
- end
- after "deploy:install", "nginx:install"
-
- desc "Setup nginx configuration for this application"
- task :setup, roles: :web do
- template "nginx_unicorn.erb", "/tmp/nginx_conf"
- run "#{sudo} mv /tmp/nginx_conf /etc/nginx/sites-enabled/#{application}"
- run "#{sudo} rm -f /etc/nginx/sites-enabled/default"
- restart
- end
- after "deploy:setup", "nginx:setup"
-
- %w[start stop restart].each do |command|
- desc "#{command} nginx"
- task command, roles: :web do
- run "#{sudo} service nginx #{command}"
- end
- end
-end
diff --git a/config/recipes/postgresql.rb b/config/recipes/postgresql.rb
deleted file mode 100644
index 09331474..00000000
--- a/config/recipes/postgresql.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-set_default(:postgresql_host, "localhost")
-set_default(:postgresql_user) { application }
-set_default(:postgresql_password) { Capistrano::CLI.password_prompt "PostgreSQL Password: " }
-set_default(:postgresql_database) { "#{application}_#{rails_env}" }
-set_default(:postgresql_pid) { "/var/run/postgresql/9.2-main.pid" }
-
-namespace :postgresql do
- desc "Install PostgreSQL."
- task :install, roles: :db, only: {primary: true} do
- run "#{sudo} apt-get -y install postgresql postgresql-contrib libpq-dev"
- end
- after "deploy:install", "postgresql:install"
-
- desc "Create a database for this application."
- task :create_database, roles: :db, only: {primary: true} do
- #run %Q{#{sudo} -u postgres psql -c "drop database #{postgresql_database};"}
- #run %Q{#{sudo} -u postgres psql -c "drop user #{postgresql_user};"}
- run %Q{#{sudo} -u postgres psql -c "create user #{postgresql_user} with SUPERUSER LOGIN CREATEDB REPLICATION password '#{postgresql_password}';"}
- run %Q{#{sudo} -u postgres psql -c "create database #{postgresql_database} owner #{postgresql_user};"}
- end
- after "deploy:setup", "postgresql:create_database"
-
- desc "Generate the database.yml configuration file."
- task :setup, roles: :app do
- run "mkdir -p #{shared_path}/config"
- template "postgresql.yml.erb", "#{shared_path}/config/database.yml"
- end
- after "deploy:setup", "postgresql:setup"
-
- desc "Symlink the database.yml file into latest release"
- task :symlink, roles: :app do
- run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
- end
- # it is done in 'deploy:symlink_configs'
- # after "deploy:finalize_update", "postgresql:symlink"
-end
diff --git a/config/recipes/templates/monit/monitrc.erb b/config/recipes/templates/monit/monitrc.erb
deleted file mode 100644
index 9db1e162..00000000
--- a/config/recipes/templates/monit/monitrc.erb
+++ /dev/null
@@ -1,26 +0,0 @@
-set daemon 30
-
-set logfile /var/log/monit.log
-set idfile /var/lib/monit/id
-set statefile /var/lib/monit/state
-
-set eventqueue
- basedir /var/lib/monit/events
- slots 100
-
-# set mailserver smtp.gmail.com port 587
-# username "foo@example.com" password "secret"
-# using tlsv1
-# with timeout 30 seconds
-
-# set alert mikdiet@gmail.com
-
-# set httpd port 2812
-# allow admin:"secret"
-
-check system first
- if loadavg(5min) > 2 for 2 cycles then alert
- if memory > 75% for 2 cycles then alert
- if cpu(user) > 75% for 2 cycles then alert
-
-include /etc/monit/conf.d/*
diff --git a/config/recipes/templates/monit/mysql.erb b/config/recipes/templates/monit/mysql.erb
deleted file mode 100644
index c4d451e9..00000000
--- a/config/recipes/templates/monit/mysql.erb
+++ /dev/null
@@ -1,5 +0,0 @@
-check process mysql with pidfile /var/run/mysqld/mysqld.pid
- start program = "/etc/init.d/mysql start"
- stop program = "/etc/init.d/mysql stop"
- if failed host localhost port 3306 protocol mysql then restart
- if 5 restarts within 5 cycles then timeout
diff --git a/config/recipes/templates/monit/nginx.erb b/config/recipes/templates/monit/nginx.erb
deleted file mode 100644
index c1d6dd59..00000000
--- a/config/recipes/templates/monit/nginx.erb
+++ /dev/null
@@ -1,5 +0,0 @@
-check process nginx with pidfile /var/run/nginx.pid
- start program = "/etc/init.d/nginx start"
- stop program = "/etc/init.d/nginx stop"
- if children > 250 then restart
- if 5 restarts within 5 cycles then timeout
diff --git a/config/recipes/templates/monit/postgresql.erb b/config/recipes/templates/monit/postgresql.erb
deleted file mode 100644
index 22e56526..00000000
--- a/config/recipes/templates/monit/postgresql.erb
+++ /dev/null
@@ -1,5 +0,0 @@
-check process postgresql with pidfile <%= postgresql_pid %>
- start program = "/etc/init.d/postgresql start"
- stop program = "/etc/init.d/postgresql stop"
- if failed host localhost port 5432 protocol pgsql then restart
- if 5 restarts within 5 cycles then timeout
diff --git a/config/recipes/templates/monit/unicorn.erb b/config/recipes/templates/monit/unicorn.erb
deleted file mode 100644
index 8b598e45..00000000
--- a/config/recipes/templates/monit/unicorn.erb
+++ /dev/null
@@ -1,15 +0,0 @@
-check process <%= application %>_unicorn with pidfile <%= unicorn_pid %>
- start program = "/etc/init.d/unicorn_<%= application %> start"
- stop program = "/etc/init.d/unicorn_<%= application %> stop"
-
-<% unicorn_workers.times do |n| %>
- <% pid = unicorn_pid.sub(".pid", ".#{n}.pid") %>
- check process <%= application %>_unicorn_worker_<%= n %> with pidfile <%= pid %>
- start program = "/bin/true"
- stop program = "/usr/bin/test -s <%= pid %> && /bin/kill -QUIT `cat <%= pid %>`"
- if mem > 200.0 MB for 1 cycles then restart
- if cpu > 25% for 3 cycles then restart
- if 5 restarts within 5 cycles then timeout
- alert mikdiet@gmail.com only on { pid }
- if changed pid 2 times within 60 cycles then alert
-<% end %>
diff --git a/config/recipes/templates/nginx_unicorn.erb b/config/recipes/templates/nginx_unicorn.erb
deleted file mode 100644
index 89fff41c..00000000
--- a/config/recipes/templates/nginx_unicorn.erb
+++ /dev/null
@@ -1,33 +0,0 @@
-upstream <%= application %>_unicorn {
- server unix:/tmp/unicorn.<%= application %>.sock fail_timeout=0;
-}
-
-server {
- listen 80;
- server_name <%= subdomains.join(' ') %>;
- root <%= current_path %>/public;
- location ^~ /assets/ {
- gzip_static on;
- expires max;
- add_header Cache-Control public;
- }
-
- try_files $uri/index.html $uri @unicorn;
- location @unicorn {
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host;
- proxy_redirect off;
- proxy_pass http://<%= application %>_unicorn;
- }
- error_page 500 502 503 504 /500.html;
- client_max_body_size 4G;
- keepalive_timeout 10;
-
- if (-f $document_root/system/maintenance.html) {
- return 503;
- }
- error_page 503 @maintenance;
- location @maintenance {
- rewrite ^(.*)$ /system/maintenance.html last;
- break;
- }
-}
diff --git a/config/recipes/templates/postgresql.yml.erb b/config/recipes/templates/postgresql.yml.erb
deleted file mode 100644
index fb9ab5df..00000000
--- a/config/recipes/templates/postgresql.yml.erb
+++ /dev/null
@@ -1,8 +0,0 @@
-<%= rails_env %>:
- adapter: postgresql
- encoding: unicode
- database: <%= postgresql_database %>
- pool: 5
- username: <%= postgresql_user %>
- password: <%= postgresql_password %>
- host: <%= postgresql_host %>
diff --git a/config/recipes/templates/unicorn.rb.erb b/config/recipes/templates/unicorn.rb.erb
deleted file mode 100644
index 6a88a6c8..00000000
--- a/config/recipes/templates/unicorn.rb.erb
+++ /dev/null
@@ -1,36 +0,0 @@
-working_directory "<%= current_path %>"
-pid "<%= unicorn_pid %>"
-stderr_path "<%= unicorn_log %>"
-stdout_path "<%= unicorn_log %>"
-
-listen "/tmp/unicorn.<%= application %>.sock"
-worker_processes <%= unicorn_workers %>
-timeout 30
-
-preload_app true
-
-before_fork do |server, worker|
- # Disconnect since the database connection will not carry over
- if defined? ActiveRecord::Base
- ActiveRecord::Base.connection.disconnect!
- end
-
- # Quit the old unicorn process
- old_pid = "#{server.config[:pid]}.oldbin"
- if File.exists?(old_pid) && server.pid != old_pid
- begin
- Process.kill("QUIT", File.read(old_pid).to_i)
- rescue Errno::ENOENT, Errno::ESRCH
- # someone else did our job for us
- end
- end
-end
-
-after_fork do |server, worker|
- # Start up the database connection again in the worker
- if defined?(ActiveRecord::Base)
- ActiveRecord::Base.establish_connection
- end
- child_pid = server.config[:pid].sub(".pid", ".#{worker.nr}.pid")
- system("echo #{Process.pid} > #{child_pid}")
-end
diff --git a/config/recipes/templates/unicorn_init.erb b/config/recipes/templates/unicorn_init.erb
deleted file mode 100755
index 848885c6..00000000
--- a/config/recipes/templates/unicorn_init.erb
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/bin/sh
-### BEGIN INIT INFO
-# Provides: unicorn_<%= application %>
-# Required-Start: $remote_fs $syslog
-# Required-Stop: $remote_fs $syslog
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: Manage unicorn server
-# Description: Start, stop, restart unicorn server for a specific application.
-### END INIT INFO
-set -e
-
-# Feel free to change any of the following variables for your app:
-TIMEOUT=${TIMEOUT-60}
-APP_ROOT=<%= current_path %>
-PID=<%= unicorn_pid %>
-CMD="cd <%= current_path %>; <%= bundle_cmd %> exec unicorn -D -c <%= unicorn_config %> -E production"
-AS_USER=<%= unicorn_user %>
-set -u
-
-OLD_PIN="$PID.oldbin"
-
-sig () {
- test -s "$PID" && kill -$1 `cat $PID`
-}
-
-oldsig () {
- test -s $OLD_PIN && kill -$1 `cat $OLD_PIN`
-}
-
-run () {
- if [ "$(id -un)" = "$AS_USER" ]; then
- eval $1
- else
- su -c "$1" - $AS_USER
- fi
-}
-
-case "$1" in
-start)
- sig 0 && echo >&2 "Already running" && exit 0
- run "$CMD"
- ;;
-stop)
- sig QUIT && exit 0
- echo >&2 "Not running"
- ;;
-force-stop)
- sig TERM && exit 0
- echo >&2 "Not running"
- ;;
-restart|reload)
- sig USR2 && echo reloaded OK && exit 0
- echo >&2 "Couldn't reload, starting '$CMD' instead"
- run "$CMD"
- ;;
-upgrade)
- if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
- then
- n=$TIMEOUT
- while test -s $OLD_PIN && test $n -ge 0
- do
- printf '.' && sleep 1 && n=$(( $n - 1 ))
- done
- echo
-
- if test $n -lt 0 && test -s $OLD_PIN
- then
- echo >&2 "$OLD_PIN still exists after $TIMEOUT seconds"
- exit 1
- fi
- exit 0
- fi
- echo >&2 "Couldn't upgrade, starting '$CMD' instead"
- run "$CMD"
- ;;
-reopen-logs)
- sig USR1
- ;;
-*)
- echo >&2 "Usage: $0 "
- exit 1
- ;;
-esac
diff --git a/config/recipes/unicorn.rb b/config/recipes/unicorn.rb
deleted file mode 100644
index 9c99a0ed..00000000
--- a/config/recipes/unicorn.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-set_default(:unicorn_user) { user }
-set_default(:unicorn_pid) { "#{current_path}/tmp/pids/unicorn.pid" }
-set_default(:unicorn_config) { "#{shared_path}/config/unicorn.rb" }
-set_default(:unicorn_log) { "#{shared_path}/log/unicorn.log" }
-set_default(:unicorn_workers, 2)
-
-namespace :unicorn do
- desc "Setup Unicorn initializer and app configuration"
- task :setup, roles: :app do
- run "mkdir -p #{shared_path}/config"
- template "unicorn.rb.erb", unicorn_config
- template "unicorn_init.erb", "/tmp/unicorn_init"
- run "chmod +x /tmp/unicorn_init"
- run "#{sudo} mv /tmp/unicorn_init /etc/init.d/unicorn_#{application}"
- run "#{sudo} update-rc.d -f unicorn_#{application} defaults"
- end
- after "deploy:setup", "unicorn:setup"
-
- %w[start stop restart].each do |command|
- desc "#{command} unicorn"
- task command, roles: :app do
- run "/etc/init.d/unicorn_#{application} #{command}"
- end
- after "deploy:#{command}", "unicorn:#{command}"
- end
-end
diff --git a/config/routes.rb b/config/routes.rb
index 27de8228..6d36a123 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,8 +1,5 @@
-Rusrails::Application.routes.draw do
- get 'map' => 'pages#map'
-
+Rails.application.routes.draw do
resource :search, only: :show, controller: :search
mount StaticDocs::Engine, at: "/"
-
end
diff --git a/config/secrets.yml b/config/secrets.yml
new file mode 100644
index 00000000..6dd1ae6a
--- /dev/null
+++ b/config/secrets.yml
@@ -0,0 +1,32 @@
+# Be sure to restart your server when you modify this file.
+
+# Your secret key is used for verifying the integrity of signed cookies.
+# If you change this key, all old signed cookies will become invalid!
+
+# Make sure the secret is at least 30 characters and all random,
+# no regular words or you'll be exposed to dictionary attacks.
+# You can use `rails secret` to generate a secure secret key.
+
+# Make sure the secrets in this file are kept private
+# if you're sharing your code publicly.
+
+# Shared secrets are available across all environments.
+
+# shared:
+# api_key: a1B2c3D4e5F6
+
+# Environmental secrets are only available for that specific environment.
+
+development:
+ secret_key_base: a40015f6c1d36a1d1d64b26013aa7ac90365cba5de584775c24f55cc2b77e7c67fef4e487cedc54d256bb5a1808a29ac0fecdc814eaf82362b7812df46ce18cb
+
+test:
+ secret_key_base: bf6e7bf22f90578b5bca197e9d067858ff6222086784cb970235aa41e5f9f27fc505307f024da707e51da6e170ef80784d13ed4e6a2a3de18ebac2a4f94a454e
+
+# Do not keep production secrets in the unencrypted secrets file.
+# Instead, either read values from the environment.
+# Or, use `bin/rails secrets:setup` to configure encrypted secrets
+# and move the `production:` environment over there.
+
+production:
+ secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
diff --git a/config/spring.rb b/config/spring.rb
new file mode 100644
index 00000000..c9119b40
--- /dev/null
+++ b/config/spring.rb
@@ -0,0 +1,6 @@
+%w(
+ .ruby-version
+ .rbenv-vars
+ tmp/restart.txt
+ tmp/caching-dev.txt
+).each { |path| Spring.watch(path) }
diff --git a/config/storage.yml b/config/storage.yml
new file mode 100644
index 00000000..d32f76e8
--- /dev/null
+++ b/config/storage.yml
@@ -0,0 +1,34 @@
+test:
+ service: Disk
+ root: <%= Rails.root.join("tmp/storage") %>
+
+local:
+ service: Disk
+ root: <%= Rails.root.join("storage") %>
+
+# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
+# amazon:
+# service: S3
+# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
+# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
+# region: us-east-1
+# bucket: your_own_bucket
+
+# Remember not to checkin your GCS keyfile to a repository
+# google:
+# service: GCS
+# project: your_project
+# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
+# bucket: your_own_bucket
+
+# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
+# microsoft:
+# service: AzureStorage
+# storage_account_name: your_account_name
+# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
+# container: your_container_name
+
+# mirror:
+# service: Mirror
+# primary: local
+# mirrors: [ amazon, google, microsoft ]
diff --git a/cspell.config.mjs b/cspell.config.mjs
new file mode 100644
index 00000000..10a2fb67
--- /dev/null
+++ b/cspell.config.mjs
@@ -0,0 +1,69 @@
+// Kindly provided by @Jason3S
+//
+// https://github.com/streetsidesoftware/cspell/discussions/5118#discussioncomment-7972837
+
+import { promises as fs } from 'fs';
+
+function expand(pattern, options = { begin: '(', end: ')', sep: '|' }, start = 0) {
+ const len = pattern.length;
+ const parts = [];
+ function push(word) {
+ if (Array.isArray(word)) {
+ parts.push(...word);
+ } else {
+ parts.push(word);
+ }
+ }
+ let i = start;
+ let curWord = '';
+ while (i < len) {
+ const ch = pattern[i++];
+ if (ch === options.end) {
+ break;
+ }
+ if (ch === options.begin) {
+ const nested = expand(pattern, options, i);
+ i = nested.idx;
+ curWord = nested.parts.flatMap((p) => (Array.isArray(curWord) ? curWord.map((w) => w + p) : [curWord + p]));
+ continue;
+ }
+ if (ch === options.sep) {
+ push(curWord);
+ curWord = '';
+ continue;
+ }
+ curWord = Array.isArray(curWord) ? curWord.map((w) => w + ch) : curWord + ch;
+ }
+ push(curWord);
+ return { parts, idx: i };
+}
+
+function expandWord(pattern, options = { begin: '(', end: ')', sep: '|' }) {
+ return expand(pattern, options).parts;
+}
+
+function expandWords(wordList) {
+ const words = wordList
+ .split(/\n/g)
+ .map((w) => w.trim())
+ .filter((w) => !!w && !w.startsWith('#'))
+ .flatMap((w) => expandWord(w));
+ return words;
+}
+
+const wordsFile = new URL('words.txt', import.meta.url);
+
+const wordList = await fs.readFile(wordsFile, 'utf8');
+
+const config = {
+ id: 'example-config',
+ dictionaryDefinitions: [
+ {
+ name: 'custom-words',
+ words: expandWords(wordList),
+ },
+ ],
+ dictionaries: ['custom-words'],
+};
+
+export default config;
\ No newline at end of file
diff --git a/cspell.json b/cspell.json
new file mode 100644
index 00000000..812c63fe
--- /dev/null
+++ b/cspell.json
@@ -0,0 +1,8 @@
+{
+ "import": [
+ "@cspell/dict-ru_ru/cspell-ext.json"
+ ],
+ "version": "0.2",
+ "language": "ru",
+ "ignoreRegExpList": ["/[a-zA-Z]+/g"]
+}
\ No newline at end of file
diff --git a/db/migrate/20210516125901_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb b/db/migrate/20210516125901_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb
new file mode 100644
index 00000000..ff5d72c7
--- /dev/null
+++ b/db/migrate/20210516125901_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb
@@ -0,0 +1,10 @@
+# This migration comes from active_storage (originally 20180723000244)
+class AddForeignKeyConstraintToActiveStorageAttachmentsForBlobId < ActiveRecord::Migration[6.0]
+ def up
+ return if foreign_key_exists?(:active_storage_attachments, column: :blob_id)
+
+ if table_exists?(:active_storage_blobs)
+ add_foreign_key :active_storage_attachments, :active_storage_blobs, column: :blob_id
+ end
+ end
+end
diff --git a/db/migrate/20230711215740_add_service_name_to_active_storage_blobs.active_storage.rb b/db/migrate/20230711215740_add_service_name_to_active_storage_blobs.active_storage.rb
new file mode 100644
index 00000000..a15c6ce8
--- /dev/null
+++ b/db/migrate/20230711215740_add_service_name_to_active_storage_blobs.active_storage.rb
@@ -0,0 +1,22 @@
+# This migration comes from active_storage (originally 20190112182829)
+class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0]
+ def up
+ return unless table_exists?(:active_storage_blobs)
+
+ unless column_exists?(:active_storage_blobs, :service_name)
+ add_column :active_storage_blobs, :service_name, :string
+
+ if configured_service = ActiveStorage::Blob.service.name
+ ActiveStorage::Blob.unscoped.update_all(service_name: configured_service)
+ end
+
+ change_column :active_storage_blobs, :service_name, :string, null: false
+ end
+ end
+
+ def down
+ return unless table_exists?(:active_storage_blobs)
+
+ remove_column :active_storage_blobs, :service_name
+ end
+end
diff --git a/db/migrate/20230711215741_create_active_storage_variant_records.active_storage.rb b/db/migrate/20230711215741_create_active_storage_variant_records.active_storage.rb
new file mode 100644
index 00000000..94ac83af
--- /dev/null
+++ b/db/migrate/20230711215741_create_active_storage_variant_records.active_storage.rb
@@ -0,0 +1,27 @@
+# This migration comes from active_storage (originally 20191206030411)
+class CreateActiveStorageVariantRecords < ActiveRecord::Migration[6.0]
+ def change
+ return unless table_exists?(:active_storage_blobs)
+
+ # Use Active Record's configured type for primary key
+ create_table :active_storage_variant_records, id: primary_key_type, if_not_exists: true do |t|
+ t.belongs_to :blob, null: false, index: false, type: blobs_primary_key_type
+ t.string :variation_digest, null: false
+
+ t.index %i[ blob_id variation_digest ], name: "index_active_storage_variant_records_uniqueness", unique: true
+ t.foreign_key :active_storage_blobs, column: :blob_id
+ end
+ end
+
+ private
+ def primary_key_type
+ config = Rails.configuration.generators
+ config.options[config.orm][:primary_key_type] || :primary_key
+ end
+
+ def blobs_primary_key_type
+ pkey_name = connection.primary_key(:active_storage_blobs)
+ pkey_column = connection.columns(:active_storage_blobs).find { |c| c.name == pkey_name }
+ pkey_column.bigint? ? :bigint : pkey_column.type
+ end
+end
diff --git a/db/migrate/20231105110018_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb b/db/migrate/20231105110018_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb
new file mode 100644
index 00000000..93c8b85a
--- /dev/null
+++ b/db/migrate/20231105110018_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb
@@ -0,0 +1,8 @@
+# This migration comes from active_storage (originally 20211119233751)
+class RemoveNotNullOnActiveStorageBlobsChecksum < ActiveRecord::Migration[6.0]
+ def change
+ return unless table_exists?(:active_storage_blobs)
+
+ change_column_null(:active_storage_blobs, :checksum, true)
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index c4af0322..e27622a6 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -1,39 +1,36 @@
-# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
-# Note that this schema.rb definition is the authoritative source for your
-# database schema. If you need to create the application database on another
-# system, you should be using db:schema:load, not running all the migrations
-# from scratch. The latter is a flawed and unsustainable approach (the more migrations
-# you'll amass, the slower it'll run and the greater likelihood for issues).
+# This file is the source Rails uses to define your schema when running `bin/rails
+# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
+# be faster and is potentially less error prone than running all of your
+# migrations from scratch. Old migrations may fail to apply correctly if those
+# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20130503124427) do
-
+ActiveRecord::Schema[7.0].define(version: 2023_11_05_110018) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
- create_table "redirects", force: true do |t|
- t.string "from"
- t.string "to"
- t.datetime "created_at"
- t.datetime "updated_at"
+ create_table "redirects", force: :cascade do |t|
+ t.string "from"
+ t.string "to"
+ t.datetime "created_at", precision: nil
+ t.datetime "updated_at", precision: nil
end
- create_table "static_docs_pages", force: true do |t|
- t.string "title"
- t.string "path"
- t.string "namespace"
- t.text "body"
- t.string "extension"
- t.datetime "created_at"
- t.datetime "updated_at"
+ create_table "static_docs_pages", force: :cascade do |t|
+ t.string "title"
+ t.string "path"
+ t.string "namespace"
+ t.text "body"
+ t.string "extension"
+ t.datetime "created_at", precision: nil
+ t.datetime "updated_at", precision: nil
+ t.index ["namespace"], name: "index_static_docs_pages_on_namespace"
+ t.index ["path"], name: "index_static_docs_pages_on_path"
end
- add_index "static_docs_pages", ["namespace"], name: "index_static_docs_pages_on_namespace", using: :btree
- add_index "static_docs_pages", ["path"], name: "index_static_docs_pages_on_path", using: :btree
-
end
diff --git a/db/seeds.rb b/db/seeds.rb
index d7fbcdc4..7aaf7fa5 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -1,201 +1,6 @@
Redirect.delete_all
current_redirects = {
- '/rails-routing/breaking-up-a-large-route-file' => '/rails-routing',
- '/active-record-validations-and-callbacks/the-object-lifecycle' => '/different-guides/active-record-callbacks',
- '/active-record-validations-and-callbacks/callbacks' => '/different-guides/active-record-callbacks',
- '/active-record-validations-and-callbacks/observers' => '/different-guides/active-record-callbacks',
- '/action-mailer-basics/asynchronous' => '/action-mailer-basics',
- '/ruby-on-rails-security-guide/mass-assignment' => '/ruby-on-rails-security-guide',
-
- '/getting-started-with-rails/this-guide-assumes' => '/getting-started-with-rails',
- '/getting-started-with-rails/what-is-rails' => '/getting-started-with-rails',
- '/getting-started-with-rails/creating-a-new-rails-project' => '/getting-started-with-rails',
- '/getting-started-with-rails/hello-rails' => '/getting-started-with-rails',
- '/getting-started-with-rails/getting-up-and-running' => '/getting-started-with-rails',
- '/getting-started-with-rails/adding-a-second-model' => '/getting-started-with-rails',
- '/getting-started-with-rails/refactoring' => '/getting-started-with-rails',
- '/getting-started-with-rails/deleting-comments' => '/getting-started-with-rails',
- '/getting-started-with-rails/security' => '/getting-started-with-rails',
- '/getting-started-with-rails/whats-next' => '/getting-started-with-rails',
- '/getting-started-with-rails/configuration-gotchas' => '/getting-started-with-rails',
-
- '/rails-database-migrations/anatomy-of-a-migration' => '/rails-database-migrations',
- '/rails-database-migrations/creating-a-migration' => '/rails-database-migrations',
- '/rails-database-migrations/writing-a-migration' => '/rails-database-migrations',
- '/rails-database-migrations/running-migrations' => '/rails-database-migrations',
- '/rails-database-migrations/changing-existing-migrations' => '/rails-database-migrations',
- '/rails-database-migrations/using-models-in-your-migrations' => '/rails-database-migrations',
- '/rails-database-migrations/schema-dumping-and-you' => '/rails-database-migrations',
- '/rails-database-migrations/active-record-and-referential-integrity' => '/rails-database-migrations',
- '/rails-database-migrations/migrations-and-seed-data' => '/rails-database-migrations',
-
- '/active-record-validations-and-callbacks/validations-overview' => '/active-record-validations',
- '/active-record-validations-and-callbacks/validation-helpers' => '/active-record-validations',
- '/active-record-validations-and-callbacks/common-validation-options' => '/active-record-validations',
- '/active-record-validations-and-callbacks/strict-validations' => '/active-record-validations',
- '/active-record-validations-and-callbacks/conditional-validation' => '/active-record-validations',
- '/active-record-validations-and-callbacks/creating-custom-validation-methods' => '/active-record-validations',
- '/active-record-validations-and-callbacks/working-with-validation-errors' => '/active-record-validations',
- '/active-record-validations-and-callbacks/displaying-validation-errors-in-the-view' => '/active-record-validations',
-
- '/active-record-validations-and-callbacks' => '/active-record-validations',
-
- '/active-record-associations/why-associations' => '/active-record-associations',
- '/active-record-associations/the-types-of-associations-1' => '/active-record-associations',
- '/active-record-associations/the-types-of-associations-2' => '/active-record-associations',
- '/active-record-associations/tips-tricks-and-warnings' => '/active-record-associations',
- '/active-record-associations/belongsto-association-reference' => '/active-record-associations',
- '/active-record-associations/hasone-association-reference' => '/active-record-associations',
- '/active-record-associations/hasmany-association-reference' => '/active-record-associations',
- '/active-record-associations/hasandbelongstomany-association-reference' => '/active-record-associations',
- '/active-record-associations/association-callbacks-and-extensions' => '/active-record-associations',
-
- '/active-record-query-interface/retrieving-objects-from-the-database' => '/active-record-query-interface',
- '/active-record-query-interface/conditions' => '/active-record-query-interface',
- '/active-record-query-interface/find-options' => '/active-record-query-interface',
- '/active-record-query-interface/joining-tables' => '/active-record-query-interface',
- '/active-record-query-interface/eager-loading-associations' => '/active-record-query-interface',
- '/active-record-query-interface/scopes' => '/active-record-query-interface',
- '/active-record-query-interface/dynamic-finders' => '/active-record-query-interface',
- '/active-record-query-interface/find-or-build-a-new-object' => '/active-record-query-interface',
- '/active-record-query-interface/finding-by-sql' => '/active-record-query-interface',
- '/active-record-query-interface/selectall' => '/active-record-query-interface',
- '/active-record-query-interface/pluck' => '/active-record-query-interface',
- '/active-record-query-interface/existence-of-objects' => '/active-record-query-interface',
- '/active-record-query-interface/calculations' => '/active-record-query-interface',
- '/active-record-query-interface/running-explain' => '/active-record-query-interface',
-
- '/layouts-and-rendering-in-rails/overview-how-the-pieces-fit-together' => '/layouts-and-rendering-in-rails',
- '/layouts-and-rendering-in-rails/creating-responses-1' => '/layouts-and-rendering-in-rails',
- '/layouts-and-rendering-in-rails/creating-responses-2' => '/layouts-and-rendering-in-rails',
- '/layouts-and-rendering-in-rails/structuring-layouts' => '/layouts-and-rendering-in-rails',
- '/layouts-and-rendering-in-rails/structuring-layouts-2' => '/layouts-and-rendering-in-rails',
- '/layouts-and-rendering-in-rails/structuring-layouts-3' => '/layouts-and-rendering-in-rails',
-
- '/rails-form-helpers/dealing-with-basic-forms' => '/rails-form-helpers',
- '/rails-form-helpers/dealing-with-model-objects' => '/rails-form-helpers',
- '/rails-form-helpers/making-select-boxes-with-ease' => '/rails-form-helpers',
- '/rails-form-helpers/using-date-and-time-form-helpers' => '/rails-form-helpers',
- '/rails-form-helpers/uploading-files' => '/rails-form-helpers',
- '/rails-form-helpers/customising-form-builders' => '/rails-form-helpers',
- '/rails-form-helpers/understanding-parameter-naming-conventions' => '/rails-form-helpers',
- '/rails-form-helpers/forms-to-external-resources' => '/rails-form-helpers',
- '/rails-form-helpers/building-complex-forms' => '/rails-form-helpers',
-
- '/action-controller-overview/what-does-a-controller-do' => '/action-controller-overview',
- '/action-controller-overview/methods-and-actions' => '/action-controller-overview',
- '/action-controller-overview/parameters' => '/action-controller-overview',
- '/action-controller-overview/session' => '/action-controller-overview',
- '/action-controller-overview/cookies' => '/action-controller-overview',
- '/action-controller-overview/rendering-xml-and-json-data' => '/action-controller-overview',
- '/action-controller-overview/filters' => '/action-controller-overview',
- '/action-controller-overview/request-forgery-protection' => '/action-controller-overview',
- '/action-controller-overview/the-request-and-response-objects' => '/action-controller-overview',
- '/action-controller-overview/http-authentications' => '/action-controller-overview',
- '/action-controller-overview/streaming-and-file-downloads' => '/action-controller-overview',
- '/action-controller-overview/parameter-filtering' => '/action-controller-overview',
- '/action-controller-overview/rescue' => '/action-controller-overview',
- '/action-controller-overview/force-https-protocol' => '/action-controller-overview',
-
- '/rails-routing/the-purpose-of-the-rails-router' => '/rails-routing',
- '/rails-routing/resource-routing-the-rails-default-1' => '/rails-routing',
- '/rails-routing/resource-routing-the-rails-default-2' => '/rails-routing',
- '/rails-routing/non-resourceful-routes' => '/rails-routing',
- '/rails-routing/customizing-resourceful-routes' => '/rails-routing',
- '/rails-routing/inspecting-and-testing-routes' => '/rails-routing',
-
- '/active-support-core-extensions/how-to-load-core-extensions' => '/active-support-core-extensions',
- '/active-support-core-extensions/extensions-to-all-objects' => '/active-support-core-extensions',
- '/active-support-core-extensions/extensions-to-module' => '/active-support-core-extensions',
- '/active-support-core-extensions/extensions-to-class' => '/active-support-core-extensions',
- '/active-support-core-extensions/extensions-to-string' => '/active-support-core-extensions',
- '/active-support-core-extensions/extensions-to-numeric-integer-float' => '/active-support-core-extensions',
- '/active-support-core-extensions/extensions-to-enumerable' => '/active-support-core-extensions',
- '/active-support-core-extensions/extensions-to-array' => '/active-support-core-extensions',
- '/active-support-core-extensions/extensions-to-hash' => '/active-support-core-extensions',
- '/active-support-core-extensions/extensions-to-regexp' => '/active-support-core-extensions',
- '/active-support-core-extensions/extensions-to-range' => '/active-support-core-extensions',
- '/active-support-core-extensions/extensions-to-proc' => '/active-support-core-extensions',
- '/active-support-core-extensions/extensions-to-date' => '/active-support-core-extensions',
- '/active-support-core-extensions/extensions-to-datetime' => '/active-support-core-extensions',
- '/active-support-core-extensions/extensions-to-time' => '/active-support-core-extensions',
- '/active-support-core-extensions/extensions-to-process-file-nameerror-loaderror' => '/active-support-core-extensions',
-
- '/rails-internationalization-i18n-api/how-i18n-in-ruby-on-rails-works' => '/rails-internationalization-i18n-api',
- '/rails-internationalization-i18n-api/setup-the-rails-application-for-internationalization' => '/rails-internationalization-i18n-api',
- '/rails-internationalization-i18n-api/internationalizing-your-application' => '/rails-internationalization-i18n-api',
- '/rails-internationalization-i18n-api/overview-of-the-i18n-api-features' => '/rails-internationalization-i18n-api',
- '/rails-internationalization-i18n-api/how-to-store-your-custom-translations' => '/rails-internationalization-i18n-api',
- '/rails-internationalization-i18n-api/customize-your-i18n-setup' => '/rails-internationalization-i18n-api',
-
- '/action-mailer-basics/sending-emails' => '/action-mailer-basics',
- '/action-mailer-basics/receiving-emails' => '/action-mailer-basics',
- '/action-mailer-basics/action-mailer-callbacks' => '/action-mailer-basics',
- '/action-mailer-basics/using-action-mailer-helpers' => '/action-mailer-basics',
- '/action-mailer-basics/action-mailer-configuration' => '/action-mailer-basics',
- '/action-mailer-basics/mailer-testing' => '/action-mailer-basics',
-
- '/a-guide-to-testing-rails-applications/why-write-tests-for-your-rails-applications' => '/a-guide-to-testing-rails-applications',
- '/a-guide-to-testing-rails-applications/introduction-to-testing' => '/a-guide-to-testing-rails-applications',
- '/a-guide-to-testing-rails-applications/unit-testing-your-models' => '/a-guide-to-testing-rails-applications',
- '/a-guide-to-testing-rails-applications/functional-tests-for-your-controllers' => '/a-guide-to-testing-rails-applications',
- '/a-guide-to-testing-rails-applications/integration-testing' => '/a-guide-to-testing-rails-applications',
- '/a-guide-to-testing-rails-applications/rake-tasks-for-running-your-tests' => '/a-guide-to-testing-rails-applications',
- '/a-guide-to-testing-rails-applications/brief-note-about-test-unit' => '/a-guide-to-testing-rails-applications',
- '/a-guide-to-testing-rails-applications/setup-and-teardown' => '/a-guide-to-testing-rails-applications',
- '/a-guide-to-testing-rails-applications/testing-routes' => '/a-guide-to-testing-rails-applications',
- '/a-guide-to-testing-rails-applications/testing-your-mailers' => '/a-guide-to-testing-rails-applications',
- '/a-guide-to-testing-rails-applications/other-testing-approaches' => '/a-guide-to-testing-rails-applications',
-
- '/ruby-on-rails-security-guide/introduction' => '/ruby-on-rails-security-guide',
- '/ruby-on-rails-security-guide/sessions' => '/ruby-on-rails-security-guide',
- '/ruby-on-rails-security-guide/cross-site-request-forgery-csrf' => '/ruby-on-rails-security-guide',
- '/ruby-on-rails-security-guide/redirection-and-files' => '/ruby-on-rails-security-guide',
- '/ruby-on-rails-security-guide/intranet-and-admin-security' => '/ruby-on-rails-security-guide',
- '/ruby-on-rails-security-guide/user-management' => '/ruby-on-rails-security-guide',
- '/ruby-on-rails-security-guide/injection' => '/ruby-on-rails-security-guide',
- '/ruby-on-rails-security-guide/default-headers' => '/ruby-on-rails-security-guide',
- '/ruby-on-rails-security-guide/additional-resources' => '/ruby-on-rails-security-guide',
-
- '/debugging-rails-applications/view-helpers-for-debugging' => '/debugging-rails-applications',
- '/debugging-rails-applications/the-logger' => '/debugging-rails-applications',
- '/debugging-rails-applications/debugging-with-ruby-debug' => '/debugging-rails-applications',
- '/debugging-rails-applications/debugging-memory-leaks' => '/debugging-rails-applications',
- '/debugging-rails-applications/plugins-for-debugging-references' => '/debugging-rails-applications',
-
- '/configuring-rails-applications/locations-for-initialization-code' => '/configuring-rails-applications',
- '/configuring-rails-applications/configuring-rails-components' => '/configuring-rails-applications',
- '/configuring-rails-applications/rails-environment-settings' => '/configuring-rails-applications',
- '/configuring-rails-applications/initialization' => '/configuring-rails-applications',
- '/configuring-rails-applications/database-pooling' => '/configuring-rails-applications',
-
- '/a-guide-to-the-rails-command-line/command-line-basics' => '/a-guide-to-the-rails-command-line',
- '/a-guide-to-the-rails-command-line/rake' => '/a-guide-to-the-rails-command-line',
- '/a-guide-to-the-rails-command-line/the-rails-advanced-command-line' => '/a-guide-to-the-rails-command-line',
-
- '/caching-with-rails-an-overview/basic-caching' => '/caching-with-rails-an-overview',
- '/caching-with-rails-an-overview/cache-stores' => '/caching-with-rails-an-overview',
- '/caching-with-rails-an-overview/conditional-get-support' => '/caching-with-rails-an-overview',
-
- '/asset-pipeline/what-is-the-asset-pipeline' => '/asset-pipeline',
- '/asset-pipeline/how-to-use-the-asset-pipeline' => '/asset-pipeline',
- '/asset-pipeline/in-development' => '/asset-pipeline',
- '/asset-pipeline/in-production' => '/asset-pipeline',
- '/asset-pipeline/customizing-the-pipeline' => '/asset-pipeline',
- '/asset-pipeline/assets-cache-store' => '/asset-pipeline',
- '/asset-pipeline/adding-assets-to-your-gems' => '/asset-pipeline',
- '/asset-pipeline/upgrading-from-old-versions-of-rails' => '/asset-pipeline',
-
- '/different-guides/3_0_release_notes' => '/3_0_release_notes',
- '/different-guides/3_1_release_notes' => '/3_1_release_notes',
- '/different-guides/3_2_release_notes' => '/3_2_release_notes',
- '/different-guides/4_0_release_notes' => '/4_0_release_notes',
- '/different-guides/active-record-callbacks' => '/active-record-callbacks',
- '/different-guides/engines' => '/engines',
- '/different-guides/rails-on-rack' => '/rails-on-rack',
- '/different-guides/upgrading-ruby-on-rails' => '/upgrading-ruby-on-rails',
-
}
current_redirects.each do |from, to|
diff --git a/lib/renderers/markdown.rb b/lib/renderers/markdown.rb
index cc8a2453..e8e00d28 100644
--- a/lib/renderers/markdown.rb
+++ b/lib/renderers/markdown.rb
@@ -1,39 +1,70 @@
-# forked from https://github.com/lifo/docrails/blob/master/guides/rails_guides/markdown/renderer.rb
+# forked from https://github.com/rails/rails/blob/master/guides/rails_guides/markdown/renderer.rb
+class Rusrails::Markdown
+ def render(body)
+ engine.render(body)
+ end
-require 'redcarpet'
-require 'nokogiri'
+ def engine
+ @engine ||= Redcarpet::Markdown.new(Renderer, {
+ no_intra_emphasis: true,
+ fenced_code_blocks: true,
+ autolink: true,
+ strikethrough: true,
+ superscript: true,
+ tables: true
+ })
+ end
-class Markdown
+ # Add more common shell commands
+ Rouge::Lexers::Shell::BUILTINS << "|bin/rails|brew|bundle|gem|git|node|rails|rake|ruby|sqlite3|yarn"
class Renderer < Redcarpet::Render::HTML
attr_reader :headers
- def initialize(options={})
+ def initialize(options = {})
super
@numeration = []
@headers = []
+ @hid_container = []
+ @hid_hash = {}
end
def block_code(code, language)
- <<-HTML
-
+ HTML
end
def sanitizer
- @sanitizer ||= HTML::FullSanitizer.new
+ @sanitizer ||= Rails::Html::FullSanitizer.new
end
def header(text, header_level)
# Always increase the heading level by, so we can use h1, h2 heading in the document
header_level += 1
- text.gsub!(/\A\s*\(([^\)]+)\)/, '')
+ text.gsub!(/\A\s*\(([^\)]+)\)\s/, '')
hid = sanitizer.sanitize($1 || text).parameterize
+ @hid_container << hid
+
+ if @hid_container.include? hid
+ if @hid_hash[hid].present?
+ @hid_hash[hid] = @hid_hash[hid] + 1
+ else
+ prev_count_hid_container = @hid_container.count(hid) - 1
+ @hid_hash[hid] = prev_count_hid_container if prev_count_hid_container != 0
+ end
+
+ hid.concat (@hid_hash[hid].to_i + 1).to_s if @hid_hash[hid].present?
+ else
+ @hid_hash[hid] = @hid_container.count(hid)
+ end
+
if header_level > 2
@numeration[header_level] ||= 0
@numeration[header_level] += 1
@@ -84,10 +115,15 @@ def table(header, body)
end
def image(link, title, alt_text)
- %Q()
+ %Q()
+ end
+
+ private
+
+ def helpers
+ ActionController::Base.helpers
end
- private
def convert_footnotes(text)
text.gsub(/\[(\d+)\]<\/sup>/i) do
%() +
@@ -95,16 +131,16 @@ def convert_footnotes(text)
end
end
- def brush_for(code_type)
+ def lexer_language(code_type)
case code_type
- when 'ruby', 'sql', 'plain'
- code_type
- when 'erb'
- 'ruby; html-script: true'
- when 'html'
- 'xml' # html is understood, but there are .xml rules in the CSS
- else
- 'plain'
+ when "html+erb"
+ "erb"
+ when "bash"
+ "console"
+ when nil
+ "plaintext"
+ else
+ ::Rouge::Lexer.find(code_type) ? code_type : "plaintext"
end
end
@@ -130,20 +166,4 @@ def convert_notes(body)
end
end
end
-
- def render(body)
- engine.render(body)
- end
-
- def engine
- @engine ||= Redcarpet::Markdown.new(Renderer, {
- no_intra_emphasis: true,
- fenced_code_blocks: true,
- autolink: true,
- strikethrough: true,
- superscript: true,
- tables: true
- })
- end
-
end
diff --git a/lib/renderers/textile_extension.rb b/lib/renderers/textile_extension.rb
deleted file mode 100644
index bf69c98c..00000000
--- a/lib/renderers/textile_extension.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# forked from https://github.com/lifo/docrails/blob/master/guides/rails_guides/textile_extensions.rb
-
-module TextileExtensions
- def notestuff(body)
- # The following regexp detects special labels followed by a
- # paragraph, perhaps at the end of the document.
- #
- # It is important that we do not eat more than one newline
- # because formatting may be wrong otherwise. For example,
- # if a bulleted list follows the first item is not rendered
- # as a list item, but as a paragraph starting with a plain
- # asterisk.
- body.gsub!(/^(TIP|IMPORTANT|CAUTION|WARNING|NOTE|INFO)[.:](.*?)(\n(?=\n)|\Z)/m) do |m|
- css_class = case $1
- when 'CAUTION', 'IMPORTANT'
- 'warning'
- when 'TIP'
- 'info'
- else
- $1.downcase
- end
- %Q(
#{$2.strip}
)
- end
- end
-
- def plusplus(body)
- body.gsub!(/\+(.*?)\+/) do |m|
- "#{$1}"
- end
-
- # The real plus sign
- body.gsub!('', '+')
- end
-
- def brush_for(code_type)
- case code_type
- when 'ruby', 'sql', 'plain'
- code_type
- when 'erb'
- # TODO: fix mixing with html
- # 'ruby; html-script: true'
- 'ruby'
- when 'html'
- 'xml' # html is understood, but there are .xml rules in the CSS
- else
- 'plain'
- end
- end
-
- def code(body)
- body.gsub!(%r{<(yaml|shell|ruby|erb|html|sql|plain)>(.*?)\1>}m) do |m|
- <
-
-
-#{ERB::Util.h($2).strip}
-
-
-
-HTML
- end
- end
-
- def rails_mark(body)
- body.gsub!(/\(Rails(\d+)\)/m) do |m|
- %Q(Rails #{$1.strip.split(//).join "."})
- end
- end
-end
diff --git a/lib/tasks/deploy.rake b/lib/tasks/deploy.rake
new file mode 100644
index 00000000..b4bb3992
--- /dev/null
+++ b/lib/tasks/deploy.rake
@@ -0,0 +1,71 @@
+require 'git'
+
+namespace :deploy do
+ task start: %i[
+ production
+ clean_deploy_folder
+ assets:clobber
+ assets:precompile
+ copy_public
+ assets:clobber
+ static_docs:import
+ start_rails_server
+ generate_pages
+ stop_rails_server
+ commit_and_push
+ done
+ ]
+
+ task :production do
+ ENV['RAILS_ENV'] = 'production'
+ end
+
+ task :clean_deploy_folder do
+ FileUtils.rm_rf 'deploy' if File.exist? 'deploy'
+ end
+
+ task :copy_public do
+ FileUtils.cp_r 'public', 'deploy'
+ end
+
+ task start_rails_server: 'tmp:cache:clear' do
+ # `rails s -d` # TODO: doesn't work, probably some legacy setup, need to compare with new Rails app setup.
+ `rails s > /dev/null &`
+ puts 'waiting for server start'
+ sleep 10 # bootsnap
+ puts 'continue..'
+ end
+
+ task generate_pages: :environment do
+ Dir.chdir 'deploy' do
+ Page.find_each do |page|
+ File.open("#{page.path}.html", 'wb:UTF-8') do |file|
+ file << URI.open("http://localhost:3000/#{page.path}").read
+ end
+ end
+ File.open("search.html", 'wb:UTF-8') do |file|
+ file << URI.open("http://localhost:3000/search").read
+ end
+ end
+ end
+
+ task :stop_rails_server do
+ `cat tmp/pids/server.pid | xargs -I {} kill {}`
+ end
+
+ task :commit_and_push do
+ pages = '../rusrails.github.io'
+ git = Git.open(pages)
+ git.pull
+ git.remove('*', recursive: true)
+ FileUtils.cp_r 'deploy/.', pages
+ `echo 'rusrails.ru' >> ../rusrails.github.io/CNAME`
+ git.add(all: true)
+ git.commit("Generated version #{Time.now}")
+ git.push
+ end
+
+ task :done do
+ puts 'Done!'
+ end
+end
diff --git a/lib/tasks/docrails.rake b/lib/tasks/docrails.rake
new file mode 100644
index 00000000..b270c14d
--- /dev/null
+++ b/lib/tasks/docrails.rake
@@ -0,0 +1,105 @@
+require 'git'
+
+namespace :docrails do
+ desc 'Current status of translations'
+
+ task status: :environment do
+ docrails # pull
+
+ known_guides = (config['pages'] + config['plan'] + config['old']).map { |page| page['file'] }
+ all_guides = Dir["#{docrails_path}/guides/source/*.md"].map { |file| file[/[^\/]+\z/]}
+ new_guides = all_guides - known_guides
+ removed_guides = known_guides - all_guides
+
+ puts "New guides: #{new_guides.join(', ')}" if new_guides.present?
+ puts "Removed guides: #{removed_guides.join(', ')}" if removed_guides.present?
+
+ images_stat = docrails.diff(config['images']['revision']).path('guides/assets/images').stats
+ images_stat[:files].reject! { |file, _| file == 'guides/assets/images/favicon.ico' }
+ if images_stat[:files].present?
+ puts "Updated images:"
+ images_stat[:files].each { |file, _| puts " - %s" % file }
+ end
+
+ puts
+
+ stats = []
+
+ config['pages'].each do |page|
+ file = "guides/source/#{page['file']}"
+ stat = docrails.diff(page['revision']).path(file).stats
+ log = docrails.log(1).path(file).first
+ outdated = log.author_date.to_date - Date.strptime(page['date'], '%d/%m/%Y')
+ stats << page.merge(stat[:total])
+ .merge(objectish: log.objectish, new_date: log.author_date, outdated: outdated.to_i)
+ end
+
+ config['plan'].each do |page|
+ file = "guides/source/#{page['file']}"
+ stat = docrails.diff('4b825dc642cb6eb9a060e54bf8d69288fbee4904').path(file).stats
+ full_log = docrails.log.path(file)
+ log = full_log.first
+ init = full_log.last
+ stats << page.merge(stat[:total])
+ .merge(new: true, outdated: (Date.current - init.author_date.to_date).to_i)
+ .merge(objectish: log.objectish, new_date: log.author_date)
+ end
+
+ stats.sort_by! { |stat| stat[:lines] + stat[:outdated] }
+
+ stats.map do |stat|
+ score = stat[:lines] + stat[:outdated]
+ color = case
+ when stat[:new] then 34
+ when score < 0 then 37
+ when 0 === score then 90
+ when (1..200) === score then 32
+ when (201..400) === score then 33
+ when (401..700) === score then 31
+ else 91
+ end
+
+ puts "\e[%sm%s %55.55s: +/- %4s/%4s, outdated %4s days (%s %s)\e[0m" %
+ [color, stat[:new] ? '*' : ' ', stat['file'], stat[:insertions], stat[:deletions],
+ stat[:outdated], stat[:objectish], stat[:new_date].strftime('%d/%m/%Y')]
+ end
+ end
+
+ desc "make diff (use rake 'docrails:diff[file_name]' > diff.diff)"
+
+ task :diff, [:file_name] => :environment do |_, args|
+ page = config['pages'].detect { |page| page['file'] == args.file_name }
+ if page
+ file = "guides/source/#{page['file']}"
+ log = docrails.log(1).path(file).first
+ puts "-" * 80
+ puts " revision: #{log.objectish}"
+ puts " date: #{log.author_date.strftime('%d/%m/%Y')}"
+ puts "-" * 80
+ puts docrails.diff(page['revision']).path(file).first.patch
+ else
+ puts "Page #{args.file_name} not found!"
+ end
+ end
+
+ def docrails
+ @docrails ||= if Dir.exist?(docrails_path)
+ Git.open(docrails_path).tap do |git|
+ git.pull('origin', 'main')
+ rescue
+ puts 'Cannot access remote rails repo, using local copy'
+ end
+ else
+ Git.clone 'git@github.com:rails/rails.git', 'rails', path: docrails_path(false)
+ end
+ end
+
+ def docrails_path(inside = true)
+ path = ['tmp', inside ? 'rails' : nil].compact
+ Rails.root.join(*path)
+ end
+
+ def config
+ @config ||= YAML.load IO.read Rails.root.join 'source', 'index.yml'
+ end
+end
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 00000000..92bab9ce
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,3236 @@
+{
+ "name": "rusrails",
+ "version": "1.0.1",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "rusrails",
+ "version": "1.0.1",
+ "license": "CC BY-SA 4.0",
+ "devDependencies": {
+ "@cspell/dict-ru_ru": "latest",
+ "cspell": "latest"
+ }
+ },
+ "node_modules/@cspell/cspell-bundled-dicts": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.2.3.tgz",
+ "integrity": "sha512-AmKr/laSnmuTlECsIkf71N8FPd/ualJx13OdIJNIvUjIE741x/EACITIWLnTK9qFbsefOYp7bUeo9Xtbdw5JSA==",
+ "dev": true,
+ "dependencies": {
+ "@cspell/dict-ada": "^4.0.2",
+ "@cspell/dict-aws": "^4.0.1",
+ "@cspell/dict-bash": "^4.1.3",
+ "@cspell/dict-companies": "^3.0.28",
+ "@cspell/dict-cpp": "^5.0.10",
+ "@cspell/dict-cryptocurrencies": "^4.0.0",
+ "@cspell/dict-csharp": "^4.0.2",
+ "@cspell/dict-css": "^4.0.12",
+ "@cspell/dict-dart": "^2.0.3",
+ "@cspell/dict-django": "^4.1.0",
+ "@cspell/dict-docker": "^1.1.7",
+ "@cspell/dict-dotnet": "^5.0.0",
+ "@cspell/dict-elixir": "^4.0.3",
+ "@cspell/dict-en_us": "^4.3.12",
+ "@cspell/dict-en-common-misspellings": "^1.0.2",
+ "@cspell/dict-en-gb": "1.1.33",
+ "@cspell/dict-filetypes": "^3.0.3",
+ "@cspell/dict-fonts": "^4.0.0",
+ "@cspell/dict-fsharp": "^1.0.1",
+ "@cspell/dict-fullstack": "^3.1.5",
+ "@cspell/dict-gaming-terms": "^1.0.4",
+ "@cspell/dict-git": "^2.0.0",
+ "@cspell/dict-golang": "^6.0.5",
+ "@cspell/dict-haskell": "^4.0.1",
+ "@cspell/dict-html": "^4.0.5",
+ "@cspell/dict-html-symbol-entities": "^4.0.0",
+ "@cspell/dict-java": "^5.0.6",
+ "@cspell/dict-k8s": "^1.0.2",
+ "@cspell/dict-latex": "^4.0.0",
+ "@cspell/dict-lorem-ipsum": "^4.0.0",
+ "@cspell/dict-lua": "^4.0.3",
+ "@cspell/dict-makefile": "^1.0.0",
+ "@cspell/dict-node": "^4.0.3",
+ "@cspell/dict-npm": "^5.0.14",
+ "@cspell/dict-php": "^4.0.4",
+ "@cspell/dict-powershell": "^5.0.3",
+ "@cspell/dict-public-licenses": "^2.0.5",
+ "@cspell/dict-python": "^4.1.10",
+ "@cspell/dict-r": "^2.0.1",
+ "@cspell/dict-ruby": "^5.0.2",
+ "@cspell/dict-rust": "^4.0.1",
+ "@cspell/dict-scala": "^5.0.0",
+ "@cspell/dict-software-terms": "^3.3.14",
+ "@cspell/dict-sql": "^2.1.3",
+ "@cspell/dict-svelte": "^1.0.2",
+ "@cspell/dict-swift": "^2.0.1",
+ "@cspell/dict-typescript": "^3.1.2",
+ "@cspell/dict-vue": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@cspell/cspell-json-reporter": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.2.3.tgz",
+ "integrity": "sha512-603qzkEQZueKauvzCeAMKZqcTBEEJEfs3yBsDKx1jYqyMPuTXnh3vmxkPy0paiJuE625BjzlCuvok225u6x9Qw==",
+ "dev": true,
+ "dependencies": {
+ "@cspell/cspell-types": "8.2.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@cspell/cspell-pipe": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.2.3.tgz",
+ "integrity": "sha512-ga39z+K2ZaSQczaRayNUTrz10z7umEdFiK7AdWOQpGmym5JTtTK0ntnKvKKsdSJ9F5I7TZVxgZH6r4CCEPlEEg==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@cspell/cspell-resolver": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.2.3.tgz",
+ "integrity": "sha512-H0855Lg0DxWDcT0FtJyqLvUqOJuE1qSg9X3ENs/ltZntQeaU8wZc+B34bXJrGpJVMuiiqHp4w6rcNN3lsOcshQ==",
+ "dev": true,
+ "dependencies": {
+ "global-directory": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@cspell/cspell-service-bus": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.2.3.tgz",
+ "integrity": "sha512-hMLEzE2MkFir3kii046RecR1JAAfA6RQhLddjwQTq1c8YCWJ4lQEKUdM5x7nr/UpJtsMj8eYZ7CtbbnxQyn7Zg==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@cspell/cspell-types": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.2.3.tgz",
+ "integrity": "sha512-AZIC1n7veQSylp9ZAcVDvIaY+oS/vpzFNJ77rzuhEy/B6X/9jzeI8wg/+vWkmhO59q4iF/ZlswWK3UXfeSnUFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@cspell/dict-ada": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.0.2.tgz",
+ "integrity": "sha512-0kENOWQeHjUlfyId/aCM/mKXtkEgV0Zu2RhUXCBr4hHo9F9vph+Uu8Ww2b0i5a4ZixoIkudGA+eJvyxrG1jUpA==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-aws": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.1.tgz",
+ "integrity": "sha512-NXO+kTPQGqaaJKa4kO92NAXoqS+i99dQzf3/L1BxxWVSBS3/k1f3uhmqIh7Crb/n22W793lOm0D9x952BFga3Q==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-bash": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.1.3.tgz",
+ "integrity": "sha512-tOdI3QVJDbQSwPjUkOiQFhYcu2eedmX/PtEpVWg0aFps/r6AyjUQINtTgpqMYnYuq8O1QUIQqnpx21aovcgZCw==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-companies": {
+ "version": "3.0.29",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.0.29.tgz",
+ "integrity": "sha512-F/8XnkqjU7jmSDAcD3LSSX+WxCVUWPssqlO4lzGMIK3MNIUt+d48eSIt3pFAIB/Z9y0ojoLHUtWX9HJ1ZtGrXQ==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-cpp": {
+ "version": "5.0.10",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.0.10.tgz",
+ "integrity": "sha512-WCRuDrkFdpmeIR6uXQYKU9loMQKNFS4bUhtHdv5fu4qVyJSh3k/kgmtTm1h1BDTj8EwPRc/RGxS+9Z3b2mnabA==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-cryptocurrencies": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-4.0.0.tgz",
+ "integrity": "sha512-EiZp91ATyRxTmauIQfOX9adLYCunKjHEh092rrM7o2eMXP9n7zpXAL9BK7LviL+LbB8VDOm21q+s83cKrrRrsg==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-csharp": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.2.tgz",
+ "integrity": "sha512-1JMofhLK+4p4KairF75D3A924m5ERMgd1GvzhwK2geuYgd2ZKuGW72gvXpIV7aGf52E3Uu1kDXxxGAiZ5uVG7g==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-css": {
+ "version": "4.0.12",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.0.12.tgz",
+ "integrity": "sha512-vGBgPM92MkHQF5/2jsWcnaahOZ+C6OE/fPvd5ScBP72oFY9tn5GLuomcyO0z8vWCr2e0nUSX1OGimPtcQAlvSw==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-dart": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.0.3.tgz",
+ "integrity": "sha512-cLkwo1KT5CJY5N5RJVHks2genFkNCl/WLfj+0fFjqNR+tk3tBI1LY7ldr9piCtSFSm4x9pO1x6IV3kRUY1lLiw==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-data-science": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-1.0.11.tgz",
+ "integrity": "sha512-TaHAZRVe0Zlcc3C23StZqqbzC0NrodRwoSAc8dis+5qLeLLnOCtagYQeROQvDlcDg3X/VVEO9Whh4W/z4PAmYQ==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-django": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.1.0.tgz",
+ "integrity": "sha512-bKJ4gPyrf+1c78Z0Oc4trEB9MuhcB+Yg+uTTWsvhY6O2ncFYbB/LbEZfqhfmmuK/XJJixXfI1laF2zicyf+l0w==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-docker": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.7.tgz",
+ "integrity": "sha512-XlXHAr822euV36GGsl2J1CkBIVg3fZ6879ZOg5dxTIssuhUOCiV2BuzKZmt6aIFmcdPmR14+9i9Xq+3zuxeX0A==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-dotnet": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.0.tgz",
+ "integrity": "sha512-EOwGd533v47aP5QYV8GlSSKkmM9Eq8P3G/eBzSpH3Nl2+IneDOYOBLEUraHuiCtnOkNsz0xtZHArYhAB2bHWAw==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-elixir": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.3.tgz",
+ "integrity": "sha512-g+uKLWvOp9IEZvrIvBPTr/oaO6619uH/wyqypqvwpmnmpjcfi8+/hqZH8YNKt15oviK8k4CkINIqNhyndG9d9Q==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-en_us": {
+ "version": "4.3.12",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.12.tgz",
+ "integrity": "sha512-1bsUxFjgxF30FTzcU5uvmCvH3lyqVKR9dbwsJhomBlUM97f0edrd6590SiYBXDm7ruE68m3lJd4vs0Ev2D6FtQ==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-en-common-misspellings": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-1.0.2.tgz",
+ "integrity": "sha512-jg7ZQZpZH7+aAxNBlcAG4tGhYF6Ksy+QS5Df73Oo+XyckBjC9QS+PrRwLTeYoFIgXy5j3ICParK5r3MSSoL4gw==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-en-gb": {
+ "version": "1.1.33",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb/-/dict-en-gb-1.1.33.tgz",
+ "integrity": "sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-filetypes": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.3.tgz",
+ "integrity": "sha512-J9UP+qwwBLfOQ8Qg9tAsKtSY/WWmjj21uj6zXTI9hRLD1eG1uUOLcfVovAmtmVqUWziPSKMr87F6SXI3xmJXgw==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-fonts": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-4.0.0.tgz",
+ "integrity": "sha512-t9V4GeN/m517UZn63kZPUYP3OQg5f0OBLSd3Md5CU3eH1IFogSvTzHHnz4Wqqbv8NNRiBZ3HfdY/pqREZ6br3Q==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-fsharp": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-fsharp/-/dict-fsharp-1.0.1.tgz",
+ "integrity": "sha512-23xyPcD+j+NnqOjRHgW3IU7Li912SX9wmeefcY0QxukbAxJ/vAN4rBpjSwwYZeQPAn3fxdfdNZs03fg+UM+4yQ==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-fullstack": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.1.5.tgz",
+ "integrity": "sha512-6ppvo1dkXUZ3fbYn/wwzERxCa76RtDDl5Afzv2lijLoijGGUw5yYdLBKJnx8PJBGNLh829X352ftE7BElG4leA==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-gaming-terms": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.0.4.tgz",
+ "integrity": "sha512-hbDduNXlk4AOY0wFxcDMWBPpm34rpqJBeqaySeoUH70eKxpxm+dvjpoRLJgyu0TmymEICCQSl6lAHTHSDiWKZg==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-git": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-2.0.0.tgz",
+ "integrity": "sha512-n1AxyX5Kgxij/sZFkxFJlzn3K9y/sCcgVPg/vz4WNJ4K9YeTsUmyGLA2OQI7d10GJeiuAo2AP1iZf2A8j9aj2w==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-golang": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.5.tgz",
+ "integrity": "sha512-w4mEqGz4/wV+BBljLxduFNkMrd3rstBNDXmoX5kD4UTzIb4Sy0QybWCtg2iVT+R0KWiRRA56QKOvBsgXiddksA==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-haskell": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.1.tgz",
+ "integrity": "sha512-uRrl65mGrOmwT7NxspB4xKXFUenNC7IikmpRZW8Uzqbqcu7ZRCUfstuVH7T1rmjRgRkjcIjE4PC11luDou4wEQ==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-html": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.5.tgz",
+ "integrity": "sha512-p0brEnRybzSSWi8sGbuVEf7jSTDmXPx7XhQUb5bgG6b54uj+Z0Qf0V2n8b/LWwIPJNd1GygaO9l8k3HTCy1h4w==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-html-symbol-entities": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.0.tgz",
+ "integrity": "sha512-HGRu+48ErJjoweR5IbcixxETRewrBb0uxQBd6xFGcxbEYCX8CnQFTAmKI5xNaIt2PKaZiJH3ijodGSqbKdsxhw==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-java": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-5.0.6.tgz",
+ "integrity": "sha512-kdE4AHHHrixyZ5p6zyms1SLoYpaJarPxrz8Tveo6gddszBVVwIUZ+JkQE1bWNLK740GWzIXdkznpUfw1hP9nXw==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-k8s": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.2.tgz",
+ "integrity": "sha512-tLT7gZpNPnGa+IIFvK9SP1LrSpPpJ94a/DulzAPOb1Q2UBFwdpFd82UWhio0RNShduvKG/WiMZf/wGl98pn+VQ==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-latex": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-4.0.0.tgz",
+ "integrity": "sha512-LPY4y6D5oI7D3d+5JMJHK/wxYTQa2lJMSNxps2JtuF8hbAnBQb3igoWEjEbIbRRH1XBM0X8dQqemnjQNCiAtxQ==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-lorem-ipsum": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-4.0.0.tgz",
+ "integrity": "sha512-1l3yjfNvMzZPibW8A7mQU4kTozwVZVw0AvFEdy+NcqtbxH+TvbSkNMqROOFWrkD2PjnKG0+Ea0tHI2Pi6Gchnw==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-lua": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.3.tgz",
+ "integrity": "sha512-lDHKjsrrbqPaea13+G9s0rtXjMO06gPXPYRjRYawbNmo4E/e3XFfVzeci3OQDQNDmf2cPOwt9Ef5lu2lDmwfJg==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-makefile": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-makefile/-/dict-makefile-1.0.0.tgz",
+ "integrity": "sha512-3W9tHPcSbJa6s0bcqWo6VisEDTSN5zOtDbnPabF7rbyjRpNo0uHXHRJQF8gAbFzoTzBBhgkTmrfSiuyQm7vBUQ==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-node": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-4.0.3.tgz",
+ "integrity": "sha512-sFlUNI5kOogy49KtPg8SMQYirDGIAoKBO3+cDLIwD4MLdsWy1q0upc7pzGht3mrjuyMiPRUV14Bb0rkVLrxOhg==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-npm": {
+ "version": "5.0.14",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.0.14.tgz",
+ "integrity": "sha512-k0kC7/W2qG5YII+SW6s+JtvKrkZg651vizi5dv/5G2HmJaeLNgDqBVeeDk/uV+ntBorM66XG4BPMjSxoaIlC5w==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-php": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.5.tgz",
+ "integrity": "sha512-9r8ao7Z/mH9Z8pSB7yLtyvcCJWw+/MnQpj7xGVYzIV7V2ZWDRjXZAMgteHMJ37m8oYz64q5d4tiipD300QSetQ==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-powershell": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.3.tgz",
+ "integrity": "sha512-lEdzrcyau6mgzu1ie98GjOEegwVHvoaWtzQnm1ie4DyZgMr+N6D0Iyj1lzvtmt0snvsDFa5F2bsYzf3IMKcpcA==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-public-licenses": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.5.tgz",
+ "integrity": "sha512-91HK4dSRri/HqzAypHgduRMarJAleOX5NugoI8SjDLPzWYkwZ1ftuCXSk+fy8DLc3wK7iOaFcZAvbjmnLhVs4A==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-python": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.1.11.tgz",
+ "integrity": "sha512-XG+v3PumfzUW38huSbfT15Vqt3ihNb462ulfXifpQllPok5OWynhszCLCRQjQReV+dgz784ST4ggRxW452/kVg==",
+ "dev": true,
+ "dependencies": {
+ "@cspell/dict-data-science": "^1.0.11"
+ }
+ },
+ "node_modules/@cspell/dict-r": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.0.1.tgz",
+ "integrity": "sha512-KCmKaeYMLm2Ip79mlYPc8p+B2uzwBp4KMkzeLd5E6jUlCL93Y5Nvq68wV5fRLDRTf7N1LvofkVFWfDcednFOgA==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-ru_ru": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-ru_ru/-/dict-ru_ru-2.2.0.tgz",
+ "integrity": "sha512-RpEYhY+GbD6TL26y1YC8sPdxpxuCFuzkqfILOtaflL0EFFZRODbvtXW7umjP6QjfxbLSbyMWCTnkZCZzFFFnTw==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-ruby": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.2.tgz",
+ "integrity": "sha512-cIh8KTjpldzFzKGgrqUX4bFyav5lC52hXDKo4LbRuMVncs3zg4hcSf4HtURY+f2AfEZzN6ZKzXafQpThq3dl2g==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-rust": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.1.tgz",
+ "integrity": "sha512-xJSSzHDK2z6lSVaOmMxl3PTOtfoffaxMo7fTcbZUF+SCJzfKbO6vnN9TCGX2sx1RHFDz66Js6goz6SAZQdOwaw==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-scala": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.0.tgz",
+ "integrity": "sha512-ph0twaRoV+ylui022clEO1dZ35QbeEQaKTaV2sPOsdwIokABPIiK09oWwGK9qg7jRGQwVaRPEq0Vp+IG1GpqSQ==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-software-terms": {
+ "version": "3.3.15",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-3.3.15.tgz",
+ "integrity": "sha512-1qqMGFi1TUNq9gQj4FTLPTlqVzQLXrj80MsKoXVpysr+823kMWesQAjqHiPg+MYsQ3DlTcpGWcjq/EbYonqueQ==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-sql": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.1.3.tgz",
+ "integrity": "sha512-SEyTNKJrjqD6PAzZ9WpdSu6P7wgdNtGV2RV8Kpuw1x6bV+YsSptuClYG+JSdRExBTE6LwIe1bTklejUp3ZP8TQ==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-svelte": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.2.tgz",
+ "integrity": "sha512-rPJmnn/GsDs0btNvrRBciOhngKV98yZ9SHmg8qI6HLS8hZKvcXc0LMsf9LLuMK1TmS2+WQFAan6qeqg6bBxL2Q==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-swift": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.1.tgz",
+ "integrity": "sha512-gxrCMUOndOk7xZFmXNtkCEeroZRnS2VbeaIPiymGRHj5H+qfTAzAKxtv7jJbVA3YYvEzWcVE2oKDP4wcbhIERw==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-typescript": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.1.2.tgz",
+ "integrity": "sha512-lcNOYWjLUvDZdLa0UMNd/LwfVdxhE9rKA+agZBGjL3lTA3uNvH7IUqSJM/IXhJoBpLLMVEOk8v1N9xi+vDuCdA==",
+ "dev": true
+ },
+ "node_modules/@cspell/dict-vue": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.0.tgz",
+ "integrity": "sha512-niiEMPWPV9IeRBRzZ0TBZmNnkK3olkOPYxC1Ny2AX4TGlYRajcW0WUtoSHmvvjZNfWLSg2L6ruiBeuPSbjnG6A==",
+ "dev": true
+ },
+ "node_modules/@cspell/dynamic-import": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.2.3.tgz",
+ "integrity": "sha512-udJF+88F4UMH2eVKe3Utsh4X1PyNwqPJclIeD3/MDMFWm16lLkFYMqqrdr51tNLKVi4cXceGrUEapmGwf87l/w==",
+ "dev": true,
+ "dependencies": {
+ "import-meta-resolve": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=18.0"
+ }
+ },
+ "node_modules/@cspell/strong-weak-map": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.2.3.tgz",
+ "integrity": "sha512-/0gQZw87MqGX8f28E+LhFfrsWdRdQEL8EEQeMXrrzSoPnfSz+ItHMhhrwPF+bMePPjaaUNYoRXvX7hxiDsGm0w==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/array-timsort": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz",
+ "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==",
+ "dev": true
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+ "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+ "dev": true,
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chalk-template": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-1.1.0.tgz",
+ "integrity": "sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk-template?sponsor=1"
+ }
+ },
+ "node_modules/clear-module": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/clear-module/-/clear-module-4.1.2.tgz",
+ "integrity": "sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^2.0.0",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/commander": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
+ "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/comment-json": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.3.tgz",
+ "integrity": "sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==",
+ "dev": true,
+ "dependencies": {
+ "array-timsort": "^1.0.3",
+ "core-util-is": "^1.0.3",
+ "esprima": "^4.0.1",
+ "has-own-prop": "^2.0.0",
+ "repeat-string": "^1.6.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/configstore": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz",
+ "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==",
+ "dev": true,
+ "dependencies": {
+ "dot-prop": "^6.0.1",
+ "graceful-fs": "^4.2.6",
+ "unique-string": "^3.0.0",
+ "write-file-atomic": "^3.0.3",
+ "xdg-basedir": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/yeoman/configstore?sponsor=1"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/crypto-random-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz",
+ "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cspell": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.2.3.tgz",
+ "integrity": "sha512-lJEIglmBINLW4Jwn+5W1k6Zb5EjyRFLnTvc1uQ268/9pcsB+GWUZruplIe5+erR3AxZ+N7Tqp7IY9j2Jf1+/Fg==",
+ "dev": true,
+ "dependencies": {
+ "@cspell/cspell-json-reporter": "8.2.3",
+ "@cspell/cspell-pipe": "8.2.3",
+ "@cspell/cspell-types": "8.2.3",
+ "@cspell/dynamic-import": "8.2.3",
+ "chalk": "^5.3.0",
+ "chalk-template": "^1.1.0",
+ "commander": "^11.1.0",
+ "cspell-gitignore": "8.2.3",
+ "cspell-glob": "8.2.3",
+ "cspell-io": "8.2.3",
+ "cspell-lib": "8.2.3",
+ "fast-glob": "^3.3.2",
+ "fast-json-stable-stringify": "^2.1.0",
+ "file-entry-cache": "^8.0.0",
+ "get-stdin": "^9.0.0",
+ "semver": "^7.5.4",
+ "strip-ansi": "^7.1.0",
+ "vscode-uri": "^3.0.8"
+ },
+ "bin": {
+ "cspell": "bin.mjs",
+ "cspell-esm": "bin.mjs"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/streetsidesoftware/cspell?sponsor=1"
+ }
+ },
+ "node_modules/cspell-config-lib": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.2.3.tgz",
+ "integrity": "sha512-ATbOR06GKBIFM5SPKMF4fgo5G2qmOfdV8TbpyzNtw1AGL7PoOgDNFiKSutEzO5EHyZuXE71ZFxH3rVr2gIV7Dw==",
+ "dev": true,
+ "dependencies": {
+ "@cspell/cspell-types": "8.2.3",
+ "comment-json": "^4.2.3",
+ "yaml": "^2.3.4"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/cspell-dictionary": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.2.3.tgz",
+ "integrity": "sha512-M/idc3TLjYMpT4+8PlIg7kzoeGkR7o6h6pTwRfy/ZkBkEaV+U/35ZtVLO4qjxnuX6wrmawYmHhYqgzyKLEJIhw==",
+ "dev": true,
+ "dependencies": {
+ "@cspell/cspell-pipe": "8.2.3",
+ "@cspell/cspell-types": "8.2.3",
+ "cspell-trie-lib": "8.2.3",
+ "fast-equals": "^5.0.1",
+ "gensequence": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/cspell-gitignore": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.2.3.tgz",
+ "integrity": "sha512-tPUI+Aoq1b1shD04CLprrS8wEriiF4G1J+qBiCZK2KWOh6IcufuuDhP1Jtkzz9uONgGWFPF6jj/9TXRFlQexbQ==",
+ "dev": true,
+ "dependencies": {
+ "cspell-glob": "8.2.3",
+ "find-up-simple": "^1.0.0"
+ },
+ "bin": {
+ "cspell-gitignore": "bin.mjs"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/cspell-glob": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.2.3.tgz",
+ "integrity": "sha512-byP2kBblO5d9rZr73MPor+KfoFdry4uu/MQmwLiK5mxgmokZYv5GVDX2DrO16Ni4yJ6/2rBPWLfq+DfCXSWqyw==",
+ "dev": true,
+ "dependencies": {
+ "micromatch": "^4.0.5"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/cspell-grammar": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.2.3.tgz",
+ "integrity": "sha512-z57Qyu24BsHHp/nZ9ftN377cSCgSJg+6oywIglau7ws7vRpUgYKVoKxn+ZJfOrIZpXfZUqgph5IwAGFI+aRN6w==",
+ "dev": true,
+ "dependencies": {
+ "@cspell/cspell-pipe": "8.2.3",
+ "@cspell/cspell-types": "8.2.3"
+ },
+ "bin": {
+ "cspell-grammar": "bin.mjs"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/cspell-io": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.2.3.tgz",
+ "integrity": "sha512-mPbLXiIje9chncy/Xb9C6AxqjJm9AFHz/nmIIP5bc6gd4w/yaGlQNyO8jjHF1u2JBVbIxPQSMjFgEuqasPy4Sg==",
+ "dev": true,
+ "dependencies": {
+ "@cspell/cspell-service-bus": "8.2.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/cspell-lib": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.2.3.tgz",
+ "integrity": "sha512-NA4FsGomGPNp15TWbXx13bfknLGU8B66j0QlU3i4oDrWBj/t5m7O1nmiQqcaDSKd9s5HtdTHfxLc83hdzmmizg==",
+ "dev": true,
+ "dependencies": {
+ "@cspell/cspell-bundled-dicts": "8.2.3",
+ "@cspell/cspell-pipe": "8.2.3",
+ "@cspell/cspell-resolver": "8.2.3",
+ "@cspell/cspell-types": "8.2.3",
+ "@cspell/dynamic-import": "8.2.3",
+ "@cspell/strong-weak-map": "8.2.3",
+ "clear-module": "^4.1.2",
+ "comment-json": "^4.2.3",
+ "configstore": "^6.0.0",
+ "cspell-config-lib": "8.2.3",
+ "cspell-dictionary": "8.2.3",
+ "cspell-glob": "8.2.3",
+ "cspell-grammar": "8.2.3",
+ "cspell-io": "8.2.3",
+ "cspell-trie-lib": "8.2.3",
+ "fast-equals": "^5.0.1",
+ "gensequence": "^6.0.0",
+ "import-fresh": "^3.3.0",
+ "resolve-from": "^5.0.0",
+ "vscode-languageserver-textdocument": "^1.0.11",
+ "vscode-uri": "^3.0.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/cspell-trie-lib": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.2.3.tgz",
+ "integrity": "sha512-yN2PwceN9ViCjXUhhi3MTWfi15Rpc9CsSFFPV3A6cOWoB0qBnuTXk8hBSx+427UGYjtlXPP6EZKY8w8OK6PweA==",
+ "dev": true,
+ "dependencies": {
+ "@cspell/cspell-pipe": "8.2.3",
+ "@cspell/cspell-types": "8.2.3",
+ "gensequence": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/dot-prop": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz",
+ "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
+ "dev": true,
+ "dependencies": {
+ "is-obj": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/fast-equals": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz",
+ "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz",
+ "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up-simple": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz",
+ "integrity": "sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.0.tgz",
+ "integrity": "sha512-EryKbCE/wxpxKniQlyas6PY1I9vwtF3uCBweX+N8KYTCn3Y12RTGtQAJ/bd5pl7kxUAc8v/R3Ake/N17OZiFqA==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4",
+ "rimraf": "^5.0.5"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.2.9",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
+ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
+ "dev": true
+ },
+ "node_modules/foreground-child": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
+ "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/gensequence": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/gensequence/-/gensequence-6.0.0.tgz",
+ "integrity": "sha512-8WwuywE9pokJRAcg2QFR/plk3cVPebSUqRPzpGQh3WQ0wIiHAw+HyOQj5IuHyUTQBHpBKFoB2JUMu9zT3vJ16Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/get-stdin": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz",
+ "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/glob": {
+ "version": "10.3.10",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
+ "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+ "dev": true,
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.5",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/global-directory": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz",
+ "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==",
+ "dev": true,
+ "dependencies": {
+ "ini": "4.1.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true
+ },
+ "node_modules/has-own-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz",
+ "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-fresh/node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/import-fresh/node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/import-meta-resolve": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz",
+ "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/ini": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz",
+ "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-obj": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
+ "dev": true
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/jackspeak": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
+ "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+ "dev": true,
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz",
+ "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==",
+ "dev": true,
+ "engines": {
+ "node": "14 || >=16.14"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
+ "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-2.0.0.tgz",
+ "integrity": "sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-scurry": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
+ "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^9.1.1 || ^10.0.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz",
+ "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^10.3.7"
+ },
+ "bin": {
+ "rimraf": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/string-width-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
+ "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typedarray-to-buffer": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+ "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+ "dev": true,
+ "dependencies": {
+ "is-typedarray": "^1.0.0"
+ }
+ },
+ "node_modules/unique-string": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz",
+ "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==",
+ "dev": true,
+ "dependencies": {
+ "crypto-random-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/vscode-languageserver-textdocument": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz",
+ "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==",
+ "dev": true
+ },
+ "node_modules/vscode-uri": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz",
+ "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==",
+ "dev": true
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/write-file-atomic": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+ "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+ "dev": true,
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "is-typedarray": "^1.0.0",
+ "signal-exit": "^3.0.2",
+ "typedarray-to-buffer": "^3.1.5"
+ }
+ },
+ "node_modules/write-file-atomic/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "node_modules/xdg-basedir": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz",
+ "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/yaml": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz",
+ "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 14"
+ }
+ }
+ },
+ "dependencies": {
+ "@cspell/cspell-bundled-dicts": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.2.3.tgz",
+ "integrity": "sha512-AmKr/laSnmuTlECsIkf71N8FPd/ualJx13OdIJNIvUjIE741x/EACITIWLnTK9qFbsefOYp7bUeo9Xtbdw5JSA==",
+ "dev": true,
+ "requires": {
+ "@cspell/dict-ada": "^4.0.2",
+ "@cspell/dict-aws": "^4.0.1",
+ "@cspell/dict-bash": "^4.1.3",
+ "@cspell/dict-companies": "^3.0.28",
+ "@cspell/dict-cpp": "^5.0.10",
+ "@cspell/dict-cryptocurrencies": "^4.0.0",
+ "@cspell/dict-csharp": "^4.0.2",
+ "@cspell/dict-css": "^4.0.12",
+ "@cspell/dict-dart": "^2.0.3",
+ "@cspell/dict-django": "^4.1.0",
+ "@cspell/dict-docker": "^1.1.7",
+ "@cspell/dict-dotnet": "^5.0.0",
+ "@cspell/dict-elixir": "^4.0.3",
+ "@cspell/dict-en_us": "^4.3.12",
+ "@cspell/dict-en-common-misspellings": "^1.0.2",
+ "@cspell/dict-en-gb": "1.1.33",
+ "@cspell/dict-filetypes": "^3.0.3",
+ "@cspell/dict-fonts": "^4.0.0",
+ "@cspell/dict-fsharp": "^1.0.1",
+ "@cspell/dict-fullstack": "^3.1.5",
+ "@cspell/dict-gaming-terms": "^1.0.4",
+ "@cspell/dict-git": "^2.0.0",
+ "@cspell/dict-golang": "^6.0.5",
+ "@cspell/dict-haskell": "^4.0.1",
+ "@cspell/dict-html": "^4.0.5",
+ "@cspell/dict-html-symbol-entities": "^4.0.0",
+ "@cspell/dict-java": "^5.0.6",
+ "@cspell/dict-k8s": "^1.0.2",
+ "@cspell/dict-latex": "^4.0.0",
+ "@cspell/dict-lorem-ipsum": "^4.0.0",
+ "@cspell/dict-lua": "^4.0.3",
+ "@cspell/dict-makefile": "^1.0.0",
+ "@cspell/dict-node": "^4.0.3",
+ "@cspell/dict-npm": "^5.0.14",
+ "@cspell/dict-php": "^4.0.4",
+ "@cspell/dict-powershell": "^5.0.3",
+ "@cspell/dict-public-licenses": "^2.0.5",
+ "@cspell/dict-python": "^4.1.10",
+ "@cspell/dict-r": "^2.0.1",
+ "@cspell/dict-ruby": "^5.0.2",
+ "@cspell/dict-rust": "^4.0.1",
+ "@cspell/dict-scala": "^5.0.0",
+ "@cspell/dict-software-terms": "^3.3.14",
+ "@cspell/dict-sql": "^2.1.3",
+ "@cspell/dict-svelte": "^1.0.2",
+ "@cspell/dict-swift": "^2.0.1",
+ "@cspell/dict-typescript": "^3.1.2",
+ "@cspell/dict-vue": "^3.0.0"
+ }
+ },
+ "@cspell/cspell-json-reporter": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.2.3.tgz",
+ "integrity": "sha512-603qzkEQZueKauvzCeAMKZqcTBEEJEfs3yBsDKx1jYqyMPuTXnh3vmxkPy0paiJuE625BjzlCuvok225u6x9Qw==",
+ "dev": true,
+ "requires": {
+ "@cspell/cspell-types": "8.2.3"
+ }
+ },
+ "@cspell/cspell-pipe": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.2.3.tgz",
+ "integrity": "sha512-ga39z+K2ZaSQczaRayNUTrz10z7umEdFiK7AdWOQpGmym5JTtTK0ntnKvKKsdSJ9F5I7TZVxgZH6r4CCEPlEEg==",
+ "dev": true
+ },
+ "@cspell/cspell-resolver": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.2.3.tgz",
+ "integrity": "sha512-H0855Lg0DxWDcT0FtJyqLvUqOJuE1qSg9X3ENs/ltZntQeaU8wZc+B34bXJrGpJVMuiiqHp4w6rcNN3lsOcshQ==",
+ "dev": true,
+ "requires": {
+ "global-directory": "^4.0.1"
+ }
+ },
+ "@cspell/cspell-service-bus": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.2.3.tgz",
+ "integrity": "sha512-hMLEzE2MkFir3kii046RecR1JAAfA6RQhLddjwQTq1c8YCWJ4lQEKUdM5x7nr/UpJtsMj8eYZ7CtbbnxQyn7Zg==",
+ "dev": true
+ },
+ "@cspell/cspell-types": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.2.3.tgz",
+ "integrity": "sha512-AZIC1n7veQSylp9ZAcVDvIaY+oS/vpzFNJ77rzuhEy/B6X/9jzeI8wg/+vWkmhO59q4iF/ZlswWK3UXfeSnUFg==",
+ "dev": true
+ },
+ "@cspell/dict-ada": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.0.2.tgz",
+ "integrity": "sha512-0kENOWQeHjUlfyId/aCM/mKXtkEgV0Zu2RhUXCBr4hHo9F9vph+Uu8Ww2b0i5a4ZixoIkudGA+eJvyxrG1jUpA==",
+ "dev": true
+ },
+ "@cspell/dict-aws": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.1.tgz",
+ "integrity": "sha512-NXO+kTPQGqaaJKa4kO92NAXoqS+i99dQzf3/L1BxxWVSBS3/k1f3uhmqIh7Crb/n22W793lOm0D9x952BFga3Q==",
+ "dev": true
+ },
+ "@cspell/dict-bash": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.1.3.tgz",
+ "integrity": "sha512-tOdI3QVJDbQSwPjUkOiQFhYcu2eedmX/PtEpVWg0aFps/r6AyjUQINtTgpqMYnYuq8O1QUIQqnpx21aovcgZCw==",
+ "dev": true
+ },
+ "@cspell/dict-companies": {
+ "version": "3.0.29",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.0.29.tgz",
+ "integrity": "sha512-F/8XnkqjU7jmSDAcD3LSSX+WxCVUWPssqlO4lzGMIK3MNIUt+d48eSIt3pFAIB/Z9y0ojoLHUtWX9HJ1ZtGrXQ==",
+ "dev": true
+ },
+ "@cspell/dict-cpp": {
+ "version": "5.0.10",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.0.10.tgz",
+ "integrity": "sha512-WCRuDrkFdpmeIR6uXQYKU9loMQKNFS4bUhtHdv5fu4qVyJSh3k/kgmtTm1h1BDTj8EwPRc/RGxS+9Z3b2mnabA==",
+ "dev": true
+ },
+ "@cspell/dict-cryptocurrencies": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-4.0.0.tgz",
+ "integrity": "sha512-EiZp91ATyRxTmauIQfOX9adLYCunKjHEh092rrM7o2eMXP9n7zpXAL9BK7LviL+LbB8VDOm21q+s83cKrrRrsg==",
+ "dev": true
+ },
+ "@cspell/dict-csharp": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.2.tgz",
+ "integrity": "sha512-1JMofhLK+4p4KairF75D3A924m5ERMgd1GvzhwK2geuYgd2ZKuGW72gvXpIV7aGf52E3Uu1kDXxxGAiZ5uVG7g==",
+ "dev": true
+ },
+ "@cspell/dict-css": {
+ "version": "4.0.12",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.0.12.tgz",
+ "integrity": "sha512-vGBgPM92MkHQF5/2jsWcnaahOZ+C6OE/fPvd5ScBP72oFY9tn5GLuomcyO0z8vWCr2e0nUSX1OGimPtcQAlvSw==",
+ "dev": true
+ },
+ "@cspell/dict-dart": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.0.3.tgz",
+ "integrity": "sha512-cLkwo1KT5CJY5N5RJVHks2genFkNCl/WLfj+0fFjqNR+tk3tBI1LY7ldr9piCtSFSm4x9pO1x6IV3kRUY1lLiw==",
+ "dev": true
+ },
+ "@cspell/dict-data-science": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-1.0.11.tgz",
+ "integrity": "sha512-TaHAZRVe0Zlcc3C23StZqqbzC0NrodRwoSAc8dis+5qLeLLnOCtagYQeROQvDlcDg3X/VVEO9Whh4W/z4PAmYQ==",
+ "dev": true
+ },
+ "@cspell/dict-django": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.1.0.tgz",
+ "integrity": "sha512-bKJ4gPyrf+1c78Z0Oc4trEB9MuhcB+Yg+uTTWsvhY6O2ncFYbB/LbEZfqhfmmuK/XJJixXfI1laF2zicyf+l0w==",
+ "dev": true
+ },
+ "@cspell/dict-docker": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.7.tgz",
+ "integrity": "sha512-XlXHAr822euV36GGsl2J1CkBIVg3fZ6879ZOg5dxTIssuhUOCiV2BuzKZmt6aIFmcdPmR14+9i9Xq+3zuxeX0A==",
+ "dev": true
+ },
+ "@cspell/dict-dotnet": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.0.tgz",
+ "integrity": "sha512-EOwGd533v47aP5QYV8GlSSKkmM9Eq8P3G/eBzSpH3Nl2+IneDOYOBLEUraHuiCtnOkNsz0xtZHArYhAB2bHWAw==",
+ "dev": true
+ },
+ "@cspell/dict-elixir": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.3.tgz",
+ "integrity": "sha512-g+uKLWvOp9IEZvrIvBPTr/oaO6619uH/wyqypqvwpmnmpjcfi8+/hqZH8YNKt15oviK8k4CkINIqNhyndG9d9Q==",
+ "dev": true
+ },
+ "@cspell/dict-en_us": {
+ "version": "4.3.12",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.12.tgz",
+ "integrity": "sha512-1bsUxFjgxF30FTzcU5uvmCvH3lyqVKR9dbwsJhomBlUM97f0edrd6590SiYBXDm7ruE68m3lJd4vs0Ev2D6FtQ==",
+ "dev": true
+ },
+ "@cspell/dict-en-common-misspellings": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-1.0.2.tgz",
+ "integrity": "sha512-jg7ZQZpZH7+aAxNBlcAG4tGhYF6Ksy+QS5Df73Oo+XyckBjC9QS+PrRwLTeYoFIgXy5j3ICParK5r3MSSoL4gw==",
+ "dev": true
+ },
+ "@cspell/dict-en-gb": {
+ "version": "1.1.33",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb/-/dict-en-gb-1.1.33.tgz",
+ "integrity": "sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==",
+ "dev": true
+ },
+ "@cspell/dict-filetypes": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.3.tgz",
+ "integrity": "sha512-J9UP+qwwBLfOQ8Qg9tAsKtSY/WWmjj21uj6zXTI9hRLD1eG1uUOLcfVovAmtmVqUWziPSKMr87F6SXI3xmJXgw==",
+ "dev": true
+ },
+ "@cspell/dict-fonts": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-4.0.0.tgz",
+ "integrity": "sha512-t9V4GeN/m517UZn63kZPUYP3OQg5f0OBLSd3Md5CU3eH1IFogSvTzHHnz4Wqqbv8NNRiBZ3HfdY/pqREZ6br3Q==",
+ "dev": true
+ },
+ "@cspell/dict-fsharp": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-fsharp/-/dict-fsharp-1.0.1.tgz",
+ "integrity": "sha512-23xyPcD+j+NnqOjRHgW3IU7Li912SX9wmeefcY0QxukbAxJ/vAN4rBpjSwwYZeQPAn3fxdfdNZs03fg+UM+4yQ==",
+ "dev": true
+ },
+ "@cspell/dict-fullstack": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.1.5.tgz",
+ "integrity": "sha512-6ppvo1dkXUZ3fbYn/wwzERxCa76RtDDl5Afzv2lijLoijGGUw5yYdLBKJnx8PJBGNLh829X352ftE7BElG4leA==",
+ "dev": true
+ },
+ "@cspell/dict-gaming-terms": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.0.4.tgz",
+ "integrity": "sha512-hbDduNXlk4AOY0wFxcDMWBPpm34rpqJBeqaySeoUH70eKxpxm+dvjpoRLJgyu0TmymEICCQSl6lAHTHSDiWKZg==",
+ "dev": true
+ },
+ "@cspell/dict-git": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-2.0.0.tgz",
+ "integrity": "sha512-n1AxyX5Kgxij/sZFkxFJlzn3K9y/sCcgVPg/vz4WNJ4K9YeTsUmyGLA2OQI7d10GJeiuAo2AP1iZf2A8j9aj2w==",
+ "dev": true
+ },
+ "@cspell/dict-golang": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.5.tgz",
+ "integrity": "sha512-w4mEqGz4/wV+BBljLxduFNkMrd3rstBNDXmoX5kD4UTzIb4Sy0QybWCtg2iVT+R0KWiRRA56QKOvBsgXiddksA==",
+ "dev": true
+ },
+ "@cspell/dict-haskell": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.1.tgz",
+ "integrity": "sha512-uRrl65mGrOmwT7NxspB4xKXFUenNC7IikmpRZW8Uzqbqcu7ZRCUfstuVH7T1rmjRgRkjcIjE4PC11luDou4wEQ==",
+ "dev": true
+ },
+ "@cspell/dict-html": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.5.tgz",
+ "integrity": "sha512-p0brEnRybzSSWi8sGbuVEf7jSTDmXPx7XhQUb5bgG6b54uj+Z0Qf0V2n8b/LWwIPJNd1GygaO9l8k3HTCy1h4w==",
+ "dev": true
+ },
+ "@cspell/dict-html-symbol-entities": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.0.tgz",
+ "integrity": "sha512-HGRu+48ErJjoweR5IbcixxETRewrBb0uxQBd6xFGcxbEYCX8CnQFTAmKI5xNaIt2PKaZiJH3ijodGSqbKdsxhw==",
+ "dev": true
+ },
+ "@cspell/dict-java": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-5.0.6.tgz",
+ "integrity": "sha512-kdE4AHHHrixyZ5p6zyms1SLoYpaJarPxrz8Tveo6gddszBVVwIUZ+JkQE1bWNLK740GWzIXdkznpUfw1hP9nXw==",
+ "dev": true
+ },
+ "@cspell/dict-k8s": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.2.tgz",
+ "integrity": "sha512-tLT7gZpNPnGa+IIFvK9SP1LrSpPpJ94a/DulzAPOb1Q2UBFwdpFd82UWhio0RNShduvKG/WiMZf/wGl98pn+VQ==",
+ "dev": true
+ },
+ "@cspell/dict-latex": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-4.0.0.tgz",
+ "integrity": "sha512-LPY4y6D5oI7D3d+5JMJHK/wxYTQa2lJMSNxps2JtuF8hbAnBQb3igoWEjEbIbRRH1XBM0X8dQqemnjQNCiAtxQ==",
+ "dev": true
+ },
+ "@cspell/dict-lorem-ipsum": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-4.0.0.tgz",
+ "integrity": "sha512-1l3yjfNvMzZPibW8A7mQU4kTozwVZVw0AvFEdy+NcqtbxH+TvbSkNMqROOFWrkD2PjnKG0+Ea0tHI2Pi6Gchnw==",
+ "dev": true
+ },
+ "@cspell/dict-lua": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.3.tgz",
+ "integrity": "sha512-lDHKjsrrbqPaea13+G9s0rtXjMO06gPXPYRjRYawbNmo4E/e3XFfVzeci3OQDQNDmf2cPOwt9Ef5lu2lDmwfJg==",
+ "dev": true
+ },
+ "@cspell/dict-makefile": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-makefile/-/dict-makefile-1.0.0.tgz",
+ "integrity": "sha512-3W9tHPcSbJa6s0bcqWo6VisEDTSN5zOtDbnPabF7rbyjRpNo0uHXHRJQF8gAbFzoTzBBhgkTmrfSiuyQm7vBUQ==",
+ "dev": true
+ },
+ "@cspell/dict-node": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-4.0.3.tgz",
+ "integrity": "sha512-sFlUNI5kOogy49KtPg8SMQYirDGIAoKBO3+cDLIwD4MLdsWy1q0upc7pzGht3mrjuyMiPRUV14Bb0rkVLrxOhg==",
+ "dev": true
+ },
+ "@cspell/dict-npm": {
+ "version": "5.0.14",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.0.14.tgz",
+ "integrity": "sha512-k0kC7/W2qG5YII+SW6s+JtvKrkZg651vizi5dv/5G2HmJaeLNgDqBVeeDk/uV+ntBorM66XG4BPMjSxoaIlC5w==",
+ "dev": true
+ },
+ "@cspell/dict-php": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.5.tgz",
+ "integrity": "sha512-9r8ao7Z/mH9Z8pSB7yLtyvcCJWw+/MnQpj7xGVYzIV7V2ZWDRjXZAMgteHMJ37m8oYz64q5d4tiipD300QSetQ==",
+ "dev": true
+ },
+ "@cspell/dict-powershell": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.3.tgz",
+ "integrity": "sha512-lEdzrcyau6mgzu1ie98GjOEegwVHvoaWtzQnm1ie4DyZgMr+N6D0Iyj1lzvtmt0snvsDFa5F2bsYzf3IMKcpcA==",
+ "dev": true
+ },
+ "@cspell/dict-public-licenses": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.5.tgz",
+ "integrity": "sha512-91HK4dSRri/HqzAypHgduRMarJAleOX5NugoI8SjDLPzWYkwZ1ftuCXSk+fy8DLc3wK7iOaFcZAvbjmnLhVs4A==",
+ "dev": true
+ },
+ "@cspell/dict-python": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.1.11.tgz",
+ "integrity": "sha512-XG+v3PumfzUW38huSbfT15Vqt3ihNb462ulfXifpQllPok5OWynhszCLCRQjQReV+dgz784ST4ggRxW452/kVg==",
+ "dev": true,
+ "requires": {
+ "@cspell/dict-data-science": "^1.0.11"
+ }
+ },
+ "@cspell/dict-r": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.0.1.tgz",
+ "integrity": "sha512-KCmKaeYMLm2Ip79mlYPc8p+B2uzwBp4KMkzeLd5E6jUlCL93Y5Nvq68wV5fRLDRTf7N1LvofkVFWfDcednFOgA==",
+ "dev": true
+ },
+ "@cspell/dict-ru_ru": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-ru_ru/-/dict-ru_ru-2.2.0.tgz",
+ "integrity": "sha512-RpEYhY+GbD6TL26y1YC8sPdxpxuCFuzkqfILOtaflL0EFFZRODbvtXW7umjP6QjfxbLSbyMWCTnkZCZzFFFnTw==",
+ "dev": true
+ },
+ "@cspell/dict-ruby": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.2.tgz",
+ "integrity": "sha512-cIh8KTjpldzFzKGgrqUX4bFyav5lC52hXDKo4LbRuMVncs3zg4hcSf4HtURY+f2AfEZzN6ZKzXafQpThq3dl2g==",
+ "dev": true
+ },
+ "@cspell/dict-rust": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.1.tgz",
+ "integrity": "sha512-xJSSzHDK2z6lSVaOmMxl3PTOtfoffaxMo7fTcbZUF+SCJzfKbO6vnN9TCGX2sx1RHFDz66Js6goz6SAZQdOwaw==",
+ "dev": true
+ },
+ "@cspell/dict-scala": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.0.tgz",
+ "integrity": "sha512-ph0twaRoV+ylui022clEO1dZ35QbeEQaKTaV2sPOsdwIokABPIiK09oWwGK9qg7jRGQwVaRPEq0Vp+IG1GpqSQ==",
+ "dev": true
+ },
+ "@cspell/dict-software-terms": {
+ "version": "3.3.15",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-3.3.15.tgz",
+ "integrity": "sha512-1qqMGFi1TUNq9gQj4FTLPTlqVzQLXrj80MsKoXVpysr+823kMWesQAjqHiPg+MYsQ3DlTcpGWcjq/EbYonqueQ==",
+ "dev": true
+ },
+ "@cspell/dict-sql": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.1.3.tgz",
+ "integrity": "sha512-SEyTNKJrjqD6PAzZ9WpdSu6P7wgdNtGV2RV8Kpuw1x6bV+YsSptuClYG+JSdRExBTE6LwIe1bTklejUp3ZP8TQ==",
+ "dev": true
+ },
+ "@cspell/dict-svelte": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.2.tgz",
+ "integrity": "sha512-rPJmnn/GsDs0btNvrRBciOhngKV98yZ9SHmg8qI6HLS8hZKvcXc0LMsf9LLuMK1TmS2+WQFAan6qeqg6bBxL2Q==",
+ "dev": true
+ },
+ "@cspell/dict-swift": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.1.tgz",
+ "integrity": "sha512-gxrCMUOndOk7xZFmXNtkCEeroZRnS2VbeaIPiymGRHj5H+qfTAzAKxtv7jJbVA3YYvEzWcVE2oKDP4wcbhIERw==",
+ "dev": true
+ },
+ "@cspell/dict-typescript": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.1.2.tgz",
+ "integrity": "sha512-lcNOYWjLUvDZdLa0UMNd/LwfVdxhE9rKA+agZBGjL3lTA3uNvH7IUqSJM/IXhJoBpLLMVEOk8v1N9xi+vDuCdA==",
+ "dev": true
+ },
+ "@cspell/dict-vue": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.0.tgz",
+ "integrity": "sha512-niiEMPWPV9IeRBRzZ0TBZmNnkK3olkOPYxC1Ny2AX4TGlYRajcW0WUtoSHmvvjZNfWLSg2L6ruiBeuPSbjnG6A==",
+ "dev": true
+ },
+ "@cspell/dynamic-import": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.2.3.tgz",
+ "integrity": "sha512-udJF+88F4UMH2eVKe3Utsh4X1PyNwqPJclIeD3/MDMFWm16lLkFYMqqrdr51tNLKVi4cXceGrUEapmGwf87l/w==",
+ "dev": true,
+ "requires": {
+ "import-meta-resolve": "^4.0.0"
+ }
+ },
+ "@cspell/strong-weak-map": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.2.3.tgz",
+ "integrity": "sha512-/0gQZw87MqGX8f28E+LhFfrsWdRdQEL8EEQeMXrrzSoPnfSz+ItHMhhrwPF+bMePPjaaUNYoRXvX7hxiDsGm0w==",
+ "dev": true
+ },
+ "@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "requires": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ }
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "optional": true
+ },
+ "ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true
+ },
+ "array-timsort": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz",
+ "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.1.1"
+ }
+ },
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+ "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+ "dev": true
+ },
+ "chalk-template": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-1.1.0.tgz",
+ "integrity": "sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^5.2.0"
+ }
+ },
+ "clear-module": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/clear-module/-/clear-module-4.1.2.tgz",
+ "integrity": "sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==",
+ "dev": true,
+ "requires": {
+ "parent-module": "^2.0.0",
+ "resolve-from": "^5.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "commander": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
+ "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
+ "dev": true
+ },
+ "comment-json": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.3.tgz",
+ "integrity": "sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==",
+ "dev": true,
+ "requires": {
+ "array-timsort": "^1.0.3",
+ "core-util-is": "^1.0.3",
+ "esprima": "^4.0.1",
+ "has-own-prop": "^2.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "configstore": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz",
+ "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^6.0.1",
+ "graceful-fs": "^4.2.6",
+ "unique-string": "^3.0.0",
+ "write-file-atomic": "^3.0.3",
+ "xdg-basedir": "^5.0.1"
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "crypto-random-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz",
+ "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^1.0.1"
+ }
+ },
+ "cspell": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.2.3.tgz",
+ "integrity": "sha512-lJEIglmBINLW4Jwn+5W1k6Zb5EjyRFLnTvc1uQ268/9pcsB+GWUZruplIe5+erR3AxZ+N7Tqp7IY9j2Jf1+/Fg==",
+ "dev": true,
+ "requires": {
+ "@cspell/cspell-json-reporter": "8.2.3",
+ "@cspell/cspell-pipe": "8.2.3",
+ "@cspell/cspell-types": "8.2.3",
+ "@cspell/dynamic-import": "8.2.3",
+ "chalk": "^5.3.0",
+ "chalk-template": "^1.1.0",
+ "commander": "^11.1.0",
+ "cspell-gitignore": "8.2.3",
+ "cspell-glob": "8.2.3",
+ "cspell-io": "8.2.3",
+ "cspell-lib": "8.2.3",
+ "fast-glob": "^3.3.2",
+ "fast-json-stable-stringify": "^2.1.0",
+ "file-entry-cache": "^8.0.0",
+ "get-stdin": "^9.0.0",
+ "semver": "^7.5.4",
+ "strip-ansi": "^7.1.0",
+ "vscode-uri": "^3.0.8"
+ }
+ },
+ "cspell-config-lib": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.2.3.tgz",
+ "integrity": "sha512-ATbOR06GKBIFM5SPKMF4fgo5G2qmOfdV8TbpyzNtw1AGL7PoOgDNFiKSutEzO5EHyZuXE71ZFxH3rVr2gIV7Dw==",
+ "dev": true,
+ "requires": {
+ "@cspell/cspell-types": "8.2.3",
+ "comment-json": "^4.2.3",
+ "yaml": "^2.3.4"
+ }
+ },
+ "cspell-dictionary": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.2.3.tgz",
+ "integrity": "sha512-M/idc3TLjYMpT4+8PlIg7kzoeGkR7o6h6pTwRfy/ZkBkEaV+U/35ZtVLO4qjxnuX6wrmawYmHhYqgzyKLEJIhw==",
+ "dev": true,
+ "requires": {
+ "@cspell/cspell-pipe": "8.2.3",
+ "@cspell/cspell-types": "8.2.3",
+ "cspell-trie-lib": "8.2.3",
+ "fast-equals": "^5.0.1",
+ "gensequence": "^6.0.0"
+ }
+ },
+ "cspell-gitignore": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.2.3.tgz",
+ "integrity": "sha512-tPUI+Aoq1b1shD04CLprrS8wEriiF4G1J+qBiCZK2KWOh6IcufuuDhP1Jtkzz9uONgGWFPF6jj/9TXRFlQexbQ==",
+ "dev": true,
+ "requires": {
+ "cspell-glob": "8.2.3",
+ "find-up-simple": "^1.0.0"
+ }
+ },
+ "cspell-glob": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.2.3.tgz",
+ "integrity": "sha512-byP2kBblO5d9rZr73MPor+KfoFdry4uu/MQmwLiK5mxgmokZYv5GVDX2DrO16Ni4yJ6/2rBPWLfq+DfCXSWqyw==",
+ "dev": true,
+ "requires": {
+ "micromatch": "^4.0.5"
+ }
+ },
+ "cspell-grammar": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.2.3.tgz",
+ "integrity": "sha512-z57Qyu24BsHHp/nZ9ftN377cSCgSJg+6oywIglau7ws7vRpUgYKVoKxn+ZJfOrIZpXfZUqgph5IwAGFI+aRN6w==",
+ "dev": true,
+ "requires": {
+ "@cspell/cspell-pipe": "8.2.3",
+ "@cspell/cspell-types": "8.2.3"
+ }
+ },
+ "cspell-io": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.2.3.tgz",
+ "integrity": "sha512-mPbLXiIje9chncy/Xb9C6AxqjJm9AFHz/nmIIP5bc6gd4w/yaGlQNyO8jjHF1u2JBVbIxPQSMjFgEuqasPy4Sg==",
+ "dev": true,
+ "requires": {
+ "@cspell/cspell-service-bus": "8.2.3"
+ }
+ },
+ "cspell-lib": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.2.3.tgz",
+ "integrity": "sha512-NA4FsGomGPNp15TWbXx13bfknLGU8B66j0QlU3i4oDrWBj/t5m7O1nmiQqcaDSKd9s5HtdTHfxLc83hdzmmizg==",
+ "dev": true,
+ "requires": {
+ "@cspell/cspell-bundled-dicts": "8.2.3",
+ "@cspell/cspell-pipe": "8.2.3",
+ "@cspell/cspell-resolver": "8.2.3",
+ "@cspell/cspell-types": "8.2.3",
+ "@cspell/dynamic-import": "8.2.3",
+ "@cspell/strong-weak-map": "8.2.3",
+ "clear-module": "^4.1.2",
+ "comment-json": "^4.2.3",
+ "configstore": "^6.0.0",
+ "cspell-config-lib": "8.2.3",
+ "cspell-dictionary": "8.2.3",
+ "cspell-glob": "8.2.3",
+ "cspell-grammar": "8.2.3",
+ "cspell-io": "8.2.3",
+ "cspell-trie-lib": "8.2.3",
+ "fast-equals": "^5.0.1",
+ "gensequence": "^6.0.0",
+ "import-fresh": "^3.3.0",
+ "resolve-from": "^5.0.0",
+ "vscode-languageserver-textdocument": "^1.0.11",
+ "vscode-uri": "^3.0.8"
+ }
+ },
+ "cspell-trie-lib": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.2.3.tgz",
+ "integrity": "sha512-yN2PwceN9ViCjXUhhi3MTWfi15Rpc9CsSFFPV3A6cOWoB0qBnuTXk8hBSx+427UGYjtlXPP6EZKY8w8OK6PweA==",
+ "dev": true,
+ "requires": {
+ "@cspell/cspell-pipe": "8.2.3",
+ "@cspell/cspell-types": "8.2.3",
+ "gensequence": "^6.0.0"
+ }
+ },
+ "dot-prop": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz",
+ "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
+ "dev": true,
+ "requires": {
+ "is-obj": "^2.0.0"
+ }
+ },
+ "eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "fast-equals": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz",
+ "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==",
+ "dev": true
+ },
+ "fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ }
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "fastq": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz",
+ "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^4.0.0"
+ }
+ },
+ "fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "find-up-simple": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz",
+ "integrity": "sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==",
+ "dev": true
+ },
+ "flat-cache": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.0.tgz",
+ "integrity": "sha512-EryKbCE/wxpxKniQlyas6PY1I9vwtF3uCBweX+N8KYTCn3Y12RTGtQAJ/bd5pl7kxUAc8v/R3Ake/N17OZiFqA==",
+ "dev": true,
+ "requires": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4",
+ "rimraf": "^5.0.5"
+ }
+ },
+ "flatted": {
+ "version": "3.2.9",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
+ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
+ "dev": true
+ },
+ "foreground-child": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
+ "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ }
+ },
+ "gensequence": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/gensequence/-/gensequence-6.0.0.tgz",
+ "integrity": "sha512-8WwuywE9pokJRAcg2QFR/plk3cVPebSUqRPzpGQh3WQ0wIiHAw+HyOQj5IuHyUTQBHpBKFoB2JUMu9zT3vJ16Q==",
+ "dev": true
+ },
+ "get-stdin": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz",
+ "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==",
+ "dev": true
+ },
+ "glob": {
+ "version": "10.3.10",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
+ "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+ "dev": true,
+ "requires": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.5",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "global-directory": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz",
+ "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==",
+ "dev": true,
+ "requires": {
+ "ini": "4.1.1"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true
+ },
+ "has-own-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz",
+ "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==",
+ "dev": true
+ },
+ "import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "dependencies": {
+ "parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "requires": {
+ "callsites": "^3.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true
+ }
+ }
+ },
+ "import-meta-resolve": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz",
+ "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==",
+ "dev": true
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true
+ },
+ "ini": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz",
+ "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "is-obj": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+ "dev": true
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "jackspeak": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
+ "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+ "dev": true,
+ "requires": {
+ "@isaacs/cliui": "^8.0.2",
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "requires": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "lru-cache": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz",
+ "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==",
+ "dev": true
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ }
+ },
+ "minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ },
+ "minipass": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
+ "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+ "dev": true
+ },
+ "parent-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-2.0.0.tgz",
+ "integrity": "sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==",
+ "dev": true,
+ "requires": {
+ "callsites": "^3.1.0"
+ }
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "path-scurry": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
+ "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^9.1.1 || ^10.0.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ }
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true
+ },
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
+ "dev": true
+ },
+ "resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz",
+ "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==",
+ "dev": true,
+ "requires": {
+ "glob": "^10.3.7"
+ }
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ }
+ }
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "requires": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ }
+ },
+ "string-width-cjs": {
+ "version": "npm:string-width@4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ }
+ }
+ },
+ "strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^6.0.1"
+ }
+ },
+ "strip-ansi-cjs": {
+ "version": "npm:strip-ansi@6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ }
+ }
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "type-fest": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
+ "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
+ "dev": true
+ },
+ "typedarray-to-buffer": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+ "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+ "dev": true,
+ "requires": {
+ "is-typedarray": "^1.0.0"
+ }
+ },
+ "unique-string": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz",
+ "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==",
+ "dev": true,
+ "requires": {
+ "crypto-random-string": "^4.0.0"
+ }
+ },
+ "vscode-languageserver-textdocument": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz",
+ "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==",
+ "dev": true
+ },
+ "vscode-uri": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz",
+ "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==",
+ "dev": true
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ }
+ },
+ "wrap-ansi-cjs": {
+ "version": "npm:wrap-ansi@7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ }
+ }
+ },
+ "write-file-atomic": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+ "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4",
+ "is-typedarray": "^1.0.0",
+ "signal-exit": "^3.0.2",
+ "typedarray-to-buffer": "^3.1.5"
+ },
+ "dependencies": {
+ "signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ }
+ }
+ },
+ "xdg-basedir": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz",
+ "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "yaml": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz",
+ "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==",
+ "dev": true
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..1e8dc96d
--- /dev/null
+++ b/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "rusrails",
+ "version": "1.0.1",
+ "description": "Официальный репозиторий проекта [RusRails.ru](http://rusrails.ru)",
+ "main": "index.js",
+ "directories": {
+ "doc": "doc",
+ "lib": "lib"
+ },
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/rusrails/rusrails.git"
+ },
+ "author": "Mikhail Dieterle",
+ "license": "CC BY-SA 4.0",
+ "bugs": {
+ "url": "https://github.com/rusrails/rusrails/issues"
+ },
+ "homepage": "https://github.com/rusrails/rusrails#readme",
+ "devDependencies": {
+ "cspell": "latest",
+ "@cspell/dict-ru_ru": "latest"
+ }
+}
diff --git a/public/ads.txt b/public/ads.txt
new file mode 100644
index 00000000..b8be1d9b
--- /dev/null
+++ b/public/ads.txt
@@ -0,0 +1 @@
+google.com, pub-7764391801669990, DIRECT, f08c47fec0942fa0
\ No newline at end of file
diff --git a/public/images/belongs_to.png b/public/images/belongs_to.png
deleted file mode 100644
index 44243edb..00000000
Binary files a/public/images/belongs_to.png and /dev/null differ
diff --git a/public/images/csrf.png b/public/images/csrf.png
deleted file mode 100644
index ab73baaf..00000000
Binary files a/public/images/csrf.png and /dev/null differ
diff --git a/public/images/demo_localized_pirate.png b/public/images/demo_localized_pirate.png
deleted file mode 100644
index 91347095..00000000
Binary files a/public/images/demo_localized_pirate.png and /dev/null differ
diff --git a/public/images/demo_translated_en.png b/public/images/demo_translated_en.png
deleted file mode 100644
index ecdd878d..00000000
Binary files a/public/images/demo_translated_en.png and /dev/null differ
diff --git a/public/images/demo_translated_pirate.png b/public/images/demo_translated_pirate.png
deleted file mode 100644
index 41c58092..00000000
Binary files a/public/images/demo_translated_pirate.png and /dev/null differ
diff --git a/public/images/demo_translation_missing.png b/public/images/demo_translation_missing.png
deleted file mode 100644
index af9e2d04..00000000
Binary files a/public/images/demo_translation_missing.png and /dev/null differ
diff --git a/public/images/demo_untranslated.png b/public/images/demo_untranslated.png
deleted file mode 100644
index 3603f434..00000000
Binary files a/public/images/demo_untranslated.png and /dev/null differ
diff --git a/public/images/getting_started/article_with_comments.png b/public/images/getting_started/article_with_comments.png
deleted file mode 100644
index 117a78a3..00000000
Binary files a/public/images/getting_started/article_with_comments.png and /dev/null differ
diff --git a/public/images/getting_started/challenge.png b/public/images/getting_started/challenge.png
deleted file mode 100644
index 5b88a842..00000000
Binary files a/public/images/getting_started/challenge.png and /dev/null differ
diff --git a/public/images/getting_started/confirm_dialog.png b/public/images/getting_started/confirm_dialog.png
deleted file mode 100644
index 9755f581..00000000
Binary files a/public/images/getting_started/confirm_dialog.png and /dev/null differ
diff --git a/public/images/getting_started/forbidden_attributes_for_new_article.png b/public/images/getting_started/forbidden_attributes_for_new_article.png
deleted file mode 100644
index 9f32c684..00000000
Binary files a/public/images/getting_started/forbidden_attributes_for_new_article.png and /dev/null differ
diff --git a/public/images/getting_started/form_with_errors.png b/public/images/getting_started/form_with_errors.png
deleted file mode 100644
index 98bff37d..00000000
Binary files a/public/images/getting_started/form_with_errors.png and /dev/null differ
diff --git a/public/images/getting_started/index_action_with_edit_link.png b/public/images/getting_started/index_action_with_edit_link.png
deleted file mode 100644
index 0566a3ff..00000000
Binary files a/public/images/getting_started/index_action_with_edit_link.png and /dev/null differ
diff --git a/public/images/getting_started/new_article.png b/public/images/getting_started/new_article.png
deleted file mode 100644
index bd3ae4fa..00000000
Binary files a/public/images/getting_started/new_article.png and /dev/null differ
diff --git a/public/images/getting_started/rails_welcome.png b/public/images/getting_started/rails_welcome.png
deleted file mode 100644
index 3e07c948..00000000
Binary files a/public/images/getting_started/rails_welcome.png and /dev/null differ
diff --git a/public/images/getting_started/routing_error_no_controller.png b/public/images/getting_started/routing_error_no_controller.png
deleted file mode 100644
index ed628622..00000000
Binary files a/public/images/getting_started/routing_error_no_controller.png and /dev/null differ
diff --git a/public/images/getting_started/routing_error_no_route_matches.png b/public/images/getting_started/routing_error_no_route_matches.png
deleted file mode 100644
index 08c54f92..00000000
Binary files a/public/images/getting_started/routing_error_no_route_matches.png and /dev/null differ
diff --git a/public/images/getting_started/show_action_for_articles.png b/public/images/getting_started/show_action_for_articles.png
deleted file mode 100644
index 4dad704f..00000000
Binary files a/public/images/getting_started/show_action_for_articles.png and /dev/null differ
diff --git a/public/images/getting_started/template_is_missing_articles_new.png b/public/images/getting_started/template_is_missing_articles_new.png
deleted file mode 100644
index 4e636d09..00000000
Binary files a/public/images/getting_started/template_is_missing_articles_new.png and /dev/null differ
diff --git a/public/images/getting_started/unknown_action_create_for_articles.png b/public/images/getting_started/unknown_action_create_for_articles.png
deleted file mode 100644
index fd20cd53..00000000
Binary files a/public/images/getting_started/unknown_action_create_for_articles.png and /dev/null differ
diff --git a/public/images/getting_started/unknown_action_new_for_articles.png b/public/images/getting_started/unknown_action_new_for_articles.png
deleted file mode 100644
index e948a51e..00000000
Binary files a/public/images/getting_started/unknown_action_new_for_articles.png and /dev/null differ
diff --git a/public/images/getting_startedchallenge.png b/public/images/getting_startedchallenge.png
deleted file mode 100644
index d1637486..00000000
Binary files a/public/images/getting_startedchallenge.png and /dev/null differ
diff --git a/public/images/habtm.png b/public/images/habtm.png
deleted file mode 100644
index fea78b0b..00000000
Binary files a/public/images/habtm.png and /dev/null differ
diff --git a/public/images/has_many.png b/public/images/has_many.png
deleted file mode 100644
index 6cff5846..00000000
Binary files a/public/images/has_many.png and /dev/null differ
diff --git a/public/images/has_many_through.png b/public/images/has_many_through.png
deleted file mode 100644
index 85d75999..00000000
Binary files a/public/images/has_many_through.png and /dev/null differ
diff --git a/public/images/has_one.png b/public/images/has_one.png
deleted file mode 100644
index a70ddaaa..00000000
Binary files a/public/images/has_one.png and /dev/null differ
diff --git a/public/images/has_one_through.png b/public/images/has_one_through.png
deleted file mode 100644
index 89a7617a..00000000
Binary files a/public/images/has_one_through.png and /dev/null differ
diff --git a/public/images/i18n/demo_html_safe.png b/public/images/i18n/demo_html_safe.png
deleted file mode 100644
index f881f60d..00000000
Binary files a/public/images/i18n/demo_html_safe.png and /dev/null differ
diff --git a/public/images/i18n/demo_localized_pirate.png b/public/images/i18n/demo_localized_pirate.png
deleted file mode 100644
index 91347095..00000000
Binary files a/public/images/i18n/demo_localized_pirate.png and /dev/null differ
diff --git a/public/images/i18n/demo_translated_en.png b/public/images/i18n/demo_translated_en.png
deleted file mode 100644
index ecdd878d..00000000
Binary files a/public/images/i18n/demo_translated_en.png and /dev/null differ
diff --git a/public/images/i18n/demo_translated_pirate.png b/public/images/i18n/demo_translated_pirate.png
deleted file mode 100644
index 41c58092..00000000
Binary files a/public/images/i18n/demo_translated_pirate.png and /dev/null differ
diff --git a/public/images/i18n/demo_translation_missing.png b/public/images/i18n/demo_translation_missing.png
deleted file mode 100644
index af9e2d04..00000000
Binary files a/public/images/i18n/demo_translation_missing.png and /dev/null differ
diff --git a/public/images/i18n/demo_untranslated.png b/public/images/i18n/demo_untranslated.png
deleted file mode 100644
index 3603f434..00000000
Binary files a/public/images/i18n/demo_untranslated.png and /dev/null differ
diff --git a/public/images/i18n_demo_html_safe.png b/public/images/i18n_demo_html_safe.png
deleted file mode 100644
index f881f60d..00000000
Binary files a/public/images/i18n_demo_html_safe.png and /dev/null differ
diff --git a/public/images/polymorphic.png b/public/images/polymorphic.png
deleted file mode 100644
index ff2fd9f7..00000000
Binary files a/public/images/polymorphic.png and /dev/null differ
diff --git a/public/images/posts_index.png b/public/images/posts_index.png
deleted file mode 100644
index 50e956e8..00000000
Binary files a/public/images/posts_index.png and /dev/null differ
diff --git a/public/images/rails4_features.png b/public/images/rails4_features.png
deleted file mode 100644
index a979f022..00000000
Binary files a/public/images/rails4_features.png and /dev/null differ
diff --git a/public/images/session_fixation.png b/public/images/session_fixation.png
deleted file mode 100644
index 6b084508..00000000
Binary files a/public/images/session_fixation.png and /dev/null differ
diff --git a/public/rusrails.all.pdf b/public/rusrails.all.pdf
deleted file mode 100644
index 1ab056f1..00000000
Binary files a/public/rusrails.all.pdf and /dev/null differ
diff --git a/script/rails b/script/rails
deleted file mode 100644
index f8da2cff..00000000
--- a/script/rails
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/env ruby
-# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
-
-APP_PATH = File.expand_path('../../config/application', __FILE__)
-require File.expand_path('../../config/boot', __FILE__)
-require 'rails/commands'
diff --git a/source/3_0_release_notes.md b/source/3_0_release_notes.md
index 6cbad833..308b1eec 100644
--- a/source/3_0_release_notes.md
+++ b/source/3_0_release_notes.md
@@ -15,7 +15,9 @@ Rails 3.0 это волшебство! Он приготовит вам ужин
Помимо всего этого, мы попытались как можно лучше указать об устаревании прежнего API с помощью хороших предупреждений. Это означает, что можно перенести ваше существующее приложение на Rails 3 без необходимости немедленного переписывания всего вашего старого кода в соответствии с последними best practices.
-Эти заметки о релизе покрывают основные обновления, но не включают все мелкие багфиксы и изменения. Rails 3.0 содержит почти 4,000 комитов от более чем 250 авторов! Чтобы увидеть все, обратитесь к [списку комитов](http://github.com/rails/rails/commits/3-0-stable) в главном репозитории Rails на GitHub.
+Эти заметки о релизе покрывают только основные изменения, но не включают все мелкие исправления программных ошибок и изменения. Rails 3.0 содержит почти 4,000 коммитов от более чем 250 авторов! Чтобы увидеть все, обратитесь к [списку коммитов](https://github.com/rails/rails/commits/3-0-stable) в главном репозитории Rails на GitHub.
+
+--------------------------------------------------------------------------------
Чтобы установить Rails 3:
@@ -24,26 +26,26 @@ Rails 3.0 это волшебство! Он приготовит вам ужин
$ gem install rails
```
-Обновление до Rails 3
----------------------
+Апгрейд до Rails 3
+------------------
-Если обновляете существующее приложение, было бы хорошо иметь перед этим покрытие тестами. Также, до попытки обновиться до Rails 3, необходимо сначала обновиться до Rails 2.3.5 и убедиться, что приложение все еще выполняется так, как нужно. Затем нужно предпринять следующие изменения:
+Прежде чем апгрейднуть существующее приложение, было бы хорошо иметь перед этим покрытие тестами. Также, до попытки обновиться до Rails 3, необходимо сначала произвести апгрейд до Rails 2.3.5 и убедиться, что приложение все еще выполняется так, как нужно. Затем обратите внимание на следующие изменения:
### Rails 3 требует как минимум Ruby 1.8.7
-Rails 3.0 требует Ruby 1.8.7 или выше. Поддержка всех прежних версий Ruby была официально прекращена, и следует обновиться как можно быстрее. Rails 3.0 также совместим с Ruby 1.9.2.
+Rails 3.0 требует Ruby 1.8.7 или выше. Поддержка всех прежних версий Ruby была официально прекращена, и следует произвести апгрейд как можно раньше. Rails 3.0 также совместим с Ruby 1.9.2.
-TIP: Отметьте, что в Ruby 1.8.7 p248 и p249 имеются ошибки маршализации, ломающие Rails 3.0. Хотя в Ruby Enterprise Edition это было исправлено, начиная с релиза 1.8.7-2010.02. В ветке 1.9, Ruby 1.9.1 не пригоден к использованию, поскольку он иногда вылетает в Rails 3.0, поэтому, если хотите использовать Rails 3.0 с 1.9.x перепрыгивайте на 1.9.2 для гладкой работы.
+TIP: Отметьте, что в Ruby 1.8.7 p248 и p249 имеются программные ошибки маршаллинга, ломающие Rails 3.0. Хотя в Ruby Enterprise Edition это было исправлено, начиная с релиза 1.8.7-2010.02. В ветке 1.9, Ruby 1.9.1 не пригоден к использованию, поскольку он иногда вылетает в Rails 3.0, поэтому, если хотите использовать Rails 3.0 с 1.9.x перепрыгивайте на 1.9.2 для гладкой работы.
### Объект Rails Application
-Как часть внутренней работы по поддержке запуска нескольких приложений Rails в одном процессе, Rails 3 представляет концепцию объекта Application. Этот объект содержит все настройки, специфичные для приложения, и очень похож по сути на `config/environment.rb` из прежних версий Rails.
+Как часть внутренней работы по поддержке запуска нескольких приложений на Rails в одном процессе, Rails 3 представляет концепцию объекта Application. Этот объект содержит все настройки, специфичные для приложения, и очень похож по сути на `config/environment.rb` из прежних версий Rails.
-Теперь каждое приложение Rails должно иметь соответствующий объект application. Этот объект определяется в `config/application.rb`. При обновлении существующего приложения до Rails 3, необходимо добавить этот файл и переместить подходящие конфигурации из `config/environment.rb` в `config/application.rb`.
+Теперь каждое приложение Rails должно иметь соответствующий объект application. Этот объект определяется в `config/application.rb`. При апгрейде существующего приложения до Rails 3, необходимо добавить этот файл и переместить подходящие конфигурации из `config/environment.rb` в `config/application.rb`.
### script/* заменен на script/rails
-Новый `script/rails` заменяет все ранее использовавшиеся скрипты из директории `script`. Впрочем, сейчас не нужно запусать даже `script/rails`, команда `rails` обнаруживает его при вызове из корня приложения Rails и запускает этот скрипт. Пример изменившегося использования:
+Новый `script/rails` заменяет все ранее использовавшиеся скрипты из директории `script`. Впрочем, сейчас не нужно запускать даже `script/rails`, команда `rails` обнаруживает его при вызове из корня приложения Rails и запускает этот скрипт. Пример изменившегося использования:
```bash
$ rails console # вместо script/console
@@ -54,13 +56,13 @@ $ rails g scaffold post title:string # вместо script/generate scaffold pos
### Зависимости и config.gem
-Метода `config.gem` больше нет, он был заменен использованием `bundler` и `Gemfile`, смотрите "Внешние Гемы":#vendoring-gems ниже.
+Метода `config.gem` больше нет, он был заменен использованием `bundler` и `Gemfile`, смотрите [Внешние Гемы](#vendoring-gems) ниже.
-### Процесс обновления
+### Процесс апгрейда
-Для помощи в процессе обновления был создан плагин [Rails Upgrade](http://github.com/rails/rails_upgrade), для автоматизации его части.
+Для упрощения и автоматизации процесса апгрейда был создан плагин [Rails Upgrade](https://github.com/rails/rails_upgrade).
-Просто установите плагин, затем запустите `rake rails:upgrade:check` для проверки, какие части вашего приложения следует обновить (с ссылками на информацию, как это сделать). Он также предлагает задание по созданию `Gemfile`, основанного на текущих вызовах `config.gem`, и задание по созданию нового маршрутного файла из старого. Чтобы получить плагин, просто запустите:
+Просто установите плагин, затем запустите `rake rails:upgrade:check` для проверки, какие части вашего приложения следует обновить (с ссылками на информацию, как это сделать). Он также предлагает задачу по генерации `Gemfile`, основанного на текущих вызовах `config.gem`, и задачу по генерации нового маршрутного файла из старого. Чтобы получить плагин, просто запустите:
```bash
$ ruby script/plugin install git://github.com/rails/rails_upgrade.git
@@ -68,7 +70,7 @@ $ ruby script/plugin install git://github.com/rails/rails_upgrade.git
Пример того, как это все работает, можно увидеть в [Rails Upgrade is now an Official Plugin](http://omgbloglol.com/post/364624593/rails-upgrade-is-now-an-official-plugin)
-Помимо Rails Upgrade tool, если нужна помощь, есть люди в IRC и [rubyonrails-talk](http://groups.google.com/group/rubyonrails-talk), которые, возможно, сталкивались с подобными проблемами. Напишите в свой блог о своем опыте обновления, чтобы другие смогли воспользоваться вашими знаниями!
+Помимо Rails Upgrade tool, если нужна помощь, есть люди в IRC и [rubyonrails-talk](https://groups.google.com/group/rubyonrails-talk), которые, возможно, сталкивались с подобными проблемами. Напишите в свой блог о своем опыте апгрейда, чтобы другие смогли воспользоваться вашими знаниями!
Создание приложения Rails 3.0
-----------------------------
@@ -81,9 +83,9 @@ $ cd myapp
### Сторонние гемы
-Сейчас Rails использует `Gemfile` в корне приложения, чтобы определить гемы, требуемые для запуска вашего приложения. Этот `Gemfile` обрабатывается [Bundler](http://github.com/carlhuda/bundler), который затем устанавливает все зависимости. Он может даже установить все зависимости локально в ваше приложение, и оно не будет зависеть от системных гемов.
+Сейчас Rails использует `Gemfile` в корне приложения, чтобы определить гемы, требуемые для запуска вашего приложения. Этот `Gemfile` обрабатывается [Bundler](https://github.com/bundler/bundler), который затем устанавливает все зависимости. Он может даже установить все зависимости локально в ваше приложение, и оно не будет зависеть от системных гемов.
-Подробнее: - [домашняя страница bundler](http://gembundler.com)
+Подробнее: - [домашняя страница Bundler](https://bundler.io/)
### Живите на грани
@@ -95,7 +97,7 @@ $ cd myapp
$ rails new myapp --edge
```
-Если у вас есть локальная копия репозитория Rails, и вы хотите создать приложение с ее использованием, передайте флажок `--dev`:
+Если имеется локальная копия репозитория Rails, и необходимо сгенерировать приложение используя ее, передайте флажок `--dev`:
```bash
$ ruby /path/to/rails/bin/rails new myapp --dev
@@ -110,40 +112,40 @@ $ ruby /path/to/rails/bin/rails new myapp --dev
Railties был обновлен, чтобы предоставить совместимое с плагинами API для всего фреймворка Rails, а также полностью переписаны генераторы и зависимости Rails, в результате разработчики смогут в значительной степени внедрять свой код в генераторы и фреймворк приложения совместимым и определенным образом.
-### Все основные компоненты Rails были разделены
+### Все компоненты ядра Rails были разделены
-В связи со слиянием Merb и Rails, одной из крупных работ было устранение тесно связанных вместе основных компонентов Rails. Это было достигнуто, и теперь все основные компоненты Rails используют то же API, что вы можете использовать для своих плагинов. Это означает, что каждый сделанный вами плагин или замена любого основного компонента (например DataMapper или Sequel) имеют доступ ко всему функционалу, к которому имеют доступ основные компоненты Rails, и могут расширять и улучшать его как угодно.
+В связи с объединением Merb и Rails, одним из заданий было устранение тесно связанных вместе компонентов ядра Rails. Это было достигнуто, и теперь все компоненты ядра Rails используют то же API, что вы можете использовать для своих плагинов. Это означает, что каждый сделанный вами плагин или замена любого компонента ядра (например, DataMapper или Sequel) имеют доступ ко всей функциональности, к которой имеют доступ компоненты ядра Rails, и могут расширять и улучшать ее как угодно.
Подробнее: - [The Great Decoupling](http://yehudakatz.com/2009/07/19/rails-3-the-great-decoupling/)
### Абстракция Active Model
-Частью разделения основных компонентов было выделение всех связей из Action Pack в Active Record. Теперь это выполнено. Всем новым плагинам ORM теперь всего лишь нужно внедрить интерфейсы Active Model, чтобы работать с Action Pack.
+Частью разделения компонентов ядра было выделение всех связей из Action Pack в Active Record. Теперь это выполнено. Всем новым плагинам ORM теперь всего лишь нужно внедрить интерфейсы Active Model, чтобы работать с Action Pack.
Подробнее: - [Make Any Ruby Object Feel Like ActiveRecord](http://yehudakatz.com/2010/01/10/activemodel-make-any-ruby-object-feel-like-activerecord/)
### Абстракция контроллера
-Другой крупной частью разделения основных компонентов было создание основного суперкласса, отделенного от терминов HTTP, для управления рендерингом вьюх и т.д. Создание `AbstractController` позволило существенно упростить `ActionController` и `ActionMailer`, убрав общий код из этих библиотек, и поместив его в Abstract Controller.
+Другой крупной частью разделения компонентов ядра было создание основного суперкласса, отделенного от терминов HTTP, для управления рендерингом вью и т.д. Создание `AbstractController` позволило существенно упростить `ActionController` и `ActionMailer`, убрав общий код из этих библиотек, и поместив его в Abstract Controller.
Подробнее: - [Rails Edge Architecture](http://yehudakatz.com/2009/06/11/rails-edge-architecture/)
### Интеграция Arel
-[Arel](http://github.com/brynary/arel) (или Active Relation) был принят в качестве основы Active Record, и теперь требуется в Rails. Arel предоставляет абстракцию SQL, упрощающую Active Record и предоставляющую основы для функционала relation в Active Record.
+[Arel](https://github.com/brynary/arel) (или Active Relation) был принят в качестве основы Active Record, и теперь требуется в Rails. Arel предоставляет абстракцию SQL, упрощающую Active Record и предоставляющую основы для функциональности relation в Active Record.
-Подробнее: - [Why I wrote Arel](http://magicscalingsprinkles.wordpress.com/2010/01/28/why-i-wrote-arel/).
+Подробнее: - [Why I wrote Arel](https://web.archive.org/web/20120718093140/http://magicscalingsprinkles.wordpress.com/2010/01/28/why-i-wrote-arel/).
### Извлечение Mail
-В Action Mailer с самого начала были monkey патчи, пре-парсеры и даже агенты для отправки и получения, все в добавок к встроенному в исходик TMail. Версия 3 изменила все это, так что весь функционал, связанный с сообщениями email был выделен в гем [Mail](http://github.com/mikel/mail). Это, опять же, уменьшило повторение кода и помогло определить границы между Action Mailer и парсером email.
+В Action Mailer с самого начала были monkey патчи, пре-парсеры и даже агенты для отправки и получения, все вдобавок к встроенному в исходник TMail. Версия 3 изменила все это, так что вся функциональность, связанная с сообщениями email была выделена в гем [Mail](https://github.com/mikel/mail). Это, опять же, уменьшило повторение кода и помогло определить границы между Action Mailer и парсером email.
Подробнее: - [New Action Mailer API in Rails 3](http://lindsaar.net/2010/1/26/new-actionmailer-api-in-rails-3)
Интернационализация
-------------------
-В Rails 3 было проделано много работы над поддержкой I18n, включая гем [I18n](http://github.com/svenfuchs/i18n), поддерживающий разные улучшения производительности.
+В Rails 3 было проделано много работы над поддержкой I18n, включая гем [I18n](https://github.com/svenfuchs/i18n), поддерживающий разные улучшения производительности.
* I18n для любого объекта - поведение I18n может быть добавлено к любому объекту, включая `ActiveModel::Translation` и `ActiveModel::Validations`. Для переводов также имеется `errors.messages` fallback.
* У атрибутов имеются переводы по умолчанию.
@@ -172,13 +174,13 @@ Railties
* Новые генераторы позволяют переопределить шаблоны, поместив копию в `Rails.root/lib/templates`.
* Также представлен `Rails::Generators::TestCase`, поэтому вы можете создать собственные генераторы и протестировать их.
-Также несколько переделаны вьюхи, создаваемые генераторами Railties:
+Также несколько переделаны вью, генерируемые с помощью генераторов Railties:
-* Сейчас вьюхи используют теги `div` вместо тегов `p`.
-* Сейчас сгенерированные скафолды используют партиалы `_form`, вместо повторения кода во вьюхах edit и new.
+* Сейчас вью используют теги `div` вместо тегов `p`.
+* Сейчас сгенерированные скаффолды используют партиалы `_form`, вместо повторения кода во вью edit и new.
* Сейчас формы скаффолда используют `f.submit`, возвращающий "Create ModelName" или "Update ModelName", в зависимости от состояния переданного объекта.
-Наконец, ряд улучшений был добавлен в рейк-таски:
+Наконец, ряд улучшений был добавлен в задачи rake:
* Был добавлен `rake db:forward`, позволяющий откатить ваши миграции с возвратом отдельно или в группах.
* Был добавлен `rake routes CONTROLLER=x`, позволяющий просмотреть маршруты только к одному контроллеру.
@@ -189,13 +191,12 @@ Railties
* `RAILS_ENV` в пользу `Rails.env`, и
* `RAILS_DEFAULT_LOGGER` в пользу `Rails.logger`.
-`PLUGIN/rails/tasks` и `PLUGIN/tasks` больше не загружаются, все таски теперь должны быть в `PLUGIN/lib/tasks`.
+`PLUGIN/rails/tasks` и `PLUGIN/tasks` больше не загружаются, все задачи теперь должны быть в `PLUGIN/lib/tasks`.
Подробнее:
* [Discovering Rails 3 generators](http://blog.plataformatec.com.br/2010/01/discovering-rails-3-generators)
-* [Making Generators for Rails 3 with Thor](http://caffeinedd.com/guides/331-making-generators-for-rails-3-with-thor)
-* [The Rails Module (in Rails 3)](http://litanyagainstfear.com/blog/2010/02/03/the-rails-module/)
+* [The Rails Module (in Rails 3)](http://quaran.to/blog/2010/02/03/the-rails-module/)
Action Pack
-----------
@@ -204,7 +205,7 @@ Action Pack
### Abstract Controller
-В Abstract Controller были извлечены части общего назначения из Action Controller в виде модуля, годного в использовнии любой библиотекой, используемой для рендеринга шаблонов или партиалов, хелперов, переводов, логирования и любой части цикла отклика на запрос. Теперь эта абстракция позволяет `ActionMailer::Base` быть унаследованным от `AbstractController` и всего лишь оборачивать Rails DSL в гем Mail.
+В Abstract Controller были извлечены части общего назначения из Action Controller в виде модуля, годного в использовании любой библиотекой, используемой для рендеринга шаблонов или партиалов, хелперов, переводов, логирования и любой части цикла отклика на запрос. Теперь эта абстракция позволяет `ActionMailer::Base` быть унаследованным от `AbstractController` и всего лишь оборачивать Rails DSL в гем Mail.
Это также предоставило возможность вычистить Action Controller, упростив его код.
@@ -218,18 +219,18 @@ Action Pack
* `cookie_verifier_secret` устарел, вместо этого теперь назначается `Rails.application.config.cookie_secret`, и был перемещен в отдельный файл: `config/initializers/cookie_verification_secret.rb`.
* `session_store` настраивалось в `ActionController::Base.session`, а теперь перемещено в `Rails.application.config.session_store`. Значения по умолчанию устанавливаются в `config/initializers/session_store.rb`.
* `cookies.secure` позволяет устанавливать зашифрованные значения куки с помощью `cookie.secure[:key] => value`.
-* `cookies.permanent` позволяет устанавливать постоянные значения хэш куки `cookie.permanent[:key] => value`, вызывая исключение на шифрованных значениях, если не проходит верификация.
+* `cookies.permanent` позволяет устанавливать постоянные значения хэш куки `cookie.permanent[:key] => value`, вызывая исключение на шифрованных значениях, если не проходит верификация.
* Теперь можно передать `:notice => 'This is a flash message'` или `:alert => 'Something went wrong'` в вызове `format` внутри блока `respond_to`. Хэш `flash[]` все еще работает по-прежнему.
* Теперь в контроллеры добавился метод `respond_with`, упрощающий старые блоки `format`.
-* Добавленный `ActionController::Responder` дает гибкость в том, как будут получены созданные вами отклики.
+* Добавленный `ActionController::Responder` дает гибкость в том, как будут получены сгенерированные вами отклики.
Устарело:
* `filter_parameter_logging` устарел в пользу `config.filter_parameters << :password`.
Подробнее:
-* [Render Options in Rails 3](http://www.engineyard.com/blog/2010/render-options-in-rails-3/)
-* [Three reasons to love ActionController::Responder](http://weblog.rubyonrails.org/2009/8/31/three-reasons-love-responder)
+* [Render Options in Rails 3](https://www.engineyard.com/blog/render-options-in-rails-3)
+* [Three reasons to love ActionController::Responder](https://weblog.rubyonrails.org/2009/8/31/three-reasons-love-responder)
### Action Dispatch
@@ -254,7 +255,7 @@ end
* В роутер добавлен метод `match`, также можно к соответствующему маршруту передать любое приложение Rack.
* В роутер добавлен метод `constraints`, позволяющий защитить маршруты определенными ограничениями.
-* В роутер добавлен метод `scope`, позволяющий вложить маршруты в пространство имен для различных яхыков или иных действий, например:
+* В роутер добавлен метод `scope`, позволяющий вложить маршруты в пространство имен для разных языков или различных экшнов, например:
```ruby
scope 'es' do
@@ -278,7 +279,7 @@ NOTE. Старый стиль команд `map` все еще работает,
Подробнее:
* [The Rails 3 Router: Rack it Up](http://yehudakatz.com/2009/12/26/the-rails-3-router-rack-it-up/)
-* [Revamped Routes in Rails 3](http://rizwanreza.com/2009/12/20/revamped-routes-in-rails-3)
+* [Revamped Routes in Rails 3](https://medium.com/fusion-of-thoughts/revamped-routes-in-rails-3-b6d00654e5b0)
* [Generic Actions in Rails 3](http://yehudakatz.com/2009/12/20/generic-actions-in-rails-3/)
### Action View
@@ -287,7 +288,7 @@ NOTE. Старый стиль команд `map` все еще работает,
Произошло масштабное переписывание хелперов Action View, реализованы хуки Unobtrusive JavaScript (UJS) и убраны старые команды встроенного AJAX. Это позволило Rails использовать любой совместимый драйвер UJS для внедрения хуков UJS в хелперах.
-Это означает, что все прежние хелперы `remote_` были убраны из ядра Rails и перемещены в [Prototype Legacy Helper](http://github.com/rails/prototype_legacy_helper). Для получения хуков UJS в HTML, теперь нужно передать `:remote => true`. Для примера:
+Это означает, что все прежние хелперы `remote_` были убраны из ядра Rails и перемещены в [Prototype Legacy Helper](https://github.com/rails/prototype_legacy_helper). Для получения хуков UJS в HTML, теперь нужно передать `:remote => true`. Для примера:
```ruby
form_for @post, :remote => true
@@ -309,19 +310,19 @@ form_for @post, :remote => true
<% end %>
```
-От ваших собственных подобных хелперов ожидается, что они возвращают строку, а не добавляют к результирующиму буфферу вручную.
+От ваших собственных подобных хелперов ожидается, что они возвращают строку, а не добавляют к результирующему буферу вручную.
Хелперы с другим поведением, наподобие `cache` или `content_for`, не затронуты этим изменением, им нужен `<%` как и прежде.
-#### Другие изменния
+#### Другие изменения
-* Больше не нужно вызывать `h(string)` для экранирования HTML, это осуществляется по умолчанию во всех шаблонах вьюх. Если хотите неэкранированную строку, вызывайте `raw(string)`.
-* Теперь по умолчанию хелперы выводят HTML 5.
+* Больше не нужно вызывать `h(string)` для экранирования HTML, это осуществляется по умолчанию во всех шаблонах вью. Если хотите неэкранированную строку, вызывайте `raw(string)`.
+* Теперь по умолчанию хелперы выводят HTML5.
* Хелпер формы label теперь берет значения из I18n с отдельным значением, таким образом `f.label :name` возьмет перевод `:name`.
* Метка I18n для select теперь :en.helpers.select вместо :en.support.select.
* Теперь не нужно помещать знак минуса в конце интерполяции руби в шаблоне ERB для того, чтобы убрать перевод строки в результирующем HTML.
* В Action View добавлен хелпер `grouped_collection_select`.
-* Добавлен `content_for?`, позволяющий проверить существование содержимого во вьюхе до рендеринга.
+* Добавлен `content_for?`, позволяющий проверить существование содержимого во вью до рендеринга.
* Передача в хелперы форм `:value => nil` установит атрибут поля `value` как nil вместо значения по умолчанию
* Передача в хелперы форм `:id => nil` приведет к тому, что эти поля будут отрендерены без атрибута `id`
* Передача `:alt => nil` в `image_tag` приведет к тому, что тег `img` отрендерится без атрибута `alt`
@@ -333,13 +334,13 @@ Active Model это новшество в Rails 3.0. Он представляе
### Абстракция ORM и интерфейс Action Pack
-Частью разделения основных компонентов было выделение всех связей из Action Pack в Active Record. Теперь это выполнено. Всем новым плагинам ORM теперь всего лишь нужно внедрить интерфейсы Active Model, чтобы работать с Action Pack.
+Частью разделения компонентов ядра было выделение всех связей из Action Pack в Active Record. Теперь это выполнено. Всем новым плагинам ORM теперь всего лишь нужно внедрить интерфейсы Active Model, чтобы работать с Action Pack.
Подробнее: - [Make Any Ruby Object Feel Like ActiveRecord](http://yehudakatz.com/2010/01/10/activemodel-make-any-ruby-object-feel-like-activerecord/)
### Валидации
-Валидации были перемещены из Active Record в Active Model, предоставляя интефейс для валидаций, работающий во всех библиотеках ORM в Rails 3.
+Валидации были перемещены из Active Record в Active Model, предоставляя интерфейс для валидаций, работающий во всех библиотеках ORM в Rails 3.
* Теперь имеется краткий метод `validates :attribute, options_hash` позволяющий передать опции для всех валидационных методов класса, в метод валидации можно передать более одной опции.
* У метода `validates` имеются следующие опции:
@@ -397,7 +398,7 @@ User.validators_on(:login)
Active Record
-------------
-Active Record было уделено много внимания в Rails 3.0, включая абстрагирование в Active Model, полное обновление интерфейса запросов с применением Arel, обновления валидаций и многие улучшения и фиксы. Rails 2.x API будет полностью поддерживаемым с целью совместимости, до версии 3.1.
+Active Record было уделено много внимания в Rails 3.0, включая абстрагирование в Active Model, полное обновление интерфейса запросов с применением Arel, обновления валидаций и многие улучшения и исправления. Rails 2.x API будет полностью поддерживаемым с целью совместимости, до версии 3.1.
### Интерфейс запросов
@@ -431,15 +432,15 @@ Active Record было уделено много внимания в Rails 3.0,
### Патчи и устаревания
-Кроме того, в ветке Active Record сделано много фиксов:
+Кроме того, в ветке Active Record сделано много исправлений:
* Поддержка SQLite 2 была отброшена в пользу SQLite 3.
* Поддержка порядка следования столбцов в MySQL.
-* В адаптере PostgreSQL теперь пофикшена поддержка `TIME ZONE`, теперь не будут вставляться неправильные значения.
+* В адаптере PostgreSQL теперь исправлена поддержка `TIME ZONE`, теперь не будут вставляться неправильные значения.
* Поддержка нескольких схем в именах таблицы для PostgreSQL.
* PostgreSQL поддерживает тип данных столбца XML.
* `table_name` теперь кэшируется.
-* Много работы выполнено по адаптеру Oracle, также с множеством багфиксов.
+* Много работы выполнено по адаптеру Oracle, также с множеством исправлений программных ошибок.
А также следующее объявлено устаревшим:
@@ -461,7 +462,7 @@ Active Resource
* Добавлены валидации с помощью Active Model.
* Добавлены хуки обсерверов.
* Поддержка прокси HTTP.
-* Добавлена поддержка digest authentication.
+* Добавлена поддержка дайджест-аутентификации.
* Именование модели перемещено в Active Model.
* Изменены атрибуты Active Resource на Hash with indifferent access.
* Добавлены псевдонимы `first`, `last` и `all` для эквивалентных скоупов поиска.
@@ -472,12 +473,12 @@ Active Resource
* Переименован `SchemaDefinition` в `Schema` и `define_schema` в `schema`.
* Использован `format` из Active Resources, а не `content-type` на удаленных ошибках для загрузки ошибок.
* Использован `instance_eval` для блока схемы.
-* Пофикшен `ActiveResource::ConnectionError#to_s`, когда `@response` не отвечал на #code или #message, для совместимости с Ruby 1.9.
+* Исправлен `ActiveResource::ConnectionError#to_s`, когда `@response` не отвечал на #code или #message, для совместимости с Ruby 1.9.
* Добавлена поддержка для ошибок в формате JSON.
* Гарантировано, что `load` работает с числовыми массивами.
* Распознается отклик 410 от удаленного (remote) ресурса, как то, что ресурс был удален (deleted).
-* Добавлена возможность установить настройки SSL на соединениях Active Resource.
-* Настройки таймаута соединения также влияют на `Net::HTTP` `open_timeout`.
+* Добавлена возможность установить опции SSL на соединениях Active Resource.
+* Настройки тайм-аута соединения также влияют на `Net::HTTP` `open_timeout`.
Устарело:
@@ -487,16 +488,16 @@ Active Resource
Active Support
--------------
-В Active Support были направлены большие усилия на то, чтобы сделать его раздробленным, это означает, что вам больше не нужно требовать всю библиотеку Active Support, чтобы пользоваться ее частью. Это позволило различным частям основных компонент Rails выполняться быстрее.
+В Active Support были направлены большие усилия на то, чтобы сделать его раздробленным, это означает, что вам больше не нужно требовать всю библиотеку Active Support, чтобы пользоваться ее частью. Это позволило различным частям компонентов ядра Rails выполняться быстрее.
Вот основные изменения в Active Support:
* Большая чистка всей библиотеки от неиспользуемых методов.
-* Active Support более не предоставляет внешние библиотеки [TZInfo](http://tzinfo.rubyforge.org/), [Memcache Client](http://deveiate.org/projects/RMemCache/) и [Builder](http://builder.rubyforge.org/), все они включены как зависимости и устанавливаются с помощью команды `bundle install`.
+* Active Support более не предоставляет внешние библиотеки TZInfo, Memcache Client и Builder, все они включены как зависимости и устанавливаются с помощью команды `bundle install`.
* Безопасные буферы реализованы в `ActiveSupport::SafeBuffer`.
* Добавлены `Array.uniq_by` и `Array.uniq_by!`.
-* Убран `Array#rand` и портирован `Array#sample` из Ruby 1.9.
-* Пофикшен баг в `TimeZone.seconds_to_utc_offset`, возвращающий неправильное значение.
+* Убран `Array#rand` и бэкпортирован `Array#sample` из Ruby 1.9.
+* Исправлена программная ошибка в методе `TimeZone.seconds_to_utc_offset`, возвращающий неправильное значение.
* Добавлена промежуточная программа `ActiveSupport::Notifications`.
* `ActiveSupport.use_standard_json_time_format` теперь по умолчанию true.
* `ActiveSupport.escape_html_entities_in_json` теперь по умолчанию false.
@@ -509,13 +510,13 @@ Active Support
* Добавлен `to_i` к `DateTime` в `ActiveSupport`, таким образом `to_yaml` правильно работает в моделях с атрибутами `DateTime`.
* Добавлен `Enumerable#exclude?` в пару к `Enumerable#include?`, чтобы избежать условия `!x.include?`.
* Включена по умолчанию экранизация XSS для rails.
-* Поддержка многоуровнего объединения в `ActiveSupport::HashWithIndifferentAccess`.
+* Поддержка многоуровневого объединения в `ActiveSupport::HashWithIndifferentAccess`.
* `Enumerable#sum` теперь работает для всех перечисляемых типов, даже если они не отвечают на `:size`.
* `inspect` на нулевой продолжительности возвращает '0 seconds' вместо пустой строки.
* Добавлены `element` и `collection` в `ModelName`.
* `String#to_time` и `String#to_datetime` обрабатывают дробные секунды.
* Добавлена поддержка для новых колбэков для объекта охватывающего фильтра, отвечающего на `:before` и `:after`, используемых в предварительных и последующих колбэках.
-* Метод `ActiveSupport::OrderedHash#to_a` возвращает упорядоченный набор массивов. Соотетствует `Hash#to_a` из Ruby 1.9.
+* Метод `ActiveSupport::OrderedHash#to_a` возвращает упорядоченный набор массивов. Соответствует `Hash#to_a` из Ruby 1.9.
* `MissingSourceFile` существует как константа, но сейчас всего лишь равна `LoadError`.
* Добавлен `Class#class_attribute` для возможности объявить атрибуты на уровне класса, значения которых наследуются и перезаписываются подклассами.
* Окончательно убран `DeprecatedCallbacks` в `ActiveRecord::Associations`.
@@ -544,18 +545,18 @@ Active Support
Action Mailer
-------------
-Action Mailer получил новый API в связи с заменой TMail на новый [Mail](http://github.com/mikel/mail) в качестве библиотеки для электронных писем. В самом Action Mailer была переписана практически каждая строчка кода. В результате теперь Action Mailer просто наследуется от Abstract Controller и оборачивает гем Mail в Rails DSL. Это значительно уменьшило количество кода и дублирование других библиотек в Action Mailer.
+Action Mailer получил новый API в связи с заменой TMail на новый [Mail](https://github.com/mikel/mail) в качестве библиотеки для электронных писем. В самом Action Mailer была переписана практически каждая строчка кода. В результате теперь Action Mailer просто наследуется от Abstract Controller и оборачивает гем Mail в Rails DSL. Это значительно уменьшило количество кода и дублирование других библиотек в Action Mailer.
* По умолчанию все рассыльщики теперь находятся в `app/mailers`.
* Теперь можно отослать email с использованием нового API тремя методами: `attachments`, `headers` and `mail`.
-* Теперь в Action Mailer имеется нативная поддержка для встроенных вложений с помощью метода `attachments.inline`.
-* Методы рассылки Action Mailer теперь возвращают объекты `Mail::Message`, которые затем могут быть отосланы с помощью метода `deliver` на нимх.
+* Теперь в Action Mailer имеется нативная поддержка для встроенных прикрепленных файлов с помощью метода `attachments.inline`.
+* Методы рассылки Action Mailer теперь возвращают объекты `Mail::Message`, которые затем могут быть отосланы с помощью метода `deliver` на них.
* Все методы доставки теперь абстрагированы в геме Mail.
* Метод отправки письма может принимать хэш всех валидных полей заголовка письма в паре с их значением.
* Метод доставки `mail` работает подобно `respond_to` из Action Controller, и можно явно или неявно рендерить шаблоны. Action Mailer превратит email в multipart email по необходимости.
* В вызов `format.mime_type` в блоке mail можно передать proc и явно отрендерить определенные типы текста, или добавить макет или различные шаблоны. Вызов `render` внутри proc происходит из Abstract Controller и поддерживает те же опции.
-* Юнит тесты рассыльщика перенесены в функциональные тесты.
-* Теперь Action Mailer делегирует все автокодирование полей заголовка и тела письма в гем Mail
+* Юнит-тесты рассыльщика перенесены в функциональные тесты.
+* Теперь Action Mailer делегирует все автоматическое кодирование полей заголовка и тела письма в гем Mail
* Action Mailer автоматически закодирует поля заголовка и тело письма
Устарело:
@@ -563,8 +564,8 @@ Action Mailer получил новый API в связи с заменой TMai
* `:charset`, `:content_type`, `:mime_version`, `:implicit_parts_order` устарели в пользу стиля объявления `ActionMailer.default :key => value`.
* Динамические методы рассыльщика `create_method_name` и `deliver_method_name` устарели, просто вызывайте `method_name`, который возвратит объект `Mail::Message`.
* `ActionMailer.deliver(message)` устарел, просто вызывайте `message.deliver`.
-* `template_root` устарел, передавайте опции в вызов render в proc из метода `format.mime_type` внутри блока создания письма `mail`
-* Метод `body` для определения переменных экземпляра устарел (`body {:ivar => value}`), всего лишь определите переменные экземпляра непосредственно в методе, и они будут доступны во вьюхе.
+* `template_root` устарел, передавайте опции в вызов render в proc из метода `format.mime_type` внутри блока генерации письма `mail`
+* Метод `body` для определения переменных экземпляра устарел (`body {:ivar => value}`), всего лишь определите переменные экземпляра непосредственно в методе, и они будут доступны во вью.
* Нахождение рассыльщиков в `app/models` устарело, вместо этого используйте `app/mailers`.
Подробнее:
diff --git a/source/3_1_release_notes.md b/source/3_1_release_notes.md
index 67170914..db844499 100644
--- a/source/3_1_release_notes.md
+++ b/source/3_1_release_notes.md
@@ -5,55 +5,57 @@
* Streaming
* Обратимые миграции
-* Файлопровод (Assets Pipeline)
+* Конвейер ресурсов (Assets Pipeline)
* jQuery как библиотека JavaScript по умолчанию
-Эти заметки о релизе покрывают основные обновления, но не включают все мелкие багфиксы и изменения. Чтобы увидеть все, обратитесь к [списку комитов](http://github.com/rails/rails/commits/3-1-stable) в главном репозитории Rails на GitHub.
+Эти заметки о релизе покрывают только основные изменения. Чтобы узнать о различных исправлениях программных ошибок и изменениях, обратитесь к логам изменений или к [списку коммитов](https://github.com/rails/rails/commits/3-1-stable) в главном репозитории Rails на GitHub.
-(Upgrading to Rails 3.1) Обновление до Rails 3.1
-------------------------------------------------
+--------------------------------------------------------------------------------
-Если обновляете существующее приложение, было бы хорошо иметь перед этим покрытие тестами. Также, до попытки обновиться до Rails 3.1, необходимо сначала обновиться до Rails 3 и убедиться, что приложение все еще выполняется так, как нужно. Затем нужно предпринять следующие изменения:
+(Upgrading to Rails 3.1) Апгрейд до Rails 3.1
+---------------------------------------------
+
+Прежде чем апгрейднуть существующее приложение, было бы хорошо иметь перед этим покрытие тестами. Также, до попытки обновиться до Rails 3.1, необходимо сначала произвести апгрейд до Rails 3 и убедиться, что приложение все еще выполняется так, как нужно. Затем обратите внимание на следующие изменения:
### Rails 3.1 требует как минимум Ruby 1.8.7
-Rails 3.1 требует Ruby 1.8.7 или выше. Поддержка всех прежних версий Ruby была официально прекращена, и следует обновиться как можно быстрее. Rails 3.1 также совместим с Ruby 1.9.2.
+Rails 3.1 требует Ruby 1.8.7 или выше. Поддержка всех прежних версий Ruby была официально прекращена, и следует произвести апгрейд как можно раньше. Rails 3.1 также совместим с Ruby 1.9.2.
-TIP: Отметьте, что в Ruby 1.8.7 p248 и p249 имеются ошибки маршализации, ломающие Rails. Хотя в Ruby Enterprise Edition это было исправлено, начиная с релиза 1.8.7-2010.02. В ветке 1.9, Ruby 1.9.1 не пригоден к использованию, поскольку он иногда вылетает, поэтому, если хотите использовать 1.9.x перепрыгивайте на 1.9.2 для гладкой работы.
+TIP: Отметьте, что в Ruby 1.8.7 p248 и p249 имеются программные ошибки маршаллинга, ломающие Rails. Хотя в Ruby Enterprise Edition это было исправлено, начиная с релиза 1.8.7-2010.02. В ветке 1.9, Ruby 1.9.1 не пригоден к использованию, поскольку он иногда вылетает, поэтому, если хотите использовать 1.9.x перепрыгивайте на 1.9.2 для гладкой работы.
### Что обновить в приложении
-Следующие изменения означают обновление вашего приложения до Rails 3.1.3, последней версии 3.1.x Rails.
+Следующие изменения предназначены для апгрейда приложения до Rails 3.1.3, последней версии 3.1.x Rails.
#### Gemfile
Сделайте изменения в вашем `Gemfile`.
```ruby
-gem 'rails', '= 3.1.3'
-gem 'mysql2'
+gem "rails", "= 3.1.3"
+gem "mysql2"
-# Needed for the new asset pipeline
+# Необходимо для нового asset pipeline
group :assets do
- gem 'sass-rails', "~> 3.1.5"
- gem 'coffee-rails', "~> 3.1.1"
- gem 'uglifier', ">= 1.0.3"
+ gem "sass-rails", "~> 3.1.5"
+ gem "coffee-rails", "~> 3.1.1"
+ gem "uglifier", ">= 1.0.3"
end
-# jQuery is the default JavaScript library in Rails 3.1
-gem 'jquery-rails'
+# jQuery это библиотека JavaScript по умолчанию в Rails 3.1
+gem "jquery-rails"
```
#### config/application.rb
-* Файлопровод требует следующие добавления:
+* Конвейер ресурсов требует следующие добавления:
```ruby
config.assets.enabled = true
config.assets.version = '1.0'
```
-* Если ваше приложение использует маршрут "/assets", можно изменить префикс, используемый для ресурсов, чтобы избежать конфликтов:
+* Если ваше приложение использует маршрут "/assets", можно изменить префикс, используемый для ассетов, чтобы избежать конфликтов:
```ruby
# Defaults to '/assets'
@@ -64,7 +66,7 @@ gem 'jquery-rails'
* Уберите настройку RJS `config.action_view.debug_rjs = true`.
-* Добавьте следующее, если хотите включить файлопровод.
+* Добавьте следующее, если хотите включить конвейер ресурсов.
```ruby
# Do not compress assets
@@ -76,7 +78,7 @@ gem 'jquery-rails'
#### config/environments/production.rb
-* Снова, большинство изменений относится к файлопроводу. Подробнее о них можно прочитать в руководстве [Asset Pipeline](/asset-pipeline).
+* Снова, большинство изменений относится к конвейеру ресурсов. Подробнее о них можно прочитать в руководстве [Asset Pipeline](/asset-pipeline).
```ruby
# Compress JavaScripts and CSS
@@ -92,7 +94,7 @@ gem 'jquery-rails'
# config.assets.manifest = YOUR_PATH
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
- # config.assets.precompile `= %w( search.js )
+ # config.assets.precompile `= %w( admin.js admin.css )
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
@@ -126,9 +128,9 @@ config.static_cache_control = "public, max-age=3600"
end
```
-#### Уберите опции :cache и :concat в хелперах ресурсов во вьюхах
+#### Уберите опции :cache и :concat в хелперах ассетов во вью
-* Вместе с Asset Pipeline опции :cache и :concat больше не используются, удалите эти опции из своих вьюх.
+* Вместе с Asset Pipeline опции :cache и :concat больше не используются, удалите эти опции из своих вью.
Создание приложения Rails 3.1
-----------------------------
@@ -143,7 +145,7 @@ $ cd myapp
Сейчас Rails использует `Gemfile` в корне приложения, чтобы определить гемы, требуемые для запуска вашего приложения. Этот `Gemfile` обрабатывается [Bundler](http://github.com/carlhuda/bundler), который затем устанавливает все зависимости. Он может даже установить все зависимости локально в ваше приложение, и оно не будет зависеть от системных гемов.
-Подробнее: - [домашняя страница bundler](http://gembundler.com)
+Подробнее: - [домашняя страница Bundler](https://bundler.io/)
### Живите на грани
@@ -153,7 +155,7 @@ $ cd myapp
$ rails new myapp --edge
```
-Если у вас есть локальная копия репозитория Rails, и вы хотите создать приложение с ее использованием, передайте флажок `--dev`:
+Если имеется локальная копия репозитория Rails, и необходимо сгенерировать приложение используя ее, передайте флажок `--dev`:
```bash
$ ruby /path/to/rails/railties/bin/rails new myapp --dev
@@ -162,19 +164,19 @@ $ ruby /path/to/rails/railties/bin/rails new myapp --dev
Архитектурные изменения Rails
-----------------------------
-### Файлопровод (Assets Pipeline)
+### Конвейер ресурсов (Assets Pipeline)
-Главное изменение в Rails 3.1 это Assets Pipeline. Он делает CSS и JavaScript первосортным кодом, и делает доступной надлежащую организацию, включая использование в плагинах и engine-ах.
+Основное изменение в Rails 3.1 это Assets Pipeline. Он делает CSS и JavaScript первосортным кодом, и делает доступной надлежащую организацию, включая использование в плагинах и engine-ах.
-Файлопровод работает с помощью [Sprockets](https://github.com/sstephenson/sprockets) и раскрывается в руководстве [Asset Pipeline](/asset-pipeline).
+Конвейер ресурсов работает с помощью [Sprockets](https://github.com/rails/sprockets) и раскрывается в руководстве [Asset Pipeline](/asset-pipeline).
### HTTP Streaming
-HTTP Streaming это другое новшество в Rails 3.1. Он позволяет браузеру загружать таблицы стилей и файлы JavaScript, пока сервер все еще создает отклик. Это требует Ruby 1.9.2, является опциональным, а также требует настройки веб-сервера, но популярная связка nginx и unicorn уже готова предоставлять это преимущество.
+HTTP Streaming это другое новшество в Rails 3.1. Он позволяет браузеру загружать таблицы стилей и файлы JavaScript, пока сервер все еще генерирует отклик. Это требует Ruby 1.9.2, является опциональным, а также требует настройки веб-сервера, но популярная связка NGINX и Unicorn уже готова предоставлять это преимущество.
### Библиотека JS по умолчанию теперь jQuery
-jQuery является библиотекой JavaScript по умолчанию, которая поствляется вместе с Rails 3.1. Но если вы используете Prototype, это просто переключить.
+jQuery является библиотекой JavaScript по умолчанию, которая поставляется вместе с Rails 3.1. Но если вы используете Prototype, это просто переключить.
```bash
$ rails new myapp -j prototype
@@ -191,15 +193,15 @@ Railties
* jQuery является новой библиотекой JavaScript по умолчанию.
-* jQuery и Prototype более не встроенные, а предоставляются как гемы jquery-rails и prototype-rails.
+* jQuery и Prototype более не встроенные, а предоставляются как гемы `jquery-rails` и `prototype-rails`.
-* Генератор приложения принимает опцию `-j`, которая может быть произвольной строкой. Если передать "foo", в `Gemfile` будет добавлен гем "foo-rails", и манифест JavaScript приложения затребует "foo" и "foo_ujs". В данный момент существуют только "prototype-rails" и "jquery-rails", и эти файлы предоставляются через файлопровод.
+* Генератор приложения принимает опцию `-j`, которая может быть произвольной строкой. Если передать "foo", в `Gemfile` будет добавлен гем "foo-rails", и манифест JavaScript приложения затребует "foo" и "foo_ujs". В данный момент существуют только "prototype-rails" и "jquery-rails", и эти файлы предоставляются через конвейер ресурсов.
-* Создание приложение или плагина запускает `bundle install`, если не определено `--skip-gemfile` или `--skip-bundle`.
+* Генерация приложение или плагина запускает `bundle install`, если не определено `--skip-gemfile` или `--skip-bundle`.
-* Генераторы контроллера и ресурса теперь автоматически создадут заглушки для ресурсов (это может быть отключено с помощью `--skip-assets`). Эти заглушки будут использовать CoffeeScript и Sass, если эти библиотеки доступны.
+* Генераторы контроллера и ресурса теперь автоматически создадут заглушки для ассетов (это может быть отключено с помощью `--skip-assets`). Эти заглушки будут использовать CoffeeScript и Sass, если эти библиотеки доступны.
-* Генераторы скаффолда и приложения используют стиль хэшей из Ruby 1.9, когда запущены на Ruby 1.9. Чтобы создать старый стиль хэшей, должно быть передано `--old-style-hash`.
+* Генераторы скаффолда и приложения используют стиль хэшей из Ruby 1.9, когда запущены на Ruby 1.9. Чтобы генерировать старый стиль хэшей, должно быть передано `--old-style-hash`.
* Генератор скаффолда контроллера создает блок формата для JSON вместо XML.
@@ -207,13 +209,13 @@ Railties
* Добавлена конфигурация `config.force_ssl`, загружающая промежуточную программу `Rack::SSL` и принуждающую все запросы быть под протоколом HTTPS.
-* Добавлена команда `rails plugin new`, создающая плагин Rails с gemspec, тестами и пустым приложением для тестирования.
+* Добавлена команда `rails plugin new`, генерирующая плагин Rails с gemspec, тестами и пустым приложением для тестирования.
* К стеку промежуточных программ по умолчанию добавлены `Rack::Etag` и `Rack::ConditionalGet`.
* К стеку промежуточных программ по умолчанию добавлена `Rack::Cache`.
-* Engine-ы получили большое обновление - их можно монтировать на любой путь, включать ресурсы. запускать генераторы и т.д.
+* Engine-ы получили большое обновление - их можно монтировать на любой путь, включать ассеты. запускать генераторы и т.д.
Action Pack
-----------
@@ -224,7 +226,7 @@ Action Pack
* Определите `force_ssl` в контроллере. чтобы принудить браузер передавать данные через протокол HTTPS на конкретно этот контроллер. Для ограничения отдельных экшнов могут быть использованы `:only` или `:except`.
-* Деликатные параметры строки запроса, определенные в `config.filter_parameters`, теперь будут отфильтрованы в логе и из пути запроса.
+* Чувствительные параметры строки запроса, определенные в `config.filter_parameters`, теперь будут отфильтрованы в логе и из пути запроса.
* Параметры URL, возвращающие `nil` на `to_param`. теперь будут убраны из строки запроса.
@@ -232,9 +234,9 @@ Action Pack
* Добавлен `config.action_controller.include_all_helpers`. По умолчанию выполняет `helper :all` в `ActionController::Base`, что включает все хелперы по умолчанию. Установка `include_all_helpers` в `false` приведет к включению только application_helper и хелпера. соответствующего контроллеру (подобно foo_helper для foo_controller).
-* `url_for` и именнованные хелперы _url теперь принимают как опции `:subdomain` и `:domain`.
+* `url_for` и именованные хелперы URL теперь принимают как опции `:subdomain` и `:domain`.
-* Добавлен `Base.http_basic_authenticate_with` для простой базовой аутентификации http с помощью единственного вызова метода класса.
+* Добавлен `Base.http_basic_authenticate_with` для базовой аутентификации HTTP с помощью единственного вызова метода класса.
```ruby
class PostsController < ApplicationController
@@ -283,9 +285,9 @@ Action Pack
end
```
- Можно ограничить некоторые экшны от этого с использованием `:only` или `:except`. Подробности можно прочитать в документации по [`ActionController::Streaming`](http://api.rubyonrails.org/v3.1.0/classes/ActionController/Streaming.html).
+ Можно ограничить некоторые экшны от этого с использованием `:only` или `:except`. Подробности можно прочитать в документации по [`ActionController::Streaming`](https://api.rubyonrails.org/v3.1.0/classes/ActionController/Streaming.html).
-* Маршрутный метод redirect теперь принимает хэш опций, меняющих только рассматриваемые части url, или объект, отвечающий на вызов, позволяя повторно использовать редиректы.
+* Маршрутный метод redirect теперь принимает хэш опций, меняющих только рассматриваемые части URL, или объект, отвечающий на вызов, позволяя повторно использовать редиректы.
### Action Dispatch
@@ -313,9 +315,9 @@ Action Pack
* Добавлен HTML5 хелпер `button_tag`.
-* `file_field` автоматически добавляет `:multipart => true` к нужным формам.
+* `file_field` автоматически добавляет `:multipart => true` к внешним формам.
-* Добавлена удобная идиома создавать HTML5 атрибуты data-* в хелперах тегов с хэшем опций `:data`:
+* Добавлена удобная идиома генерировать HTML5 атрибуты data-* в хелперах тегов с хэшем опций `:data`:
```ruby
tag("div", :data => {:name => 'Stephen', :city_state => %w(Chicago IL)})
@@ -332,7 +334,7 @@ Action Pack
* Вернули `config.action_view.cache_template_loading`, позволяющий решить, должны ли быть кэшированы шаблоны, или нет.
-* Хелпер формы submit более не создает id = "object_name_id".
+* Хелпер формы submit больше не генерирует id "object_name_id".
* Позволяет `FormHelper#form_for` определить `:method` как опцию первого уровня вместо вкладывания в хэш `:html`. `form_for(==@==post, remote: true, method: :delete)` вместо `form_for(==@==post, remote: true, html: { method: :delete })`.
@@ -380,13 +382,13 @@ Active Record
* `default_scope` теперь может принимать блок, lambda или любой другой объект, отвечающий на call для ленивых вычислений.
-* Скоупы по умолчанию теперь вычисляются в самый последний момент для избегания проблем, когда могут быть созданы скоупы, которые неявно содержат скоуп по умолчанию, от которого впоследствии невозможно будет избавиться с помощью Model.unscoped.
+* Дефолтные скоупы теперь вычисляются в самый последний момент для избегания проблем, когда могут быть созданы скоупы, которые неявно содержат дефолтный скоуп, от которого впоследствии невозможно будет избавиться с помощью Model.unscoped.
* Адаптер PostgreSQL теперь поддерживает только PostgreSQL версии 8.2 и выше.
* Промежуточная программа `ConnectionManagement` изменилась, чтобы очищать пул соединения после того, как тело rack было уничтожено.
-* В Active Record добавлен метод `update_column`. Этот новый метод обновляет заданный атрибут у объекта, пропуская валидации и колбэки. Рекомендовано использовать `update_attributes` или `update_attribute` если вы не уверенны, что не хотите выполнять какой-либо колбэк, включая изменение столбца `updated_at`. Он не может быть вызван на новых записях.
+* В Active Record добавлен метод `update_column`. Этот новый метод обновляет заданный атрибут у объекта, пропуская валидации и колбэки. Рекомендовано использовать `update_attributes` или `update_attribute` если вы не уверенны, что не хотите выполнять какой-либо колбэк, включая модификацию столбца `updated_at`. Он не может быть вызван на новых записях.
* Связи с опцией `:through` теперь могут использовать любые связи как посредника или источника, включая другие связи, имеющие опцию `:through`, и связи `has_and_belongs_to_many`.
@@ -404,7 +406,7 @@ Active Record
* Одиночные связи (`has_one`, `belongs_to`) больше не имеют прокси, и просто возвращают связанную запись или `nil`. Это означает, что больше не следует использовать недокументированные методы наподобие `bob.mother.create` - используйте вместо этого `bob.create_mother`.
-* Поддержка опции `:dependent` для связи `has_many :through`. По историческим и практическим причинам, `:delete_all` является стратегией удаления по умолчанию, используемой в `association.delete(*records)`, не смотря на то, что стратегией по умолчанию для обычного has_many является `:nullify`. Также, это работает только если вторая сторона связи belongs_to. В других ситуациях следует непосредственно изменить связь through.
+* Поддержка опции `:dependent` для связи `has_many :through`. По историческим и практическим причинам, `:delete_all` является стратегией удаления по умолчанию, используемой в `association.delete(*records)`, несмотря на то, что стратегией по умолчанию для обычного has_many является `:nullify`. Кроме того, это работает только при условии, что вторая сторона связи belongs_to. В других ситуациях следует напрямую модифицировать связь through.
* Изменилось поведение `association.destroy` для `has_and_belongs_to_many` и `has_many :through`. Теперь 'destroy' или 'delete' на связи будет означать 'избавиться от связи', а не (обязательно) 'избавиться от связанных записей'.
@@ -447,12 +449,12 @@ Active Record
```ruby
class FooMigration < ActiveRecord::Migration
def up # Не self.up
- ...
+ # ...
end
end
```
-* Файлы миграции созданные генераторами модели и конструктивной миграции (для примера, add_name_to_users), используют метод обратимой миграции `change` вместо обычных методов `up` и `down`.
+* Файлы миграции, сгенерированные с помощью генераторов модели и конструктивной миграции (для примера, add_name_to_users), используют метод обратимой миграции `change` вместо обычных методов `up` и `down`.
* Убрана поддержка интерполяции строк с условиями SQL на связях. Вместо этого должен быть использован proc.
@@ -480,7 +482,7 @@ Active Record
end
```
-* При создании модели по умолчанию добавляется `add_index` для столбцов `belongs_to` или `references`.
+* При генерации модели по умолчанию добавляется `add_index` для столбцов `belongs_to` или `references`.
* Установление id для объекта в `belongs_to` обновляет связь с объектом.
@@ -535,7 +537,7 @@ Active Support
* Был отрефакторен `ActiveSupport::Dependencies::Reference`, чтобы пользоваться преимуществами нового `ClassCache`.
-* Портирован `Range#cover?` как псевдоним `Range#include?` в Ruby 1.8.
+* Бэкпортирован `Range#cover?` как псевдоним `Range#include?` в Ruby 1.8.
* Добавлены `weeks_ago` и `prev_week` в Date/DateTime/Time.
diff --git a/source/3_2_release_notes.md b/source/3_2_release_notes.md
index b7215bb6..55519887 100644
--- a/source/3_2_release_notes.md
+++ b/source/3_2_release_notes.md
@@ -8,28 +8,30 @@
* Автоматические Explain для запросов
* Тегированное логирование
-Эти заметки о релизе покрывают основные обновления, но не включают все мелкие багфиксы и изменения. Чтобы увидеть все, обратитесь к [списку комитов](http://github.com/rails/rails/commits/3-2-stable) в главном репозитории Rails на GitHub.
+Эти заметки о релизе покрывают только основные изменения. Чтобы узнать о различных исправлениях программных ошибок и изменениях, обратитесь к логам изменений или к [списку коммитов](https://github.com/rails/rails/commits/3-2-stable) в главном репозитории Rails на GitHub.
-Обновление до Rails 3.2
------------------------
+--------------------------------------------------------------------------------
-Если обновляете существующее приложение, было бы хорошо иметь перед этим покрытие тестами. Также, до попытки обновиться до Rails 3.2, необходимо сначала обновиться до Rails 3.1 и убедиться, что приложение все еще выполняется так, как нужно. Затем нужно предпринять следующие изменения:
+Апгрейд до Rails 3.2
+--------------------
+
+Прежде чем апгрейднуть существующее приложение, было бы хорошо иметь перед этим покрытие тестами. Также, до попытки обновиться до Rails 3.2, необходимо сначала произвести апгрейд до Rails 3.1 и убедиться, что приложение все еще выполняется так, как нужно. Затем обратите внимание на следующие изменения:
### Rails 3.2 требует как минимум Ruby 1.8.7
-Rails 3.2 требует Ruby 1.8.7 или выше. Поддержка всех прежних версий Ruby была официально прекращена, и следует обновиться как можно быстрее. Rails 3.2 также совместим с Ruby 1.9.2.
+Rails 3.2 требует Ruby 1.8.7 или выше. Поддержка всех прежних версий Ruby была официально прекращена, и следует произвести апгрейд как можно раньше. Rails 3.2 также совместим с Ruby 1.9.2.
-TIP: Отметьте, что в Ruby 1.8.7 p248 и p249 имеются ошибки маршализации, ломающие Rails. Хотя в Ruby Enterprise Edition это было исправлено, начиная с релиза 1.8.7-2010.02. В ветке 1.9, Ruby 1.9.1 не пригоден к использованию, поскольку он иногда вылетает, поэтому, если хотите использовать 1.9.x перепрыгивайте на 1.9.2 для гладкой работы.
+TIP: Отметьте, что в Ruby 1.8.7 p248 и p249 имеются программные ошибки маршаллинга, ломающие Rails. Хотя в Ruby Enterprise Edition это было исправлено, начиная с релиза 1.8.7-2010.02. В ветке 1.9, Ruby 1.9.1 не пригоден к использованию, поскольку он иногда вылетает, поэтому, если хотите использовать 1.9.x перепрыгивайте на 1.9.2 для гладкой работы.
### Что обновить в приложении
-* Обновите зависимости в вашем Gemfile
+* Обновите зависимости в вашем `Gemfile`
* `rails = 3.2.0`
* `sass-rails ~> 3.2.3`
* `coffee-rails ~> 3.2.1`
* `uglifier >= 1.0.3`
-* В Rails 3.2 устаревает `vendor/plugins`, а в Rails 4.0 будет убрано окончательно. Можете начинать перемещать эти плагины, выделяя их в гемы и добавляя в свой Gemfile. Если вы не хотите делать из них гемы, можно их переместить, скажем в `lib/my_plugin/*`, и добавить соответствующий инициализатор в `config/initializers/my_plugin.rb`.
+* В Rails 3.2 устаревает `vendor/plugins`, а в Rails 4.0 будет убрано окончательно. Можете начинать перемещать эти плагины, выделяя их в гемы и добавляя в свой `Gemfile`. Если вы не хотите делать из них гемы, можно их переместить, скажем в `lib/my_plugin/*`, и добавить соответствующий инициализатор в `config/initializers/my_plugin.rb`.
* Имеется ряд новых конфигурационных изменений, которые можно добавить в `config/environments/development.rb`:
@@ -57,8 +59,8 @@ TIP: Отметьте, что в Ruby 1.8.7 p248 и p249 имеются ошиб
ENGINE_ROOT = File.expand_path('../..', __FILE__)
ENGINE_PATH = File.expand_path('../../lib/your_engine_name/engine', __FILE__)
-require 'rails/all'
-require 'rails/engine/commands'
+require "rails/all"
+require "rails/engine/commands"
```
Создание приложения Rails 3.2
@@ -74,7 +76,7 @@ $ cd myapp
Сейчас Rails использует `Gemfile` в корне приложения, чтобы определить гемы, требуемые для запуска вашего приложения. Этот `Gemfile` обрабатывается [Bundler](http://github.com/carlhuda/bundler), который затем устанавливает все зависимости. Он может даже установить все зависимости локально в ваше приложение, и оно не будет зависеть от системных гемов.
-Подробнее: - [домашняя страница Bundler](http://gembundler.com)
+Подробнее: - [домашняя страница Bundler](https://bundler.io/)
### Живите на грани
@@ -84,7 +86,7 @@ $ cd myapp
$ rails new myapp --edge
```
-Если у вас есть локальная копия репозитория Rails, и вы хотите создать приложение с ее использованием, передайте флажок `--dev`:
+Если имеется локальная копия репозитория Rails, и необходимо сгенерировать приложение используя ее, передайте флажок `--dev`:
```bash
$ ruby /path/to/rails/railties/bin/rails new myapp --dev
@@ -99,13 +101,13 @@ $ ruby /path/to/rails/railties/bin/rails new myapp --dev
### Автоматические Explain запросов
-Rails 3.2 поставляется с прекрасной возможностью раскрытия запросов, созданных ARel, определив метод `explain` в `ActiveRecord::Relation`. Для примера, можно запустить что-то наподобие `puts Person.active.limit(5).explain` и результат запроса Arel будет раскрыт. Это позволяет проверку правильности индексирования и дальнейшую оптимизацию.
+Rails 3.2 поставляется с прекрасной возможностью раскрытия запросов, сгенерированных Arel, определив метод `explain` в `ActiveRecord::Relation`. Для примера, можно запустить что-то наподобие `puts Person.active.limit(5).explain` и результат запроса Arel будет раскрыт. Это позволяет проверку правильности индексирования и дальнейшую оптимизацию.
Запросы, выполняющиеся более чем пол секунды, *автоматически* раскрываются в режиме development. Это поведение, разумеется, может быть изменено.
### Тегированное логирование
-При запуске многопользовательского приложения может сильно помочь фильтрация в логе, кто что делал. TaggedLogging в Active Support помогает это сделать точным, помечая строки лога поддоменами, id запросов и чем угодно, что поможет вам отладить такие приложения.
+При запуске многопользовательского приложения может сильно помочь фильтрация в логе, кто что делал. TaggedLogging в Active Support помогает это сделать точным, помечая строчки лога поддоменами, id запросов и чем угодно, что поможет вам отладить такие приложения.
Документация
------------
@@ -123,7 +125,7 @@ Railties
* Добавлена промежуточная программа `DebugExceptions`, содержащая особенности, извлеченные из промежуточной программы `ShowExceptions`.
-* Отображает маршруты монтированных engines-ов в `rake routes`.
+* Отображает маршруты монтированных engine-ов в `rake routes`.
* Позволяет изменить порядок загрузки railties с помощью `config.railties_order` следующим образом:
@@ -133,7 +135,7 @@ Railties
* Скаффолд возвращает 204 No Content для API запросов без содержимого. Это позволяет скаффолду работать с jQuery "из коробки".
-* Обновлена промежуточная программа `Rails::Rack::Logger`, чтобы добавлять любые теги, установленные в `config.log_tags`, в `ActiveSupport::TaggedLogging`. Это позволяет легко тегировать строки лога отладочной информацией, такой как поддомен и id запроса -- оба очень полезны при отладке production многопользовательских приложений.
+* Обновлена промежуточная программа `Rails::Rack::Logger`, чтобы добавлять любые теги, установленные в `config.log_tags`, в `ActiveSupport::TaggedLogging`. Это позволяет легко тегировать строчки лога отладочной информацией, такой как поддомен и id запроса -- оба очень полезны при отладке production многопользовательских приложений.
* Опции по умолчанию для `rails new` могут быть установлены в `~/.railsrc`. Можно указать дополнительные аргументы командной строки, используемые каждый раз при запуске 'rails new', в конфигурационном файле `.railsrc` в домашней директории.
@@ -143,13 +145,13 @@ Railties
* Позволяет генераторам скаффолда/модели/миграции принимать модификаторы "index" и "uniq". Например,
- ```ruby
- rails g scaffold Post title:string:index author:uniq price:decimal{7,2}
+ ```bash
+ $ bin/rails g scaffold Post title:string:index author:uniq price:decimal{7,2}
```
создаст индексы для `title` и `author`, причем последний будет уникальным индексом. Некоторые типы, такие как decimal, принимают произвольные опции. В примере `price` будет столбцом decimal с установленными точностью и масштабом 7 и 2 соответственно.
-* Гем Turn был убран из дефолтного Gemfile.
+* Гем Turn был убран из дефолтного `Gemfile`.
* Убран старый генератор плагинов `rails generate plugin` в пользу команды `rails plugin new`.
@@ -162,7 +164,7 @@ Railties
Action Mailer
-------------
-* Обновлена версия `mail` до 2.4.0.
+* Апгрейд версия `mail` до 2.4.0.
* Убрано старое Action Mailer API, которое было объявлено устаревшим в Rails 3.0.
@@ -173,7 +175,7 @@ Action Pack
* `ActiveSupport::Benchmarkable` стал модулем по умолчанию для `ActionController::Base,` таким образом, метод `#benchmark` снова доступен в контексте контроллера, как это было раньше.
-* Добавлена опция `:gzip` в `caches_page`. Опция по умолчанию может быть настроена глобально с использованием `page_cache_compression`.
+* Добавлена опция `:gzip` в `caches_page`. Дефолтная опция может быть настроена глобально с использованием `page_cache_compression`.
* Теперь Rails будет использовать ваш макет по умолчанию (такой как "layouts/application") при определенных условий `:only` и `:except`, и если они не выполняются.
@@ -185,15 +187,15 @@ Action Pack
Rails будет использовать 'layouts/single_car' если запрос придет в экшн `:show`, и использовать `layouts/application` (или `layouts/cars`, если он существует), если запрос придет в любой другой экшн.
-* `form_for` изменился и использует `#{action}_#{as}` как класс css и id, если представлена опция `:as`. Ранние версии использовали `#{as}_#{action}`.
+* `form_for` изменился и использует `#{action}_#{as}` как класс CSS и id, если предоставлена опция `:as`. Ранние версии использовали `#{as}_#{action}`.
-* `ActionController::ParamsWrapper` на моделях Active Record теперь оборачивают атрибуты `attr_accessible` только если они существуют. Если нет, будут обернуты только атрибуты, возвращенные методом класса `attribute_names`. Это устраняет оборачивание вложенных атрибутов при помещении их в `attr_accessible`.
+* `ActionController::ParamsWrapper` на моделях Active Record теперь оборачивают атрибуты `attr_accessible`, только если они существуют. Если нет, будут обернуты только атрибуты, возвращенные методом класса `attribute_names`. Это устраняет оборачивание вложенных атрибутов при помещении их в `attr_accessible`.
* Пишет в лог "Filter chain halted as CALLBACKNAME rendered or redirected" каждый раз при прерывании предварительного колбэка.
-* Проведен рефакторинг `ActionDispatch::ShowExceptions`. Контроллер ответственнен за выбор как показывать исключения. В контроллере возможно переопределить `show_detailed_exceptions?`, чтобы определить, какие запросы должны предоставлять отладочную информацию при ошибках.
+* Проведен рефакторинг `ActionDispatch::ShowExceptions`. Контроллер ответственен за выбор как показывать исключения. В контроллере возможно переопределить `show_detailed_exceptions?`, чтобы определить, какие запросы должны предоставлять отладочную информацию при ошибках.
-* Responders теперь возвращают 204 No Content для API запросов без тела запроса (как в новых скаффолдах).
+* Responders теперь возвращают 204 No Content для API запросов без тела отклика (как в новых скаффолдах).
* Проведен рефакторинг куки `ActionController::TestCase`. Назначаемые куки для тестовых случаев теперь должны использовать `cookies[]`
@@ -211,7 +213,7 @@ Action Pack
assert_nil cookies[:email]
```
- Больше не пишется HTTP_COOKIE и куки сохраняются между запросами, поэтому если нужно манипулировать средой для вашего теста, это нужно сделать до того, как куки будут созданы.
+ Больше не пишется HTTP_COOKIE и куки теперь персистентные между запросами, поэтому если нужно манипулировать средой для вашего теста, это нужно сделать до того, как куки будут созданы.
* `send_file` теперь угадывает тип MIME по расширению файла, если не предоставлен `:type`.
@@ -221,7 +223,7 @@ Action Pack
* Изменен уровень лога для предупреждения об отсутствующем токене CSRF с `:debug` до `:warn`.
-* По умолчанию ресурсы должны использовать протокол запроса или протокол по умолчанию, если запрос не доступен.
+* По умолчанию ассеты должны использовать протокол запроса или протокол по умолчанию, если запрос недоступен.
#### Устаревания
@@ -252,7 +254,7 @@ Action Pack
* Добавлена промежуточная программа `ActionDispatch::RequestId`, создающая уникальный заголовок X-Request-Id, доступный в отклике, и включает метод `ActionDispatch::Request#uuid`. Это позволяет легко отслеживать запросы от начала до конца в стеке и идентифицировать отдельные запросы в смешанных логах, наподобие Syslog.
-* Промежуточная программа `ShowExceptions` теперь принимает приложение для обработки исключений, ответственное за рендеринг исключения при ошибках приложения. Приложение запускется с копией исключения в `env["action_dispatch.exception"]`, и с переписанным `PATH_INFO` в код статуса.
+* Промежуточная программа `ShowExceptions` теперь принимает приложение для обработки исключений, ответственное за рендеринг исключения при ошибках приложения. Приложение запускается с копией исключения в `env["action_dispatch.exception"]`, и с переписанным `PATH_INFO` в код статуса.
* Позволяет настроить отклики rescue с помощью railtie, как в `config.action_dispatch.rescue_responses`.
@@ -272,7 +274,7 @@ Action Pack
* Хелперы дат принимают новую опцию `:use_two_digit_numbers => true`, отрисовывающую селект-боксы для месяцев и дней с ведущим нулем без изменения соответствующих value. Для примера, это полезно для отображения дат в стиле ISO 8601, таких как '2011-08-01'.
-* Для вашей формы можно предоставить пространство имен для обеспечения уникальности атрибута id у элементов формы. В созданном HTML id пространство имен атрибута будет идти впереди с подчеркиванием.
+* Для вашей формы можно предоставить пространство имен для обеспечения уникальности атрибута id у элементов формы. В сгенерированном HTML id пространство имен атрибута будет идти впереди с подчеркиванием.
```ruby
<%= form_for(@offer, :namespace => 'namespace') do |f| %>
@@ -281,14 +283,14 @@ Action Pack
<% end %>
```
-* Ограничено количество вариантов для `select_year` в 1000. Передайте опцию `:max_years_allowed` для установки своего лимита.
+* Ограничено количество пунктов списка для `select_year` в 1000. Передайте опцию `:max_years_allowed` для установки своего лимита.
* Теперь `content_tag_for` и `div_for` могут принимать коллекцию записей. Они также передадут запись как первый аргумент, если вы вставите получаемый аргумент в блок. Таким образом, вместо этого:
```ruby
@items.each do |item|
content_tag_for(:li, item) do
- Title: <%= item.title %>
+ Title: <%= item.title %>
end
end
```
@@ -301,11 +303,11 @@ Action Pack
end
```
-* Добавлен метод хелпера `font_path`, вычисляющий путь к ресурсу шрифта в `public/fonts`.
+* Добавлен метод хелпера `font_path`, вычисляющий путь к ассету шрифта в `public/fonts`.
#### Устаревания
-* Передача форматов или обработчиков в render :template и тому подобные методы, например `render :template => "foo.html.erb"`, устарела. Вместо этого можно предоставить непосредственно :handlers и :formats как опции: ` render :template => "foo", :formats => [:html, :js], :handlers => :erb`.
+* Передача форматов или обработчиков в render :template и тому подобные методы, например `render :template => "foo.html.erb"`, устарела. Вместо этого можно предоставить непосредственно :handlers и :formats как опции: `render :template => "foo", :formats => [:html, :js], :handlers => :erb`.
### Sprockets
@@ -320,11 +322,11 @@ Active Record
* Реализован `ActiveRecord::Relation#explain`.
-* Реализован `AR::Base.silence_auto_explain`, позволяющий пользователю выборочно отключать автоматические EXPLAIN в блоке.
+* Реализован `ActiveRecord::Base.silence_auto_explain`, позволяющий пользователю выборочно отключать автоматические EXPLAIN в блоке.
* Реализовано логирование автоматического EXPLAIN для медленных запросов. Новый конфигурационный параметр `config.active_record.auto_explain_threshold_in_seconds` определяет, что рассматривается как медленный запрос. Установите ему nil, чтобы отключить эту возможность. По умолчанию 0.5 в режиме development, и nil в режимах test и production. Rails 3.2 поддерживает эту возможность для SQLite, MySQL (адаптер mysql2) и PostgreSQL.
-* Добавлен `ActiveRecord::Base.store` для определения простых одноколоночных хранилищ key/value.
+* Добавлен `ActiveRecord::Base.store` для определения простых key/value хранилищ с одним столбцом.
```ruby
class User < ActiveRecord::Base
@@ -332,8 +334,8 @@ Active Record
end
u = User.new(color: 'black', homepage: '37signals.com')
- u.color # Accessor stored attribute
- u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor
+ u.color # Акцессор хранимого атрибута
+ u.settings[:country] = 'Denmark' # Любой атрибут, даже если не указать через акцессор
```
* Добавлена возможность запуска миграций только для определенного пространства имен, позволяющая запустить миграции только для одного engine (например, чтобы откатить изменения от engine, чтобы убрать его).
@@ -351,9 +353,9 @@ Active Record
# SELECT id from clients where active = 1
```
-* Методы созданных связей создаются в отдельном модуле, чтобы позволить переопределение и компоновку. Для класса с именем MyModel, модель будет называться `MyModel::GeneratedFeatureMethods`. Он включается в класс модели сразу после модуля `generated_attributes_methods`, определенного в Active Model, таким образом, методы связей переопределяют методы атрибутов с таким же именем.
+* Методы сгенерированных связей создаются в отдельном модуле, чтобы позволить переопределение и компоновку. Для класса с именем MyModel, модель будет называться `MyModel::GeneratedFeatureMethods`. Он включается в класс модели сразу после модуля `generated_attributes_methods`, определенного в Active Model, таким образом, методы связей переопределяют методы атрибутов с таким же именем.
-* Добавлен `ActiveRecord::Relation#uniq` для создания уникальных запросов.
+* Добавлен `ActiveRecord::Relation#uniq` для генерации уникальных запросов.
```ruby
Client.select('DISTINCT name')
@@ -455,7 +457,6 @@ Active Record
end
Post.table_name # => "special_posts"
-
```
Active Model
@@ -500,9 +501,9 @@ Active Support
* `ActiveSupport::Notifications.subscribed` предоставляет подписки на события, пока выполняется блок.
-* Опеределены новые методы `Module#qualified_const_defined?`, `Module#qualified_const_get` и `Module#qualified_const_set`, являющиеся аналогами соответствующих методов в стандартном API, но принимающие полные имена констант.
+* Определены новые методы `Module#qualified_const_defined?`, `Module#qualified_const_get` и `Module#qualified_const_set`, являющиеся аналогами соответствующих методов в стандартном API, но принимающие ограниченные имена констант.
-* Добавлен `#deconstantize`, дополняющий `#demodulize` в словообразовании. Он убирает самый правый сегмент в полном имени константы.
+* Добавлен `#deconstantize`, дополняющий `#demodulize` в словообразовании. Он убирает самый правый сегмент в ограниченном имени константы.
* Добавлен `safe_constantize`, преобразующий строку в константу, но возвращающий `nil` вместо исключения, если константа (или ее часть) не существует.
@@ -514,7 +515,7 @@ Active Support
* Инфлектор понимает акронимы.
-* Добавлены `Time#all_day`, `Time#all_week`, `Time#all_quarter` и `Time#all_year` как способ создание интервалов.
+* Добавлены `Time#all_day`, `Time#all_week`, `Time#all_quarter` и `Time#all_year` как способ генерации интервалов.
```ruby
Event.where(:created_at => Time.now.all_week)
@@ -545,7 +546,7 @@ Active Support
* Поведение `ActiveSupport::BufferedLogger's` в части автоматического создания директории для файла лога устарело. Пожалуйста, убедитесь до инициализации, что директория для файла лога создана.
-* Устарел `ActiveSupport::BufferedLogger#auto_flushing` . Или установите уровень синхронизации на соответствующем файловом дескрипторе следующим образом. Или настройте свою файловую систему. Теперь очистку контролирует кэш файловой системы.
+* Устарел `ActiveSupport::BufferedLogger#auto_flushing`. Или установите уровень синхронизации на соответствующем файловом дескрипторе следующим образом. Или настройте свою файловую систему. Теперь очистку контролирует кэш файловой системы.
```ruby
f = File.open('foo.log', 'w')
diff --git a/source/4_0_release_notes.md b/source/4_0_release_notes.md
index 8f4792b5..ecea9f83 100644
--- a/source/4_0_release_notes.md
+++ b/source/4_0_release_notes.md
@@ -5,23 +5,21 @@
* Ruby 2.0 предпочтителен; 1.9.3+ требуется
* Строгие параметры (Strong Parameters)
-* Турболинки (Turbolinks)
+* Turbolinks
* Кэширование "матрешкой" (Russian Doll Caching)
-Эти заметки о релизе покрывают только основные обновления. Чтобы узнать о различных багфиксах и изменениях, обратитесь к логам изменений или к [списку комитов](https://github.com/rails/rails/commits/master) в главном репозитории Rails на GitHub.
+Эти заметки о релизе покрывают только основные изменения. Чтобы узнать о различных исправлениях программных ошибок и изменениях, обратитесь к логам изменений или к [списку коммитов](https://github.com/rails/rails/commits/4-0-stable) в главном репозитории Rails на GitHub.
-Обновление до Rails 4.0
------------------------
-
-Если обновляете существующее приложение, было бы хорошо иметь перед этим покрытие тестами. Также, до попытки обновиться до Rails 4.0, необходимо сначала обновиться до Rails 3.2 и убедиться, что приложение все еще выполняется так, как нужно. Список вещей, которые нужно выполнить при обновлении доступен в руководстве [Обновление Ruby on Rails](/upgrading-ruby-on-rails#upgrading-from-rails-3-2-to-rails-4-0).
+Апгрейд до Rails 4.0
+--------------------
-TODO: Configuration changes in environment files
+Прежде чем апгрейднуть существующее приложение, было бы хорошо иметь перед этим покрытие тестами. Также, до попытки обновиться до Rails 4.0, необходимо сначала произвести апгрейд до Rails 3.2 и убедиться, что приложение все еще выполняется так, как нужно. Список вещей, которые нужно выполнить для апгрейда доступен в руководстве [Апгрейд Ruby on Rails](/upgrading-ruby-on-rails#upgrading-from-rails-3-2-to-rails-4-0)
Создание приложения Rails 4.0
-----------------------------
-```
- Необходим установленный RubyGem 'rails'
+```bash
+# Необходим установленный RubyGem 'rails'
$ rails new myapp
$ cd myapp
```
@@ -30,65 +28,68 @@ $ cd myapp
Сейчас Rails использует `Gemfile` в корне приложения, чтобы определить гемы, требуемые для запуска вашего приложения. Этот `Gemfile` обрабатывается гемом [Bundler](http://github.com/carlhuda/bundler), который затем устанавливает все зависимости. Он может даже установить все зависимости локально в ваше приложение, и оно не будет зависеть от системных гемов.
-Подробнее: - [Bundler homepage](http://gembundler.com)
+Подробнее: - [домашняя страница Bundler](https://bundler.io)
### Живите на грани
`Bundler` и `Gemfile` замораживает ваше приложение Rails с помощью новой отдельной команды `bundle`. Если хотите установить напрямую из репозитория Git, передайте флажок `--edge`:
-```
+```bash
$ rails new myapp --edge
```
-Если у вас есть локальная копия репозитория Rails, и вы хотите создать приложение с ее использованием, передайте флажок `--dev`:
+Если имеется локальная копия репозитория Rails, и необходимо сгенерировать приложение используя ее, передайте флажок `--dev`:
-```
+```bash
$ ruby /path/to/rails/railties/bin/rails new myapp --dev
```
Основные особенности
--------------------
-[](/images/rails4_features.png)
+[](4_0_release_notes/rails4_features.png)
-### Обновление
+### Апгрейд
- * **Ruby 1.9.3** ([коммит](https://github.com/rails/rails/commit/a0380e808d3dbd2462df17f5d3b7fcd8bd812496)) - Предпочтителен Ruby 2.0; требуется 1.9.3+
- * **[Новая политика устареваний](http://www.youtube.com/watch?v=z6YgD6tVPQs)** - Устаревшие особенности показывают предупреждения в Rails 4.0, и будут убраны в Rails 4.1.
- * **Кэширование страниц и экшнов ActionPack** ([коммит](https://github.com/rails/rails/commit/b0a7068564f0c95e7ef28fc39d0335ed17d93e90)) - Кэширование страниц и экшнов было извлечено в отдельный гем. Кэширование страниц и экшнов требовало слишком много человеческого вмешательства (вручную прекращать кэш, когда обновляются лежащие в основе объекты модели). Вместо этого используйте кэширование по принципу "русской матрешки" (Russian doll caching).
- * **Обсерверы ActiveRecord** ([коммит](https://github.com/rails/rails/commit/ccecab3ba950a288b61a516bf9b6962e384aae0b)) - Обсерверы извелчены в отдельный гем. Обсерверы требовались только для кэширования страниц и экшнов и могли привести к спагетти-коду.
- * **Хранилище сессии ActiveRecord** ([коммит](https://github.com/rails/rails/commit/0ffe19056c8e8b2f9ae9d487b896cad2ce9387ad)) - Хранилище сессии ActiveRecord извлечено в отдельный гем. Хранение сессий в SQL затратное. Используйте вместо него сессии куки, сессии memcache или произвольные хранилища сессии.
- * **Защита от массового нащначения ActiveModel** ([коммит](https://github.com/rails/rails/commit/f8c9a4d3e88181cee644f91e1342bfe896ca64c6)) - Защита от массового назначения Rails 3 устарела. Вместо нее исользуйте строгие параметры (strong parameters).
- * **ActiveResource** ([коммит](https://github.com/rails/rails/commit/f1637bf2bb00490203503fbd943b73406e043d1d)) - ActiveResource извлечен в отдельный гем. ActiveResource не был широко используемым.
- * **убраны vendor/plugins** ([коммит](https://github.com/rails/rails/commit/853de2bd9ac572735fa6cf59fcf827e485a231c3)) - Для управления установленными гемами используйте Gemfile.
+* **Ruby 1.9.3** ([коммит](https://github.com/rails/rails/commit/a0380e808d3dbd2462df17f5d3b7fcd8bd812496)) - Предпочтителен Ruby 2.0; требуется 1.9.3+
+* **[Новая политика устареваний](https://www.youtube.com/watch?v=z6YgD6tVPQs)** - Устаревшие особенности показывают предупреждения в Rails 4.0, и будут убраны в Rails 4.1.
+* **Кэширование страниц и экшнов ActionPack** ([коммит](https://github.com/rails/rails/commit/b0a7068564f0c95e7ef28fc39d0335ed17d93e90)) - Кэширование страниц и экшнов было извлечено в отдельный гем. Кэширование страниц и экшнов требовало слишком много человеческого вмешательства (вручную прекращать кэш, когда обновляются лежащие в основе объекты модели). Вместо этого используйте кэширование по принципу "русской матрешки" (Russian doll caching).
+* **Обсерверы ActiveRecord** ([коммит](https://github.com/rails/rails/commit/ccecab3ba950a288b61a516bf9b6962e384aae0b)) - Обсерверы извлечены в отдельный гем. Обсерверы требовались только для кэширования страниц и экшнов и могли привести к спагетти-коду.
+* **Хранилище сессии ActiveRecord** ([коммит](https://github.com/rails/rails/commit/0ffe19056c8e8b2f9ae9d487b896cad2ce9387ad)) - Хранилище сессии ActiveRecord извлечено в отдельный гем. Хранение сессий в SQL затратное. Используйте вместо него сессии куки, сессии memcache или произвольные хранилища сессии.
+* **Защита от массового назначения ActiveModel** ([коммит](https://github.com/rails/rails/commit/f8c9a4d3e88181cee644f91e1342bfe896ca64c6)) - Защита от массового назначения Rails 3 устарела. Вместо нее используйте строгие параметры (strong parameters).
+* **ActiveResource** ([коммит](https://github.com/rails/rails/commit/f1637bf2bb00490203503fbd943b73406e043d1d)) - ActiveResource извлечен в отдельный гем. ActiveResource не был широко используемым.
+* **убраны vendor/plugins** ([коммит](https://github.com/rails/rails/commit/853de2bd9ac572735fa6cf59fcf827e485a231c3)) - Для управления установленными гемами используйте `Gemfile`.
### ActionPack
- * **Strong parameters** ([коммит](https://github.com/rails/rails/commit/a8f6d5c6450a7fe058348a7f10a908352bb6c7fc)) - Позволяет обновлять объекты модели только разрешенными параметрами (`params.permit(:title, :text)`).
- * **Routing concerns** ([коммит](https://github.com/rails/rails/commit/0dd24728a088fcb4ae616bb5d62734aca5276b1b)) - В маршрутном DSL, выделяет общие суб-маршруты (`comments` из `/posts/1/comments` and `/videos/1/comments`).
- * **ActionController::Live** ([коммит](https://github.com/rails/rails/commit/af0a9f9eefaee3a8120cfd8d05cbc431af376da3)) - Потоковый JSON с помощью `response.stream`.
- * **Декларативные ETags** ([коммит](https://github.com/rails/rails/commit/ed5c938fa36995f06d4917d9543ba78ed506bb8d)) - Добавляет на уровне контроллера дополнения к etag, которые будут частью вычисления etag.
- * **[Кэширование Russian doll](http://37signals.com/svn/posts/3113-how-key-based-cache-expiration-works)** ([коммит](https://github.com/rails/rails/commit/4154bf012d2bec2aae79e4a49aa94a70d3e91d49)) - Кэширует вложенные фрагменты вьюх. Каждый фрагмент прекращается на основе набора зависимостей (ключа кэширования). Ключ кэширования - это обычно версия шаблона и объект модели.
- * **Turbolinks** ([коммит](https://github.com/rails/rails/commit/e35d8b18d0649c0ecc58f6b73df6b3c8d0c6bb74)) - Обслуживает только первую страницу HTML. Когда пользователь переходит на следующую страницу, использует pushState для обновления URL и использует AJAX для обновления title и body.
- * **Извлечение ActionView из ActionController** ([коммит](https://github.com/rails/rails/commit/78b0934dd1bb84e8f093fb8ef95ca99b297b51cd)) - ActionView был отделен от ActionPack, и будет вынесен в отдельный гем в Rails 4.1.
- * **Независимость от ActiveModel** ([коммит](https://github.com/rails/rails/commit/166dbaa7526a96fdf046f093f25b0a134b277a68)) - ActionPack больше не зависит от ActiveModel.
+* **Strong parameters** ([коммит](https://github.com/rails/rails/commit/a8f6d5c6450a7fe058348a7f10a908352bb6c7fc)) - Позволяет обновлять объекты модели только разрешенными параметрами (`params.permit(:title, :text)`).
+* **Routing concerns** ([коммит](https://github.com/rails/rails/commit/0dd24728a088fcb4ae616bb5d62734aca5276b1b)) - В маршрутном DSL, выделяет общие подмаршруты (`comments` из `/posts/1/comments` and `/videos/1/comments`).
+* **ActionController::Live** ([коммит](https://github.com/rails/rails/commit/af0a9f9eefaee3a8120cfd8d05cbc431af376da3)) - Потоковый JSON с помощью `response.stream`.
+* **Декларативные ETags** ([коммит](https://github.com/rails/rails/commit/ed5c938fa36995f06d4917d9543ba78ed506bb8d)) - Добавляет на уровне контроллера дополнения к etag, которые будут частью вычисления etag.
+* **[Кэширование Russian doll](https://37signals.com/svn/posts/3113-how-key-based-cache-expiration-works)** ([коммит](https://github.com/rails/rails/commit/4154bf012d2bec2aae79e4a49aa94a70d3e91d49)) - Кэширует вложенные фрагменты вью. Каждый фрагмент прекращается на основе набора зависимостей (ключа кэширования). Ключ кэширования - это обычно версия шаблона и объект модели.
+* **Turbolinks** ([коммит](https://github.com/rails/rails/commit/e35d8b18d0649c0ecc58f6b73df6b3c8d0c6bb74)) - Обслуживает только первую страницу HTML. Когда пользователь переходит на следующую страницу, использует pushState для обновления URL и использует AJAX для обновления title и body.
+* **Извлечение ActionView из ActionController** ([коммит](https://github.com/rails/rails/commit/78b0934dd1bb84e8f093fb8ef95ca99b297b51cd)) - ActionView был отделен от ActionPack, и будет вынесен в отдельный гем в Rails 4.1.
+* **Независимость от ActiveModel** ([коммит](https://github.com/rails/rails/commit/166dbaa7526a96fdf046f093f25b0a134b277a68)) - ActionPack больше не зависит от ActiveModel.
### Основное
- * **ActiveModel::Model** ([коммит](https://github.com/rails/rails/commit/3b822e91d1a6c4eab0064989bbd07aae3a6d0d08)) - `ActiveModel::Model` - это миксин, чтобы обычные объекты Ruby могли работать с ActionPack "из коробки" (например, `form_for`).
- * **Новый API скоупов** ([коммит](https://github.com/rails/rails/commit/50cbc03d18c5984347965a94027879623fc44cce)) - Скоупы должны быть всегда вызываемыми.
- * **Выгрузка кэша схемы** ([коммит](https://github.com/rails/rails/commit/5ca4fc95818047108e69e22d200e7a4a22969477)) - Чтобы улучшить время загрузки Rails, вместо загрузки схемы непосредствненно из базы данных, загружает схему из файла выгрузки.
- * **Поддержка указания уровня изоляции транзакции** ([коммит](https://github.com/rails/rails/commit/392eeecc11a291e406db927a18b75f41b2658253)) - Выбирайте, что более важно - повторяемые чтения или улучшенное быстродействие (менее блокирующее).
- * **Dalli** ([коммит](https://github.com/rails/rails/commit/82663306f428a5bbc90c511458432afb26d2f238)) - Используется клиент Dalli в качестве хранилища сессии в memcache.
- * **start & finish для уведомлений** ([коммит](https://github.com/rails/rails/commit/f08f8750a512f741acb004d0cebe210c5f949f28)) - Инструменты Active Support сообщают подписчикам о начале и завершении уведомлений.
- * **Тредобезопасность по умолчанию** ([коммит](https://github.com/rails/rails/commit/5d416b907864d99af55ebaa400fff217e17570cd)) - Rails может быть запущен на тредовых серверах приложений без дополнительных настроек. Заметка: Проверьте, что используемые вами гемы тредобезопасны.
- * **Метод PATCH** ([коммит](https://github.com/rails/rails/commit/eed9f2539e3ab5a68e798802f464b8e4e95e619e)) - В Rails PATCH заменил PUT. PATCH использется для частичного обновления ресурсов.
+* **ActiveModel::Model** ([коммит](https://github.com/rails/rails/commit/3b822e91d1a6c4eab0064989bbd07aae3a6d0d08)) - `ActiveModel::Model` - это миксин, чтобы обычные объекты Ruby могли работать с ActionPack "из коробки" (например, `form_for`).
+* **Новый API скоупов** ([коммит](https://github.com/rails/rails/commit/50cbc03d18c5984347965a94027879623fc44cce)) - Скоупы должны быть всегда вызываемыми.
+* **Выгрузка кэша схемы** ([коммит](https://github.com/rails/rails/commit/5ca4fc95818047108e69e22d200e7a4a22969477)) - Чтобы улучшить время загрузки Rails, вместо загрузки схемы непосредственно из базы данных, загружает схему из файла выгрузки.
+* **Поддержка указания уровня изоляции транзакции** ([коммит](https://github.com/rails/rails/commit/392eeecc11a291e406db927a18b75f41b2658253)) - Выбирайте, что более важно - повторяемые чтения или улучшенное быстродействие (менее блокирующее).
+* **Dalli** ([коммит](https://github.com/rails/rails/commit/82663306f428a5bbc90c511458432afb26d2f238)) - Используется клиент Dalli в качестве хранилища сессии в memcache.
+* **start & finish для уведомлений** ([коммит](https://github.com/rails/rails/commit/f08f8750a512f741acb004d0cebe210c5f949f28)) - Инструменты Active Support сообщают подписчикам о начале и завершении уведомлений.
+* **Тредобезопасность по умолчанию** ([коммит](https://github.com/rails/rails/commit/5d416b907864d99af55ebaa400fff217e17570cd)) - Rails может быть запущен на тредовых серверах приложений без дополнительных настроек. Заметка: Проверьте, что используемые вами гемы тредобезопасны.
+
+NOTE: Убедитесь, что используемые вами гемы тредобезопасны.
+
+* **Метод PATCH** ([коммит](https://github.com/rails/rails/commit/eed9f2539e3ab5a68e798802f464b8e4e95e619e)) - В Rails PATCH заменил PUT. PATCH используется для частичного обновления ресурсов.
### Безопасность
- * **match не соответствует всем методам** ([коммит](https://github.com/rails/rails/commit/90d2802b71a6e89aedfe40564a37bd35f777e541)) - В маршрутном DSL, match требует указания метода или методов HTTP.
- * **Сущности html экранируются по умолчанию** ([коммит](https://github.com/rails/rails/commit/5f189f41258b83d49012ec5a0678d827327e7543)) - Строки, рендерящиеся в erb, экранируются, если не обернуты в `raw`, или вызван `html_safe`.
- * **Новые заголовки безопасности** ([коммит](https://github.com/rails/rails/commit/6794e92b204572d75a07bd6413bdae6ae22d5a82)) - Rails посылает следующие заголовки с каждым запросом HTTP: `X-Frame-Options` (предотвращает кликджекинг, запрещая браузеру встраивать страницу в фрейм), `X-XSS-Protection` (говорит браузеру прерывать инъекцию скрипта) и `X-Content-Type-Options` (предотвращает открытие браузером jpeg как exe).
+* **match не соответствует всем методам** ([коммит](https://github.com/rails/rails/commit/90d2802b71a6e89aedfe40564a37bd35f777e541)) - В маршрутном DSL, match требует указания метода или методов HTTP.
+* **Сущности html экранируются по умолчанию** ([коммит](https://github.com/rails/rails/commit/5f189f41258b83d49012ec5a0678d827327e7543)) - Строки, рендерящиеся в erb, экранируются, если не обернуты в `raw`, или вызван `html_safe`.
+* **Новые заголовки безопасности** ([коммит](https://github.com/rails/rails/commit/6794e92b204572d75a07bd6413bdae6ae22d5a82)) - Rails посылает следующие заголовки с каждым запросом HTTP: `X-Frame-Options` (предотвращает кликджекинг, запрещая браузеру встраивать страницу в фрейм), `X-XSS-Protection` (говорит браузеру прерывать инъекцию скрипта) и `X-Content-Type-Options` (предотвращает открытие браузером jpeg как exe).
Извлечение особенностей в гемы
---------------------------
@@ -99,7 +100,7 @@ $ ruby /path/to/rails/railties/bin/rails new myapp --dev
* Защита от массового назначения в моделях Active Record ([Github](https://github.com/rails/protected_attributes), [Pull Request](https://github.com/rails/rails/pull/7251))
* ActiveRecord::SessionStore ([Github](https://github.com/rails/activerecord-session_store), [Pull Request](https://github.com/rails/rails/pull/7436))
* Обсерверы Active Record ([Github](https://github.com/rails/rails-observers), [Commit](https://github.com/rails/rails/commit/39e85b3b90c58449164673909a6f1893cba290b2))
-* Active Resource ([Github](https://github.com/rails/activeresource), [Pull Request](https://github.com/rails/rails/pull/572), [Blog](http://yetimedia.tumblr.com/post/35233051627/activeresource-is-dead-long-live-activeresource))
+* Active Resource ([Github](https://github.com/rails/activeresource), [Pull Request](https://github.com/rails/rails/pull/572), [Blog](http://yetimedia-blog-blog.tumblr.com/post/35233051627/activeresource-is-dead-long-live-activeresource))
* Кэширование экшна ([Github](https://github.com/rails/actionpack-action_caching), [Pull Request](https://github.com/rails/rails/pull/7833))
* Кэширование страницы ([Github](https://github.com/rails/actionpack-page_caching), [Pull Request](https://github.com/rails/rails/pull/7833))
* Sprockets ([Github](https://github.com/rails/sprockets-rails))
@@ -120,7 +121,7 @@ Railties
### Значимые изменения
-* Новые места для тестов `test/models`, `test/helpers`, `test/controllers` и `test/mailers`. Также добавлены соответствующие рейк-таски. ([Pull Request](https://github.com/rails/rails/pull/7878))
+* Новые места расположения для тестов `test/models`, `test/helpers`, `test/controllers` и `test/mailers`. Также добавлены соответствующие задачи rake. ([Pull Request](https://github.com/rails/rails/pull/7878))
* Исполняемые файлы приложения теперь находятся в директории `bin/`. Запустите `rake rails:update:bin` чтобы получить `bin/bundle`, `bin/rails` и `bin/rake`.
@@ -163,7 +164,7 @@ Active Support
### Значимые изменения
-* Заменен устаревший гем `memcache-client` на `dalli` в `ActiveSupport::Cache::MemCacheStore`.
+* Заменен устаревший гем `memcache-client` на `dalli` в `ActiveSupport::Cache::MemCacheStore`.
* Оптимизирован `ActiveSupport::Cache::Entry` для уменьшения расхода памяти и процессора.
@@ -173,19 +174,19 @@ Active Support
* `String#to_date` теперь вызывает `ArgumentError: invalid date` вместо `NoMethodError: undefined method 'div' for nil:NilClass` при получения неверной даты. Это то же самое, что и `Date.parse`, и он принимает больше неправильных дат, чем 3.x, такие как:
- ```
- # ActiveSupport 3.x
- "asdf".to_date # => NoMethodError: undefined method `div' for nil:NilClass
- "333".to_date # => NoMethodError: undefined method `div' for nil:NilClass
+ ```ruby
+ # ActiveSupport 3.x
+ "asdf".to_date # => NoMethodError: undefined method `div' for nil:NilClass
+ "333".to_date # => NoMethodError: undefined method `div' for nil:NilClass
- # ActiveSupport 4
- "asdf".to_date # => ArgumentError: invalid date
- "333".to_date # => Fri, 29 Nov 2013
- ```
+ # ActiveSupport 4
+ "asdf".to_date # => ArgumentError: invalid date
+ "333".to_date # => Fri, 29 Nov 2013
+ ```
### Устаревания
-* Устарел метод `ActiveSupport::TestCase#pending`, используйте вместо него `skip` из MiniTest.
+* Устарел метод `ActiveSupport::TestCase#pending`, используйте вместо него `skip` из minitest.
* `ActiveSupport::Benchmarkable#silence` устарел из-за недостатков в тредобезопасности. Он будет убран без замен в Rails 4.1.
@@ -193,7 +194,7 @@ Active Support
* Устарел метод совместимости `Module#local_constant_names`, используйте вместо него `Module#local_constants` (который возвращает символы).
-* Устарел `BufferedLogger`. Используйте `ActiveSupport::Logger` или `logger` из стандартной библиотеки Ruby.
+* Устарел `ActiveSupport::BufferedLogger`. Используйте `ActiveSupport::Logger` или `logger` из стандартной библиотеки Ruby.
* Устарели `assert_present` и `assert_blank` в пользу `assert object.blank?` и `assert object.present?`
@@ -221,18 +222,18 @@ Active Record
Метод `remove_column` принимает несколько имен столбцов; вместо использования `remove_columns` (который необратимый).
Метод `change_table` также обратимый, если его блок не вызывает `remove`, `change` или `change_default`
- * Новый метод `reversible` делает возможным определить код для исполнения при выполении или откате миграции.
- Смотрите [Руководство по миграциям](/rails-database-migrations#writing-a-migration)
+ * Новый метод `reversible` делает возможным определить код для исполнения при выполнении или откате миграции.
+ Смотрите руководство [Миграции Active Record](/active-record-migrations#using-reversible)
- * Новый метод `revert` обратит всю миграцию или предоставленный блок.
+ * Новый метод `revert` обратит всю миграцию или предоставленный блок.
Если миграция откатывается, данная миграция / блок выполняется обычно.
- Смотрите [Руководство по миграциям](/rails-database-migrations#writing-a-migration)
+ Смотрите руководство [Миграции Active Record](/active-record-migrations#reverting-previous-migrations)
* Добавлена поддержка массивов PostgreSQL. Для создания столбца array может быть использован любой тип данных, с полной поддержкой миграций и выгрузкой схемы.
* Добавлен `Relation#load` для явной загрузки записи и возврата `self`.
-* `Model.all` теперь возвращает `ActiveRecord::Relation`, а не массив с записями. Используйте `Relation#to_a`, если вы действительно хотите массив. В некоторых особенных случаях это может вызвать повреждения при обновлении.
+* `Model.all` теперь возвращает `ActiveRecord::Relation`, а не массив с записями. Используйте `Relation#to_a`, если вы действительно хотите массив. В некоторых особенных случаях это может вызвать повреждения при апгрейде.
* Добавлен `ActiveRecord::Migration.check_pending!`, вызывающий ошибку, если миграции ожидают выполнения.
@@ -244,7 +245,7 @@ Active Record
* Убрана IdentityMap.
-* Убран автоматический запуск запросов EXPLAIN. Опция `active_record.auto_explain_threshold_in_seconds` больше не используется и должна быть убрана.
+* Убрано автоматическое выполнение запросов EXPLAIN. Опция `active_record.auto_explain_threshold_in_seconds` больше не используется и должна быть убрана.
* Добавлены `ActiveRecord::NullRelation` и `ActiveRecord::Relation#none`, реализующие паттерн нулевого объекта для класса Relation.
@@ -264,3 +265,8 @@ Active Record
* `find_or_initialize_by_...` может быть переписан с использованием `find_or_initialize_by(...)`.
* `find_or_create_by_...` может быть переписан с использованием `find_or_create_by(...)`.
* `find_or_create_by_...!` может быть переписан с использованием `find_or_create_by!(...)`.
+
+Благодарности
+-------------
+
+Взгляните [на полный список контрибьюторов Rails](https://contributors.rubyonrails.org/), на людей, которые потратили много часов, сделав Rails стабильнее и надёжнее. Спасибо им всем.
diff --git a/source/4_1_release_notes.md b/source/4_1_release_notes.md
index 88868601..1b076dc4 100644
--- a/source/4_1_release_notes.md
+++ b/source/4_1_release_notes.md
@@ -8,46 +8,42 @@
* Action Pack Variants (шаблоны, для разных устройств)
* Предпросмотр писем Action Mailer
-Эти заметки о релизе покрывают только основные обновления. Чтобы узнать о различных багфиксах и изменениях, обратитесь к логам изменений или к
-[списку комитов](https://github.com/rails/rails/commits/master) в главном репозитории Rails на GitHub.
-
+Эти заметки о релизе покрывают только основные изменения. Чтобы узнать о различных исправлениях программных ошибок и изменениях, обратитесь к логам изменений или к [списку коммитов](https://github.com/rails/rails/commits/4-1-stable) в главном репозитории Rails на GitHub.
--------------------------------------------------------------------------------
-Обновление до Rails 4.1
------------------------
-
-Если вы обновляете существующее приложение, было бы хорошо иметь перед этим покрытие тестами. Также, до попытки обновиться до Rails 4.1, необходимо сначала обновиться до Rails 4.0 и убедиться, что приложение все еще выполняется так, как нужно.
-Список вещей, которые нужно выполнить для обновления доступен в руководстве
-[Обновление Rails](/upgrading-ruby-on-rails#upgrading-from-rails-4-0-to-rails-4-1).
+Апгрейд до Rails 4.1
+--------------------
+Прежде чем апгрейднуть существующее приложение, было бы хорошо иметь перед этим покрытие тестами. Также, до попытки обновиться до Rails 4.1, необходимо сначала произвести апгрейд до Rails 4.0 и убедиться, что приложение все еще выполняется так, как нужно.
+Список вещей, которые нужно выполнить для апгрейда доступен в руководстве
+[Апгрейд Ruby on Rails](/upgrading-ruby-on-rails#upgrading-from-rails-4-0-to-rails-4-1).
-Основные изменения
-------------------
+Основные особенности
+--------------------
### Spring Application Preloader
-Spring является прелоадером для Rails приложений. Он увеличивает скорость разработки, храня
-ваше приложение запущенным в бэкграунде, поэтому при прогоне тестов, rake тасков или миграций, теперь загружать приложение каждый раз больше нет необходимости.
+Spring является прелоадером для Rails приложений. Он увеличивает скорость разработки, храня приложение запущенным в фоновом режиме, поэтому при запуске тестов, задач rake или миграций, теперь загружать приложение каждый раз больше нет необходимости.
Новое Rails 4.1 приложение будет по умолчанию идти с "springified" бинстабами. Это означает, что
`bin/rails` и `bin/rake`, будут автоматически использовать преимущества предзагруженной среды spring.
**Запуск rake задач:**
-```
-bin/rake test:models
+```bash
+$ bin/rake test:models
```
-**Запуск Rails комманд:**
+**Запуск Rails команд:**
-```
-bin/rails console
+```bash
+$ bin/rails console
```
**Spring интроспекция:**
-```
+```bash
$ bin/spring status
Spring is running:
@@ -59,16 +55,16 @@ Spring is running:
Обратитесь к [Spring README](https://github.com/jonleighton/spring/blob/master/README.md),
чтобы увидеть все возможности.
-Обратитесь к руководству по [Обновлению Rails](/upgrading-ruby-on-rails#spring)
+Обратитесь к руководству [Апгрейд Ruby on Rails](/upgrading-ruby-on-rails#spring)
- как мигрировать существующее приложение, чтобы использовать данную возможность.
### `config/secrets.yml`
Rails 4.1 генерирует новый файл `secrets.yml` в директории `config`. По умолчанию,
этот файл содержит `secret_key_base` приложения, но он так же может использоваться
-для хранения других секретных данных, таких как ключи доступа к внешним API.
+для хранения других секретов, таких как ключи доступа к внешним API.
-Секретные данные, добавляемые в этот файл, будут доступны с помощью `Rails.application.secrets`.
+Секреты, добавляемые в этот файл, будут доступны с помощью `Rails.application.secrets`.
Например, для `config/secrets.yml`:
```yaml
@@ -79,13 +75,13 @@ development:
`Rails.application.secrets.some_api_key` вернёт `SOMEKEY` в development окружении.
-Обратитесь к руководству по [Обновлению Rails](/upgrading-ruby-on-rails#config-secrets-yml)
+Обратитесь к руководству [Апгрейд Ruby on Rails](/upgrading-ruby-on-rails#config-secrets-yml)
- как мигрировать существующее приложение, чтобы использовать данную возможность.
### Action Pack Variants
-Мы часто хотим рендерить разные типы шаблонов HTML/JSON/XML - для телефонов,
-планшетов и десктопных компьютеров. С помощью Variants - это легко.
+Мы часто хотим рендерить разные типы шаблонов HTML/JSON/XML для телефонов,
+планшетов и десктопных браузеров. С помощью Variants - это легко.
Запрос Variants - это специальный формат запроса, например `:tablet`,
`:phone`, или `:desktop`.
@@ -145,14 +141,14 @@ end
так же можно увидеть полный список писем - http://localhost:3000/rails/mailers.
По умолчанию, эти превью-классы располагаются в `test/mailers/previews`.
-Директорию можно легко изменить используя `preview_path` опцию.
+Директорию можно легко изменить используя опцию `preview_path`.
-Обратитесь к [документации](http://api.rubyonrails.org/v4.1.0/classes/ActionMailer/Base.html)
+Обратитесь к [документации](https://api.rubyonrails.org/v4.1.0/classes/ActionMailer/Base.html)
за подробным описанием.
### Enum поля в Active Record
-Объявляйте в базе данных enum поле, в котором числа связываются со значениеми,
+Объявляйте в базе данных enum поле, в котором числа связываются со значениями,
но могут быть запрошены по имени
```ruby
@@ -170,13 +166,12 @@ Conversation.statuses # => { "active" => 0, "archived" => 1 }
```
-Обратитесь к [документации](http://api.rubyonrails.org/v4.1.0/classes/ActiveRecord/Enum.html)
-за подробным описанием.
+Обратитесь к [документации](https://api.rubyonrails.org/v4.1.0/classes/ActiveRecord/Enum.html) за подробным описанием.
### Message Verifiers
Message verifiers могут быть использованы для генерации и верификации подписанных сообщений.
-Это полезно для безопасной передачи деликатных данных, таких как токены remember-me и прочие подобные.
+Это полезно для безопасной передачи чувствительных данных, таких как токены remember-me и прочие подобные.
Метод `Rails.application.message_verifier` возвращает новый Message Verifier, который подписывает сообщения с помощью ключа, созданного из secret_key_base и имени верификационного сообщения:
@@ -200,12 +195,12 @@ class Todo < ActiveRecord::Base
end
def latest_event
- ...
+ # ...
end
private
def some_internal_method
- ...
+ # ...
end
end
end
@@ -215,14 +210,14 @@ end
расширение его `ActiveSupport::Concern`, и дальнейшего смешивания его с классом
`Todo`.
-Обратитесь к [документации](http://api.rubyonrails.org/v4.1.0/classes/Module/Concerning.html)
+Обратитесь к [документации](https://api.rubyonrails.org/v4.1.0/classes/Module/Concerning.html)
за подробным описанием и способами использования.
### CSRF защита от `
+
+javascript_include_tag("common", async: true)
+# =>
+```
+
+Некоторые из наиболее распространенных атрибутов - `async` и `defer`, где `async` - позволит загружать скрипт параллельно, чтобы разобрать и выполнить его как можно скорее, а `defer` - укажет, что скрипт должен быть выполнен после того, как документ был полностью разобран.
+
+INFO: Внутренне, `javascript_include_tag` использует [`javascript_path` из AssetUrlHelpers](https://api.rubyonrails.org/classes/ActionView/Helpers/AssetUrlHelper.html#method-i-javascript_path) для построения пути к скрипту.
+
+Подробности смотрите в [API-документации](https://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-javascript_include_tag).
+
+### picture_tag
+
+Возвращает HTML-тег picture для указанного источника. Она поддерживает передачу String, Array или Block.
+
+```ruby
+picture_tag("icon.webp", "icon.png")
+```
+
+Это сгенерирует следующий HTML:
+
+```html
+
+
+
+
+
+```
+
+Подробности смотрите в [API-документации](https://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-picture_tag).
+
+### preload_link_tag
+
+Возвращает тег ссылки, который браузеры могут использовать для предварительной загрузки источника. Источник может быть путем к ресурсу, управляемому конвейером ресурсов, полным путем или URI.
+
+```ruby
+preload_link_tag("application.css")
+# =>
+```
+
+Подробности смотрите в [API-документации](https://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-preload_link_tag).
+
+### stylesheet_link_tag
+
+Возвращает тег ссылки на таблицу стилей для указанных источников. Если вы не укажете расширение файла, `.css` будет автоматически добавлено.
+
+```ruby
+stylesheet_link_tag("application")
+# =>
+
+stylesheet_link_tag("application", media: "all")
+# =>
+```
+
+`media` используется для определения типа носителя для ссылки. Наиболее распространенные типы носителей: `all`, `screen`, `print` и `speech`.
+
+INFO: Внутренне, `stylesheet_link_tag` использует [`stylesheet_path` из AssetUrlHelpers](https://api.rubyonrails.org/classes/ActionView/Helpers/AssetUrlHelper.html#method-i-stylesheet_path) для построения пути к таблице стилей.
+
+Подробности смотрите в [API-документации](https://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-stylesheet_link_tag).
+
+### video_tag
+
+Генерирует HTML-тег video с источником(ами), или как отдельный тег для строкового источника или вложенные теги источника для массива нескольких источников. Источники могут быть полными путями, файлами из публичной директории videos или вложениями Active Storage.
+
+```ruby
+video_tag("trailer")
+# =>
+
+video_tag(["trailer.ogg", "trailer.flv"])
+# =>
+
+video_tag("trailer", controls: true)
+# =>
+```
+
+INFO: Внутренне, `video_tag` использует [`video_path` из AssetUrlHelpers](https://api.rubyonrails.org/classes/ActionView/Helpers/AssetUrlHelper.html#method-i-video_path) для построения пути к видео.
+
+Подробности смотрите в [API-документации](https://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-video_tag).
+
+JavaScript
+----------
+
+Набор методов для работы с JavaScript в ваших вью.
+
+### escape_javascript
+
+Экранирует символы переноса строки, а также одинарные и двойные кавычки для сегментов JavaScript. Нужно использовать этот метод, чтобы взять строку текста и убедиться, что она не будет содержать неправильных символов, которые могут привести к ошибкам при ее обработке браузером.
+
+Например, предположим, у вас есть партиал с приветствием, которое содержит двойные кавычки. Вы можете экранировать приветствие перед его использованием в JavaScript-окне предупреждения.
+
+```html+erb
+<%# app/views/users/greeting.html.rb %>
+My name is <%= current_user.name %>, and I'm here to say "Welcome to our website!"
+```
+
+```html+erb
+
+```
+
+Этот метод правильно экранирует кавычки, и приветствие отобразится в окне предупреждения.
+
+Подробности смотрите в [API-документации](https://api.rubyonrails.org/classes/ActionView/Helpers/JavaScriptHelper.html#method-i-escape_javascript).
+
+### javascript_tag
+
+Возвращает JavaScript-тег, содержащий предоставленный код. Вы можете передать хэш опций для управления поведением тега `
+```
+
+Вместо передачи содержимого в качестве аргумента, вы также можете использовать блок.
+
+```html+erb
+<%= javascript_tag type: "application/javascript" do %>
+ alert("Welcome to my app!")
+<% end %>
+```
+
+Подробности смотрите в [API-документации](https://api.rubyonrails.org/classes/ActionView/Helpers/JavaScriptHelper.html#method-i-javascript_tag).
+
+Альтернативные теги
+-------------------
+
+Набор методов для программной генерации HTML-тегов.
+
+### tag
+
+Генерирует одиночный HTML-тег с указанным `name` и `options`.
+
+Каждый тег может быть построен с помощью:
+
+```ruby
+tag.some_tag_name(optional content, options)
+```
+
+Где имя тега может быть, например, `br`, `div`, `section`, `article` или вообще любой тег.
+
+Например, вот несколько распространенных вариантов использования:
+
+```ruby
+tag.h1 "All titles fit to print"
+# =>
All titles fit to print
+
+tag.div "Hello, world!"
+# =>
Hello, world!
+```
+
+Кроме того, вы можете передать опции для добавления атрибутов к создаваемому тегу.
+
+```ruby
+tag.section class: %w( kitties puppies )
+# =>
+```
+
+Дополнительно, HTML-атрибуты `data-*` могут быть переданы хелперу `tag` с помощью опции `data`. Эта опция принимает хэш, содержащий пары ключ-значение для дополнительных атрибутов. Эти пары затем преобразуются в атрибуты `data-*` с разделителями-дефисами для обеспечения совместимости с JavaScript.
+
+```ruby
+tag.div data: { user_id: 123 }
+# =>
+```
+
+Подробности смотрите в [API-документации](https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-tag).
+
+### token_list
+
+Возвращает строку токенов, сформированную на основе предоставленных аргументов. Он также имеет псевдоним `class_names`.
+
+```ruby
+token_list("cats", "dogs")
+# => "cats dogs"
+
+token_list(nil, false, 123, "", "foo", { bar: true })
+# => "123 foo bar"
+
+mobile, alignment = true, "center"
+token_list("flex items-#{alignment}", "flex-col": mobile)
+# => "flex items-center flex-col"
+class_names("flex items-#{alignment}", "flex-col": mobile) # using the alias
+# => "flex items-center flex-col"
+```
+
+Блоки захвата
+-------------
+
+Набор методов для извлечения сгенерированной разметки, которую можно использовать в других частях файла шаблона или макета.
+
+Этот набор методов предоставляет метод `capture` для захвата блоков в переменную и способ захвата блок для использования в макете с помощью `content_for`.
+
+### capture
+
+Метод `capture` позволяет извлечь часть шаблона в переменную.
+
+```html+erb
+<% @greeting = capture do %>
+
Welcome! The date and time is <%= Time.current %>
+<% end %>
+```
+
+Затем вы можете использовать эту переменную в любом месте ваших шаблонов, макетов или хелперов.
+
+```html+erb
+
+
+ Welcome!
+
+
+ <%= @greeting %>
+
+
+```
+
+Возвращаемое значение `capture` - это строка, сгенерированная переданным блоком.
+
+``` ruby
+@greeting
+# => "Welcome to my shiny new web page! The date and time is 2018-09-06 11:09:16 -0500"
+```
+
+Подробности смотрите в [API-документации](https://api.rubyonrails.org/classes/ActionView/Helpers/CaptureHelper.html#method-i-capture).
+
+### content_for
+
+Вызов `content_for` сохраняет блок разметки под определенным идентификатором для дальнейшего использования. Вы можете обращаться к этому сохраненному содержимому позже в других шаблонах, вспомогательных модулях или макете, передавая идентификатор в качестве аргумента методу `yield`.
+
+Один из распространенных вариантов использования `content_for` - это установка заголовка страницы.
+
+Вы определяете блок `content_for` с заголовком в специальном шаблоне страницы, и затем используете `yield` в макете. На других страницах, где блок `content_for` не используется, он останется пустым, и `yield` ничего не вставит.
+
+```html+erb
+<%# app/views/users/special_page.html.erb %>
+<% content_for(:html_title) { "Special Page Title" } %>
+```
+
+```html+erb
+<%# app/views/layouts/application.html.erb %>
+
+
+ <%= content_for?(:html_title) ? yield(:html_title) : "Default Title" %>
+
+
+```
+
+Обратите внимание, что в приведенном выше примере мы используем метод-предикат `content_for?` для условного вывода заголовка. Этот метод проверяет, был ли какой-либо контент ранее захвачен с помощью `content_for`, что позволяет вам адаптировать части вашего макета в зависимости от контента в ваших вью.
+
+Дополнительно, вы можете использовать `content_for` внутри вспомогательного модуля.
+
+```ruby
+# app/helpers/title_helper.rb
+module TitleHelper
+ def html_title
+ content_for(:html_title) || "Default Title"
+ end
+end
+```
+
+Теперь вы можете вызвать `html_title` в вашем макете, чтобы получить содержимое, сохраненное в блоке `content_for`. Если на странице, которая отрисовывается (например, на `special_page`), установлен блок `content_for`, он отобразит заголовок. В противном случае будет отображен текст по умолчанию "Default Title".
+
+WARNING: `content_for` игнорируется в кэше. Поэтому не следует использовать его для элементов, которые будут кэшироваться фрагментами.
+
+NOTE: Возможно, вы задумываетесь, в чем разница между `capture` и `content_for`?
+`capture` используется для захвата блока разметки в переменную, а `content_for` используется для хранения блока разметки под идентификатором для дальнейшего использования. Внутренне `content_for` фактически вызывает `capture`. Однако ключевое отличие заключается в их поведении при многократном вызове.
+`content_for` можно вызывать несколько раз, объединяя блоки, которые он получает для определенного идентификатора, в том порядке, в котором они предоставляются. Каждый последующий вызов просто добавляется к тому, что уже сохранено. Напротив, `capture` возвращает только содержимое блока, не отслеживая предыдущих вызовов.
+
+Подробности смотрите в [API-документации](https://api.rubyonrails.org/classes/ActionView/Helpers/CaptureHelper.html#method-i-content_for).
+
+Производительность
+------------------
+
+### benchmark
+
+Оборачивайте дорогостоящие операции или потенциальные узкие места блоком `benchmark`, чтобы получить время выполнения операции.
+
+```html+erb
+<% benchmark "Process data files" do %>
+ <%= expensive_files_operation %>
+<% end %>
+```
+
+Это добавит в лог информацию вроде `Process data files (0.34523)`, которую затем можно использовать для сравнения временных затрат при оптимизации вашего кода.
+
+NOTE: Этот хелпер является частью Active Support и также доступен в контроллерах, хелперах, моделях и т.д.
+
+Подробности смотрите в [API-документации](https://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html#method-i-benchmark).
+
+### cache
+
+Вы можете кэшировать фрагменты вью, а не целые действия или страницы. Эта техника полезна для кэширования таких элементов, как меню, списки новостей, статические фрагменты HTML и т.д. Он позволяет обернуть фрагмент логики вью в блок кэша и извлекать его из хранилища кэша при следующем запросе.
+
+Метод `cache` принимает блок, содержащий контент, который вы хотите кэшировать.
+
+Например, вы можете кэшировать footer вашего макета приложения, обернув его блоком `cache`.
+
+```erb
+<% cache do %>
+ <%= render "application/footer" %>
+<% end %>
+```
+
+Вы также можете кэшировать данные на основе экземпляров модели. Например, можно кэшировать каждую статью на странице, передав объект `article` в метод `cache`. Это позволит кэшировать каждую статью отдельно.
+
+```erb
+<% @articles.each do |article| %>
+ <% cache article do %>
+ <%= render article %>
+ <% end %>
+<% end %>
+```
+
+Когда ваше приложение получает первый запрос к этой странице, Rails запишет новую запись кэша с уникальным ключом. Ключ выглядит примерно так:
+
+```irb
+views/articles/index:bea67108094918eeba32cd4a6f786301/articles/1
+```
+
+Подробности смотрите в [`Кэширование фрагмента`](caching_with_rails.html#fragment-caching) и [API-документации](https://api.rubyonrails.org/classes/ActionView/Helpers/CacheHelper.html#method-i-cache).
+
+Разное
+------
+
+### atom_feed
+
+Каналы Atom - это файловые форматы на основе XML, используемые для рассылки контента. Пользователи могут просматривать контент с помощью программ чтения RSS-каналов, а поисковые системы могут использовать их для обнаружения дополнительной информации о вашем сайте.
+
+Этот хелпер упрощает создание каналов Atom и чаще всего используется в шаблонах Builder для создания XML. Вот полный пример использования:
+
+```ruby
+# config/routes.rb
+resources :articles
+```
+
+```ruby
+# app/controllers/articles_controller.rb
+def index
+ @articles = Article.all
+
+ respond_to do |format|
+ format.html
+ format.atom
+ end
+end
+```
+
+```ruby
+# app/views/articles/index.atom.builder
+atom_feed do |feed|
+ feed.title("Articles Index")
+ feed.updated(@articles.first.created_at)
+
+ @articles.each do |article|
+ feed.entry(article) do |entry|
+ entry.title(article.title)
+ entry.content(article.body, type: "html")
+
+ entry.author do |author|
+ author.name(article.author_name)
+ end
+ end
+ end
+end
+```
+
+Подробности смотрите в [API-документации](https://api.rubyonrails.org/classes/ActionView/Helpers/AtomFeedHelper.html#method-i-atom_feed).
+
+### debug
+
+
+Возвращает представление объекта в формате YAML, обернутое тегом `pre`. Это удобный способ читабельного просмотра объекта.
+
+```ruby
+my_hash = { "first" => 1, "second" => "two", "third" => [1, 2, 3] }
+debug(my_hash)
+```
+
+```html
+
+```
+
+Подробности смотрите в [API-документации](https://api.rubyonrails.org/classes/ActionView/Helpers/DebugHelper.html#method-i-debug).
diff --git a/source/action_view_overview.md b/source/action_view_overview.md
new file mode 100644
index 00000000..ee0c7d25
--- /dev/null
+++ b/source/action_view_overview.md
@@ -0,0 +1,660 @@
+Обзор Action View
+=================
+
+После прочтения этого руководства вы узнаете:
+
+* Что такое Action View, и как его использовать вместе с Rails.
+* Как лучше использовать шаблоны, партиалы и макеты.
+* Как использовать локализованные вью.
+
+--------------------------------------------------------------------------------
+
+Что такое Action View?
+----------------------
+
+Action View - это V в [MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller). [Action Controller](/action-controller-overview) и Action View работают вместе для обработки веб-запросов. Action Controller отвечает за взаимодействие с уровнем модели (в MVC) и получение данных. Затем Action View отвечает за отрисовку тела ответа на веб-запрос, используя эти данные.
+
+По умолчанию шаблоны Action View (также называемые просто "вью") пишутся с использованием Embedded Ruby (ERB), который позволяет использовать код Ruby внутри HTML-документов.
+
+Action View предоставляет множество [вспомогательных методов - хелперов](#helpers) для динамического создания HTML-тегов для форм, дат и строк. Также можно добавлять в ваше приложение собственные хелперы по мере необходимости.
+
+NOTE: Action View может использовать функции Active Model, такие как [`to_param`](https://api.rubyonrails.org/classes/ActiveModel/Conversion.html#method-i-to_param) и [`to_partial_path`](https://api.rubyonrails.org/classes/ActiveModel/Conversion.html#method-i-to_partial_path) для упрощения кода. Это не означает, что Action View зависит от Active Model. Action View является независимым пакетом, который можно использовать с любой библиотекой Ruby.
+
+Использование Action View с Rails
+---------------------------------
+
+Шаблоны Action View (также называемые "вью") хранятся во вложенных папках внутри директории `app/views`. Там есть вложенная папка, соответствующая имени каждого контроллера. Файлы вью внутри этой папки используются для отрисовки конкретных вью в ответ на экшны контроллера.
+
+Например, при использовании генератора скаффолда для создания ресурса `article`, Rails создает следующие файлы в `app/views/articles`:
+
+```bash
+$ bin/rails generate scaffold article
+ [...]
+ invoke scaffold_controller
+ create app/controllers/articles_controller.rb
+ invoke erb
+ create app/views/articles
+ create app/views/articles/index.html.erb
+ create app/views/articles/edit.html.erb
+ create app/views/articles/show.html.erb
+ create app/views/articles/new.html.erb
+ create app/views/articles/_form.html.erb
+ [...]
+```
+
+Именование файлов следует соглашениям Rails. Их названия совпадают с названиями связанных экшнов контроллера. Например, `index.html.erb`, `edit.html.erb` и т.д.
+
+Соблюдая это соглашение, Rails автоматически найдет и отрисует соответствующую вью в конце экшна контроллера, без необходимости его явного указания. Например, экшн `index` в `articles_controller.rb` автоматически отрисует вью `index.html.erb` из директории `app/views/articles/`. Важны как название файла, так и его расположение.
+
+Итоговый HTML, возвращаемый клиенту, формируется из комбинации файла ERB `.html.erb`, обертывающего его шаблона макета и всех партиалов, на которые может ссылаться файл ERB. В оставшейся части этого руководства вы найдете более подробную информацию о каждом из трех компонентов: шаблонов (`Templates`), партиалов (`Partials`) и макетов (`Layouts`).
+
+Шаблоны
+-------
+
+Шаблоны Action View могут быть написаны в разных форматах. Если файл шаблона имеет расширение `.erb`, он использует встроенный Ruby для создания HTML-ответа. Если шаблон имеет расширение `.jbuilder`, он использует гем [Jbuilder](https://github.com/rails/jbuilder) для создания JSON-ответа. А шаблон с расширением `.builder` использует библиотеку [`Builder::XmlMarkup`](https://github.com/jimweirich/builder) для создания XML-ответа.
+
+Rails использует расширение файла для различения различных систем шаблонов. Например, HTML-файл, использующий систему шаблонов ERB, будет иметь расширение `.html.erb`, а JSON-файл, использующий систему шаблонов Jbuilder, будет иметь расширение `.json.jbuilder`. Другие библиотеки также могут добавлять свои типы шаблонов и соответствующие им расширения файлов.
+
+### ERB
+
+ERB шаблон - это способ внедрить код Ruby внутрь статического HTML с помощью специальных тегов ERB, таких как `<% %>` и `<%= %>`.
+
+При обработке Rails вью в формате ERB, заканчивающихся на `.html.erb`, он выполняет встроенный код Ruby и заменяет теги ERB на динамический вывод. Это динамическое содержимое объединяется со статической разметкой HTML для формирования окончательного HTML-ответа.
+
+Внутри ERB-шаблона Ruby-код можно включать с помощью тегов `<% %>` и `<%= %>`. Тег `<% %>` (без `=`) используется, когда вы хотите выполнить код Ruby, но не выводить его результат напрямую, например, для условий или циклов. Тег `<%= %>` используется для кода Ruby, который генерирует вывод, который вы хотите отобразить внутри шаблона. Например, для вывода атрибута модели, как `person.name` в этом примере:
+
+```html+erb
+
Names
+<% @people.each do |person| %>
+ Name: <%= person.name %>
+<% end %>
+```
+
+Цикл настроен с помощью обычных встраиваемых тегов (`<% %>`), а имя вставлено с помощью выводящих встраиваемых тегов (`<%= %>`).
+
+Имейте в виду, что функции вроде `print` и `puts` не будут отображаться во вью при использовании ERB-шаблонов. Таким образом, следующий код не будет работать:
+
+```html+erb
+<%# WRONG %>
+Hi, Mr. <% puts "Frodo" %>
+```
+
+В предыдущем примере показано, что комментарии в ERB можно добавлять с помощью тега `<%# %>`.
+
+Для подавления ведущих и завершающих пробелов вы можете использовать `<%-` `-%>` взаимозаменяемо с `<%` и `%>`
+
+### Jbuilder
+
+`Jbuilder` - это гем, поддерживаемый командой Rails и включенный в стандартный `Gemfile` Rails. Он используется для создания JSON-ответов с помощью шаблонов.
+
+Если у вас его нет, вы можете добавить следующую строку в ваш `Gemfile`:
+
+```ruby
+gem "jbuilder"
+```
+
+Объект `Jbuilder` с именем `json` автоматически становится доступным для шаблонов с расширением `.jbuilder`.
+
+Вот базовый пример:
+
+```ruby
+json.name("Alex")
+json.email("alex@example.com")
+```
+
+что произведет:
+
+```json
+{
+ "name": "Alex",
+ "email": "alex@example.com"
+}
+```
+
+Больше примеров смотрите в [документации Jbuilder](https://github.com/rails/jbuilder#jbuilder).
+
+### Builder
+
+Шаблоны Builder — это более программная альтернатива ERB. Они похожи на JBuilder, но используются для создания XML, а не JSON.
+
+Объект `XmlMarkup` с именем `xml` автоматически становится доступным для шаблонов с расширением `.builder`.
+
+Вот простой пример:
+
+```ruby
+xml.em("emphasized")
+xml.em { xml.b("emph & bold") }
+xml.a("A Link", "href" => "https://rubyonrails.org/")
+xml.target("name" => "compile", "option" => "fast")
+```
+
+которые создадут:
+
+```html
+emphasized
+emph & bold
+A link
+
+```
+
+Любой метод с блоком будет трактован как разметка тега XML с вложенной разметкой в блоке. Например, следующее:
+
+```ruby
+xml.div {
+ xml.h1(@person.name)
+ xml.p(@person.bio)
+}
+```
+
+создаст что-то вроде:
+
+```html
+
+
David Heinemeier Hansson
+
A product of Danish Design during the Winter of '79...
+
+```
+
+Больше примеров смотрите в [документации Builder](https://github.com/jimweirich/builder).
+
+### Компиляция шаблонов
+
+По умолчанию Rails компилирует каждый шаблон в метод для его отрисовки. В среде development при изменении шаблона Rails проверяет время модификации файла и перекомпилирует его.
+
+Также существует фрагментное кеширование, когда разные части страницы нужно кэшировать и обновлять по отдельности. Подробнее об этом читайте в [руководстве по кешированию](/caching-with-rails#fragment-caching).
+
+Партиалы
+--------
+
+Частичные шаблоны, обычно просто называемые "партиалами", - это способ разбить шаблоны вью на более мелкие фрагменты, пригодные для повторного использования. С помощью партиалов вы можете извлечь часть кода из вашего основного шаблона в отдельный меньший файл и отрисовать этот файл в основном шаблоне. Вы также можете передавать данные в файлы партиалов из основного шаблона.
+
+Давайте разберемся на практике с помощью примеров:
+
+### Рендеринг партиалов
+
+Для того, чтобы отрисовать партиал внутри вью, используйте метод [`render`](https://api.rubyonrails.org/classes/ActionView/Helpers/RenderingHelper.html#method-i-render) внутри этого вью:
+
+```erb
+<%= render "product" %>
+```
+
+Этот код будет искать файл с названием `_product.html.erb` в той же папке, чтобы отрисовать его внутри этой вью. По соглашению, имена файлов партиалов начинаются с подчеркивания. Это помогает отличать их от обычных файлов вью. Однако, при ссылке на партиал внутри вью, само подчеркивание не используется. Это верно даже при ссылке на партиал из другой директории:
+
+```erb
+<%= render "application/product" %>
+```
+
+Этот код найдет и отрисует файл партиала `_product.html.erb` в `app/views/application/`.
+
+### Использование партиалов для упрощения вью
+
+Еще один способ использования партиалов - рассматривать их как аналоги методов. Это позволяет вынести детали из вью, чтобы легче было понять, что происходит. Например, у вас может быть вью, которая выглядит следующим образом:
+
+```html+erb
+<%= render "application/ad_banner" %>
+
+
Products
+
+
Here are a few of our fine products:
+<% @products.each do |product| %>
+ <%= render partial: "product", locals: { product: product } %>
+<% end %>
+
+<%= render "application/footer" %>
+```
+
+Здесь партиалы `_ad_banner.html.erb` и `_footer.html.erb` могут содержать контент, который используется на многих страницах вашего приложения. Вам не нужно видеть детали этих разделов, когда вы фокусируетесь на странице продуктов.
+
+В приведенном выше примере также используется партиал `_product.html.erb`. Этот партиал содержит детали для отрисовки отдельного продукта и используется для отрисовки каждого продукта из коллекции `@products`.
+
+### Передача данных в партиалы с помощью опции `locals`
+
+При отрисовке партиала вы можете передавать данные из основной вью в партиал. Для этого используется хэш опций `locals:`. Каждый ключ в опции `locals:` доступен как локальная переменная партиала:
+
+```html+erb
+<%# app/views/products/show.html.erb %>
+
+<%= render partial: "product", locals: { my_product: @product } %>
+
+<%# app/views/products/_product.html.erb %>
+
+<%= tag.div id: dom_id(my_product) do %>
+
<%= my_product.name %>
+<% end %>
+```
+
+"Локальная переменная партиала" - это переменная, которая существует только внутри данного партиала и доступна только из него. В приведенном выше примере `my_product` является локальной переменной партиала. Ей было присвоено значение `@product` при передаче в партиал из исходной вью.
+
+Имейте в виду, что обычно эту локальную переменную мы просто назвали бы `product`. В данном примере мы используем `my_product`, чтобы отличить ее от названия переменной экземпляра и названия шаблона.
+
+Поскольку `locals` - это хэш, вы можете передавать несколько переменных по мере необходимости, например `locals: { my_product: @product, my_reviews: @reviews }`.
+
+Однако, если шаблон ссылается на переменную, которая *не передана* в представление как часть опции `locals:`, шаблон выдаст ошибку `ActionView::Template::Error`:
+
+```html+erb
+<%# app/views/products/_product.html.erb %>
+
+<%= tag.div id: dom_id(my_product) do %>
+
<%= my_product.name %>
+
+ <%# => raises ActionView::Template::Error for `product_reviews` %>
+ <% product_reviews.each do |review| %>
+ <%# ... %>
+ <% end %>
+<% end %>
+```
+
+### Использование `local_assigns`
+
+Каждый партиал имеет метод под названием [local_assigns][]. Вы можете использовать этот метод для доступа к ключам, переданным через опцию `locals:`. Если партиал был отрисован без установленного `:some_key`, значение `local_assigns[:some_key]` внутри партиала будет равно `nil`.
+
+Например, `product_reviews` будет иметь значение `nil` в приведенном ниже примере, поскольку в `locals:` установлено только значение `product`:
+
+```html+erb
+<%# app/views/products/show.html.erb %>
+
+<%= render partial: "product", locals: { product: @product } %>
+
+<%# app/views/products/_product.html.erb %>
+
+<% local_assigns[:product] # => "#" %>
+<% local_assigns[:product_reviews] # => nil %>
+```
+
+Одним из вариантов использования `local_assigns` является необязательная передача локальной переменной, а затем условное выполнение действия в партиале в зависимости от того, установлена ли локальная переменная. Например:
+
+```html+erb
+<% if local_assigns[:redirect] %>
+ <%= form.hidden_field :redirect, value: true %>
+<% end %>
+```
+
+Еще один пример из `_blob.html.erb` Active Storage. В данном случае размер устанавливается в зависимости от того, установлена ли локальная переменная `in_gallery` при отрисовке партиала, который содержит эту строку:
+
+```html+erb
+<%= image_tag blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ]) %>
+```
+
+### `render` без опций `partial` и `locals`
+
+В предыдущих примерах `render` принимает 2 опции: `partial` и `locals`. Однако, если вам нужны только эти опции, вы можете пропустить ключи `partial` и `locals` и указать только значения.
+
+Например, вместо:
+
+```erb
+<%= render partial: "product", locals: { product: @product } %>
+```
+
+Можно написать:
+
+```erb
+<%= render "product", product: @product %>
+```
+
+Вы также можете использовать эту краткую запись, основанную на соглашениях:
+
+```erb
+<%= render @product %>
+```
+
+Этот код будет искать партиал с названием `_product.html.erb` в `app/views/products/`. Дополнительно, он передаст локальную переменную `product` со значением `@product`.
+
+### Опции `as` и `object`
+
+По умолчанию, объекты, передаваемые в шаблон, находятся в локальной переменной с тем же именем, что и шаблон. Таким образом, при условии, что:
+
+```erb
+<%= render @product %>
+```
+
+внутри партиала `_product.html.erb` вы получите переменную экземпляра `@product` в локальной переменной `product`, как если бы вы написали:
+
+```erb
+<%= render partial: "product", locals: { product: @product } %>
+```
+
+Опция `object` позволяет указать другое имя. Это полезно, когда объект шаблона находится в другом месте (например, в другой переменной экземпляра или в локальной переменной).
+
+Например, вместо:
+
+```erb
+<%= render partial: "product", locals: { product: @item } %>
+```
+
+можно написать:
+
+```erb
+<%= render partial: "product", object: @item %>
+```
+
+Эта строка присваивает переменную экземпляра `@item` локальной переменной партиала с именем `product`. А что, если вы хотите изменить имя локальной переменной с `product` по умолчанию на что-то другое? Для этого можно использовать опцию `:as`.
+
+С помощью опции `:as` вы можете указать другое имя для локальной переменной, например:
+
+```erb
+<%= render partial: "product", object: @item, as: "item" %>
+```
+
+Это эквивалентно:
+
+```erb
+<%= render partial: "product", locals: { item: @item } %>
+```
+
+### Рендеринг коллекций
+
+Во вью часто приходится перебирать коллекцию, например `@products`, и отрисовывать шаблон партиала для каждого элемента коллекции. Этот шаблон реализован как единый метод, который принимает массив и отрисовывает партиал для каждого элемента массива.
+
+Поэтому такой пример для рендеринга всех продуктов:
+
+```erb
+<% @products.each do |product| %>
+ <%= render partial: "product", locals: { product: product } %>
+<% end %>
+```
+
+может быть переписан с помощью одной строчки:
+
+```erb
+<%= render partial: "product", collection: @products %>
+```
+
+Когда партиал вызывается с коллекцией, у отдельных экземпляров партиала есть доступ к рендерящемуся члену коллекции через переменную с именем партиала. В этом случае, поскольку партиал называется `_product.html.erb`, вы можете использовать `product` для ссылки на элемент коллекции, который отрисовывается.
+
+Вы также можете использовать следующую краткую запись для отрисовки коллекций, основанную на соглашениях.
+
+```erb
+<%= render @products %>
+```
+
+Выше предполагается, что `@products` - это коллекция экземпляров `Product`. Rails использует соглашения об именах, чтобы определить название используемого партиала, анализируя при этом имя модели в коллекции, в данном случае `Product`. Фактически, вы даже можете отрисовать коллекцию, состоящую из экземпляров разных моделей, используя этот сокращенный синтаксис, и Rails выберет подходящий партиал для каждого элемента коллекции.
+
+### Разделяющие шаблоны
+
+Также можете определить второй партиал, который будет отрендерен между экземплярами главного партиала, используя опцию `:spacer_template`:
+
+```erb
+<%= render partial: @products, spacer_template: "product_ruler" %>
+```
+
+Rails отрендерит партиал `_product_ruler.html.erb` (без переданных в него данных) между каждой парой партиалов `_product.html.erb`.
+
+### Переменные счетчика
+
+Rails также предоставляет внутри партиала, вызываемого из коллекции, счетчик. Эта переменная названа по имени партиала с добавлением суффикса `_counter`. Например, при отрисовке коллекции `@products` партиал `_product.html.erb` может получить доступ к переменной `product_counter`. Эта переменная указывает на количество раз, которое партиал был отрисован внутри ограничивающей его вью, начиная с значения `0` при первой отрисовке.
+
+```erb
+<%# index.html.erb %>
+<%= render partial: "product", collection: @products %>
+```
+
+```erb
+<%# _product.html.erb %>
+<%= product_counter %> # 0 для первого продукта, 1 для второго продукта...
+```
+
+То же самое работает, когда вы изменяете имя локальной переменной с помощью опции `as:`. Например, если бы вы использовали `as: :item` в своем коде, тогда счетчик назывался бы `item_counter`.
+
+Примечание: Следующие два раздела, [Строгие локальные переменные](#strict-locals) и [`local_assigns` с соответствием образцу](#local-assigns-with-pattern-matching), посвящены более продвинутым функциям использования партиалов и включены сюда для полноты картины.
+
+### (local-assigns-with-pattern-matching) `local_assigns` с соответствием образцу
+
+Поскольку `local_assigns` является `Hash`, он совместим с [оператором присваивания с помощью соответствия образцу в Ruby 3.1](https://docs.ruby-lang.org/en/master/syntax/pattern_matching_rdoc.html):
+
+```ruby
+local_assigns => { product:, **options }
+product # => "#"
+options # => {}
+```
+
+Когда ключи, кроме `:product`, присваиваются локальной хэш-переменной для партиала, их можно включить в вызов вспомогательных методов:
+
+```html+erb
+<%# app/views/products/_product.html.erb %>
+
+<% local_assigns => { product:, **options } %>
+
+<%= tag.div id: dom_id(product), **options do %>
+
+%>
+```
+
+Присваивание с помощью соответствия образцу также поддерживает переименование переменных:
+
+```ruby
+local_assigns => { product: record }
+product # => "#"
+record # => "#"
+product == record # => true
+```
+
+Вы также можете условно читать переменную, а затем переходить к значению по умолчанию, если ключ не входит в опцию `locals:`, используя метод `fetch`:
+
+```html+erb
+<%# app/views/products/_product.html.erb %>
+
+<% local_assigns.fetch(:related_products, []).each do |related_product| %>
+ <%# ... %>
+<% end %>
+```
+
+Совмещение оператора присваивания с помощью соответствия образцу в Ruby 3.1 с вызовами [Hash#with_defaults](https://api.rubyonrails.org/classes/Hash.html#method-i-with_defaults) позволяет компактно назначать значения по умолчанию локальным переменным в партиале.
+
+```html+erb
+<%# app/views/products/_product.html.erb %>
+
+<% local_assigns.with_defaults(related_products: []) => { product:, related_products: } %>
+
+<%= tag.div id: dom_id(product) do %>
+
<%= product.name %>
+
+ <% related_products.each do |related_product| %>
+ <%# ... %>
+ <% end %>
+<% end %>
+```
+
+INFO: По умолчанию партиалы принимают любые `locals` в качестве именованных аргументов. Чтобы определить, какие `locals` принимает партиал, используйте специальный комментарий `locals:. Подробнее об этом можно узнать в разделе [Строгие локальные переменные](#strict-locals).
+
+[local_assigns]:
+ https://api.rubyonrails.org/classes/ActionView/Template.html#method-i-local_assigns
+
+### (strict-locals) Строгие локальные переменные
+
+Партиалы Action View принимают любое количество `locals` в качестве именованных аргументов. С помощью специального комментария `locals:` вы можете контролировать, сколько и какие `locals` принимает шаблон, устанавливать значения по умолчанию и многое другое.
+
+Ниже приведены примеры использования специального комментария `locals:`.
+
+```erb
+<%# app/views/messages/_message.html.erb %>
+
+<%# locals: (message:) -%>
+<%= message %>
+```
+
+Вышеуказанный код делает `message` обязательной локальной переменной. Рендеринг партиала без аргумента локальной переменной `:message` приведет к ошибке:
+
+```ruby
+render "messages/message"
+# => ActionView::Template::Error: missing local: :message for app/views/messages/_message.html.erb
+```
+
+Если установлено значение по умолчанию, оно может быть использовано, если `message` не передается в `locals:`.
+
+```erb
+<%# app/views/messages/_message.html.erb %>
+
+<%# locals: (message: "Hello, world!") -%>
+<%= message %>
+```
+
+Рендеринг партиала без локальной переменной `:message` приведет к использованию значения по умолчанию, установленного в специальном комментарии `locals:`.
+
+```ruby
+render "messages/message"
+# => "Hello, world!"
+```
+
+Рендеринг партиала с локальными переменными, не указанными в специальном комментарии `local:`, также приведет к ошибке:
+
+```ruby
+render "messages/message", unknown_local: "will raise"
+# => ActionView::Template::Error: unknown local: :unknown_local for app/views/messages/_message.html.erb
+```
+
+Вы можете разрешить необязательные аргументы локальных переменных с помощью оператора двойного разбиения `**`:
+
+```erb
+<%# app/views/messages/_message.html.erb %>
+
+<%# locals: (message: "Hello, world!", **attributes) -%>
+<%= tag.p(message, **attributes) %>
+```
+
+Либо вы можете полностью отключить `locals`, установив `locals:` в пустые скобки `()`.
+
+```erb
+<%# app/views/messages/_message.html.erb %>
+
+<%# locals: () %>
+```
+
+Рендеринг партиала с *любыми* аргументами локальных переменных приведет к ошибке:
+
+```ruby
+render "messages/message", unknown_local: "will raise"
+# => ActionView::Template::Error: no locals accepted for app/views/messages/_message.html.erb
+```
+
+Action View обработает специальный комментарий `locals:` во всех шаблонизаторах, которые поддерживают комментарии, начинающиеся с символа `#`, и прочитает его на любой строке внутри партиала.
+
+CAUTION: Поддерживаются только именованные аргументы. Определение позиционных или блочных аргументов вызовет ошибку Action View во время отрисовки.
+
+Макеты
+------
+
+Макеты используются для рендеринга общего шаблона вью поверх результатов экшнов контроллеров Rails. В Rails-приложении может быть несколько макетов, в которых могут быть отрисованы страницы.
+
+Например, в приложении может быть один макет для зарегистрированного пользователя и другой для маркетинговой части сайта. Макет для зарегистрированного пользователя может включать верхнюю панель навигации, которая должна присутствовать во многих экшнах контроллера. Макет продаж для SaaS-приложения может включать верхнюю панель навигации для таких страниц, как "Цены" и "Контакты". Различные макеты могут иметь разное содержимое шапки и колонтитула.
+
+Чтобы найти макет для текущего экшна контроллера, Rails сначала ищет файл в `app/views/layouts` с тем же базовым именем, что и у контроллера. Например, для рендеринга экшнов из класса `ProductsController` будет использоваться файл `app/views/layouts/products.html.erb`.
+
+Если макет, специфичный для контроллера, не существует, Rails использует `app/views/layouts/application.html.erb`.
+
+Вот пример простого макета в файле `application.html.erb`:
+
+```html+erb
+
+
+
+ <%= "Your Rails App" %>
+ <%= csrf_meta_tags %>
+ <%= csp_meta_tag %>
+ <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
+ <%= javascript_importmap_tags %>
+
+
+
+
+
+<%= yield %>
+
+
+```
+
+В примере макета выше, содержимое вью будет отрисовано на месте `<%= yield %>` и окружено тем же содержимым ``, `