summaryrefslogtreecommitdiff
path: root/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll
diff options
context:
space:
mode:
authorBenjamin Sanders <ben@Benjamins-MacBook-Pro.local>2025-10-11 10:34:24 -0400
committerBenjamin Sanders <ben@Benjamins-MacBook-Pro.local>2025-10-11 10:34:24 -0400
commit5571dc766e2143e39762ff0b47c41d1c2e154f4c (patch)
treef4f124d314a7e76c04484515aa0fd1f2e271a601 /vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll
parent359f3309c97fc894b63e0a295c76ab298504d635 (diff)
Vendor bundled gems for deployment
Diffstat (limited to 'vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll')
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/cache.rb186
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/cleaner.rb111
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/collection.rb310
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/command.rb105
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/build.rb82
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/clean.rb44
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/doctor.rb177
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/help.rb34
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/new.rb168
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/new_theme.rb39
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve.rb372
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/live_reload_reactor.rb119
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/livereload_assets/livereload.js1183
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/mime_types_charset.json71
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/servlet.rb206
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/websockets.rb81
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/configuration.rb313
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converter.rb54
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/identity.rb41
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/markdown.rb113
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/markdown/kramdown_parser.rb197
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/smartypants.rb70
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/convertible.rb257
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/deprecator.rb50
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/document.rb543
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/collection_drop.rb20
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/document_drop.rb74
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/drop.rb294
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/excerpt_drop.rb23
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/jekyll_drop.rb32
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/site_drop.rb66
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/static_file_drop.rb14
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/theme_drop.rb39
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/unified_payload_drop.rb30
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/url_drop.rb140
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/entry_filter.rb117
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/errors.rb20
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/excerpt.rb200
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/external.rb75
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters.rb540
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters/date_filters.rb110
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters/grouping_filters.rb64
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters/url_filters.rb98
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/frontmatter_defaults.rb238
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/generator.rb5
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/hooks.rb107
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/inclusion.rb32
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/layout.rb55
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_extensions.rb22
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_renderer.rb80
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_renderer/file.rb77
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_renderer/table.rb45
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/log_adapter.rb151
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/mime.types940
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/page.rb215
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/page_excerpt.rb25
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/page_without_a_file.rb14
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/path_manager.rb74
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/plugin.rb92
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/plugin_manager.rb123
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/profiler.rb51
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/publisher.rb23
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/reader.rb209
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/collection_reader.rb23
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/data_reader.rb113
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/layout_reader.rb62
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/page_reader.rb25
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/post_reader.rb85
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/static_file_reader.rb25
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/theme_assets_reader.rb52
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/regenerator.rb195
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/related_posts.rb52
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/renderer.rb263
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/site.rb576
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/static_file.rb203
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/stevenson.rb57
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/highlight.rb129
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/include.rb275
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/link.rb42
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/post_url.rb106
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/theme.rb90
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/theme_builder.rb121
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/url.rb167
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils.rb371
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/ansi.rb57
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/exec.rb26
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/internet.rb37
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/platforms.rb67
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/thread_event.rb31
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/win_tz.rb46
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/version.rb5
91 files changed, 12761 insertions, 0 deletions
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/cache.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/cache.rb
new file mode 100644
index 0000000..8bffd0d
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/cache.rb
@@ -0,0 +1,186 @@
+# frozen_string_literal: true
+
+require "digest"
+
+module Jekyll
+ class Cache
+ # class-wide base cache
+ @base_cache = {}
+
+ # class-wide directive to write cache to disk is enabled by default
+ @disk_cache_enabled = true
+
+ class << self
+ attr_accessor :cache_dir # class-wide cache location
+
+ attr_reader :base_cache, # class-wide base cache reader
+ :disk_cache_enabled # class-wide directive to write cache to disk
+
+ # Disable Marshaling cached items to disk
+ def disable_disk_cache!
+ @disk_cache_enabled = false
+ end
+
+ # Clear all caches
+ def clear
+ delete_cache_files
+ base_cache.each_value(&:clear)
+ end
+
+ # Compare the current config to the cached config
+ # If they are different, clear all caches
+ #
+ # Returns nothing.
+ def clear_if_config_changed(config)
+ config = config.inspect
+ cache = Jekyll::Cache.new "Jekyll::Cache"
+ return if cache.key?("config") && cache["config"] == config
+
+ clear
+ cache = Jekyll::Cache.new "Jekyll::Cache"
+ cache["config"] = config
+ nil
+ end
+
+ private
+
+ # Delete all cached items from all caches
+ #
+ # Returns nothing.
+ def delete_cache_files
+ FileUtils.rm_rf(@cache_dir) if disk_cache_enabled
+ end
+ end
+
+ #
+
+ # Get an existing named cache, or create a new one if none exists
+ #
+ # name - name of the cache
+ #
+ # Returns nothing.
+ def initialize(name)
+ @cache = Jekyll::Cache.base_cache[name] ||= {}
+ @name = name.gsub(%r![^\w\s-]!, "-")
+ end
+
+ # Clear this particular cache
+ def clear
+ delete_cache_files
+ @cache.clear
+ end
+
+ # Retrieve a cached item
+ # Raises if key does not exist in cache
+ #
+ # Returns cached value
+ def [](key)
+ return @cache[key] if @cache.key?(key)
+
+ path = path_to(hash(key))
+ if disk_cache_enabled? && File.file?(path) && File.readable?(path)
+ @cache[key] = load(path)
+ else
+ raise
+ end
+ end
+
+ # Add an item to cache
+ #
+ # Returns nothing.
+ def []=(key, value)
+ @cache[key] = value
+ return unless disk_cache_enabled?
+
+ path = path_to(hash(key))
+ value = new Hash(value) if value.is_a?(Hash) && !value.default.nil?
+ dump(path, value)
+ rescue TypeError
+ Jekyll.logger.debug "Cache:", "Cannot dump object #{key}"
+ end
+
+ # If an item already exists in the cache, retrieve it.
+ # Else execute code block, and add the result to the cache, and return that result.
+ def getset(key)
+ self[key]
+ rescue StandardError
+ value = yield
+ self[key] = value
+ value
+ end
+
+ # Remove one particular item from the cache
+ #
+ # Returns nothing.
+ def delete(key)
+ @cache.delete(key)
+ File.delete(path_to(hash(key))) if disk_cache_enabled?
+ end
+
+ # Check if `key` already exists in this cache
+ #
+ # Returns true if key exists in the cache, false otherwise
+ def key?(key)
+ # First, check if item is already cached in memory
+ return true if @cache.key?(key)
+ # Otherwise, it might be cached on disk
+ # but we should not consider the disk cache if it is disabled
+ return false unless disk_cache_enabled?
+
+ path = path_to(hash(key))
+ File.file?(path) && File.readable?(path)
+ end
+
+ def disk_cache_enabled?
+ !!Jekyll::Cache.disk_cache_enabled
+ end
+
+ private
+
+ # Given a hashed key, return the path to where this item would be saved on disk.
+ def path_to(hash = nil)
+ @base_dir ||= File.join(Jekyll::Cache.cache_dir, @name)
+ return @base_dir if hash.nil?
+
+ File.join(@base_dir, hash[0..1], hash[2..-1]).freeze
+ end
+
+ # Given a key, return a SHA2 hash that can be used for caching this item to disk.
+ def hash(key)
+ Digest::SHA2.hexdigest(key).freeze
+ end
+
+ # Remove all this caches items from disk
+ #
+ # Returns nothing.
+ def delete_cache_files
+ FileUtils.rm_rf(path_to) if disk_cache_enabled?
+ end
+
+ # Load `path` from disk and return the result.
+ # This MUST NEVER be called in Safe Mode
+ # rubocop:disable Security/MarshalLoad
+ def load(path)
+ raise unless disk_cache_enabled?
+
+ cached_file = File.open(path, "rb")
+ value = Marshal.load(cached_file)
+ cached_file.close
+ value
+ end
+ # rubocop:enable Security/MarshalLoad
+
+ # Given a path and a value, save value to disk at path.
+ # This should NEVER be called in Safe Mode
+ #
+ # Returns nothing.
+ def dump(path, value)
+ return unless disk_cache_enabled?
+
+ FileUtils.mkdir_p(File.dirname(path))
+ File.open(path, "wb") do |cached_file|
+ Marshal.dump(value, cached_file)
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/cleaner.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/cleaner.rb
new file mode 100644
index 0000000..59e7c22
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/cleaner.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+module Jekyll
+ # Handles the cleanup of a site's destination before it is built.
+ class Cleaner
+ HIDDEN_FILE_REGEX = %r!/\.{1,2}$!.freeze
+ attr_reader :site
+
+ def initialize(site)
+ @site = site
+ end
+
+ # Cleans up the site's destination directory
+ def cleanup!
+ FileUtils.rm_rf(obsolete_files)
+ FileUtils.rm_rf(metadata_file) unless @site.incremental?
+ end
+
+ private
+
+ # Private: The list of files and directories to be deleted during cleanup process
+ #
+ # Returns an Array of the file and directory paths
+ def obsolete_files
+ out = (existing_files - new_files - new_dirs + replaced_files).to_a
+ Jekyll::Hooks.trigger :clean, :on_obsolete, out
+ out
+ end
+
+ # Private: The metadata file storing dependency tree and build history
+ #
+ # Returns an Array with the metadata file as the only item
+ def metadata_file
+ [site.regenerator.metadata_file]
+ end
+
+ # Private: The list of existing files, apart from those included in
+ # keep_files and hidden files.
+ #
+ # Returns a Set with the file paths
+ def existing_files
+ files = Set.new
+ regex = keep_file_regex
+ dirs = keep_dirs
+
+ Utils.safe_glob(site.in_dest_dir, ["**", "*"], File::FNM_DOTMATCH).each do |file|
+ next if HIDDEN_FILE_REGEX.match?(file) || regex.match?(file) || dirs.include?(file)
+
+ files << file
+ end
+
+ files
+ end
+
+ # Private: The list of files to be created when site is built.
+ #
+ # Returns a Set with the file paths
+ def new_files
+ @new_files ||= Set.new.tap do |files|
+ site.each_site_file { |item| files << item.destination(site.dest) }
+ end
+ end
+
+ # Private: The list of directories to be created when site is built.
+ # These are the parent directories of the files in #new_files.
+ #
+ # Returns a Set with the directory paths
+ def new_dirs
+ @new_dirs ||= new_files.flat_map { |file| parent_dirs(file) }.to_set
+ end
+
+ # Private: The list of parent directories of a given file
+ #
+ # Returns an Array with the directory paths
+ def parent_dirs(file)
+ parent_dir = File.dirname(file)
+ if parent_dir == site.dest
+ []
+ else
+ parent_dirs(parent_dir).unshift(parent_dir)
+ end
+ end
+
+ # Private: The list of existing files that will be replaced by a directory
+ # during build
+ #
+ # Returns a Set with the file paths
+ def replaced_files
+ new_dirs.select { |dir| File.file?(dir) }.to_set
+ end
+
+ # Private: The list of directories that need to be kept because they are
+ # parent directories of files specified in keep_files
+ #
+ # Returns a Set with the directory paths
+ def keep_dirs
+ site.keep_files.flat_map { |file| parent_dirs(site.in_dest_dir(file)) }.to_set
+ end
+
+ # Private: Creates a regular expression from the config's keep_files array
+ #
+ # Examples
+ # ['.git','.svn'] with site.dest "/myblog/_site" creates
+ # the following regex: /\A\/myblog\/_site\/(\.git|\/.svn)/
+ #
+ # Returns the regular expression
+ def keep_file_regex
+ %r!\A#{Regexp.quote(site.dest)}/(#{Regexp.union(site.keep_files).source})!
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/collection.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/collection.rb
new file mode 100644
index 0000000..1ce33bf
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/collection.rb
@@ -0,0 +1,310 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Collection
+ attr_reader :site, :label, :metadata
+ attr_writer :docs
+
+ # Create a new Collection.
+ #
+ # site - the site to which this collection belongs.
+ # label - the name of the collection
+ #
+ # Returns nothing.
+ def initialize(site, label)
+ @site = site
+ @label = sanitize_label(label)
+ @metadata = extract_metadata
+ end
+
+ # Fetch the Documents in this collection.
+ # Defaults to an empty array if no documents have been read in.
+ #
+ # Returns an array of Jekyll::Document objects.
+ def docs
+ @docs ||= []
+ end
+
+ # Override of normal respond_to? to match method_missing's logic for
+ # looking in @data.
+ def respond_to_missing?(method, include_private = false)
+ docs.respond_to?(method.to_sym, include_private) || super
+ end
+
+ # Override of method_missing to check in @data for the key.
+ def method_missing(method, *args, &blck)
+ if docs.respond_to?(method.to_sym)
+ Jekyll.logger.warn "Deprecation:",
+ "#{label}.#{method} should be changed to #{label}.docs.#{method}."
+ Jekyll.logger.warn "", "Called by #{caller(0..0)}."
+ docs.public_send(method.to_sym, *args, &blck)
+ else
+ super
+ end
+ end
+
+ # Fetch the static files in this collection.
+ # Defaults to an empty array if no static files have been read in.
+ #
+ # Returns an array of Jekyll::StaticFile objects.
+ def files
+ @files ||= []
+ end
+
+ # Read the allowed documents into the collection's array of docs.
+ #
+ # Returns the sorted array of docs.
+ def read
+ filtered_entries.each do |file_path|
+ full_path = collection_dir(file_path)
+ next if File.directory?(full_path)
+
+ if Utils.has_yaml_header? full_path
+ read_document(full_path)
+ else
+ read_static_file(file_path, full_path)
+ end
+ end
+ site.static_files.concat(files) unless files.empty?
+ sort_docs!
+ end
+
+ # All the entries in this collection.
+ #
+ # Returns an Array of file paths to the documents in this collection
+ # relative to the collection's directory
+ def entries
+ return [] unless exists?
+
+ @entries ||= begin
+ collection_dir_slash = "#{collection_dir}/"
+ Utils.safe_glob(collection_dir, ["**", "*"], File::FNM_DOTMATCH).map do |entry|
+ entry[collection_dir_slash] = ""
+ entry
+ end
+ end
+ end
+
+ # Filtered version of the entries in this collection.
+ # See `Jekyll::EntryFilter#filter` for more information.
+ #
+ # Returns a list of filtered entry paths.
+ def filtered_entries
+ return [] unless exists?
+
+ @filtered_entries ||=
+ Dir.chdir(directory) do
+ entry_filter.filter(entries).reject do |f|
+ path = collection_dir(f)
+ File.directory?(path) || entry_filter.symlink?(f)
+ end
+ end
+ end
+
+ # The directory for this Collection, relative to the site source or the directory
+ # containing the collection.
+ #
+ # Returns a String containing the directory name where the collection
+ # is stored on the filesystem.
+ def relative_directory
+ @relative_directory ||= "_#{label}"
+ end
+
+ # The full path to the directory containing the collection.
+ #
+ # Returns a String containing th directory name where the collection
+ # is stored on the filesystem.
+ def directory
+ @directory ||= site.in_source_dir(
+ File.join(container, relative_directory)
+ )
+ end
+
+ # The full path to the directory containing the collection, with
+ # optional subpaths.
+ #
+ # *files - (optional) any other path pieces relative to the
+ # directory to append to the path
+ #
+ # Returns a String containing th directory name where the collection
+ # is stored on the filesystem.
+ def collection_dir(*files)
+ return directory if files.empty?
+
+ site.in_source_dir(container, relative_directory, *files)
+ end
+
+ # Checks whether the directory "exists" for this collection.
+ # The directory must exist on the filesystem and must not be a symlink
+ # if in safe mode.
+ #
+ # Returns false if the directory doesn't exist or if it's a symlink
+ # and we're in safe mode.
+ def exists?
+ File.directory?(directory) && !entry_filter.symlink?(directory)
+ end
+
+ # The entry filter for this collection.
+ # Creates an instance of Jekyll::EntryFilter.
+ #
+ # Returns the instance of Jekyll::EntryFilter for this collection.
+ def entry_filter
+ @entry_filter ||= Jekyll::EntryFilter.new(site, relative_directory)
+ end
+
+ # An inspect string.
+ #
+ # Returns the inspect string
+ def inspect
+ "#<#{self.class} @label=#{label} docs=#{docs}>"
+ end
+
+ # Produce a sanitized label name
+ # Label names may not contain anything but alphanumeric characters,
+ # underscores, and hyphens.
+ #
+ # label - the possibly-unsafe label
+ #
+ # Returns a sanitized version of the label.
+ def sanitize_label(label)
+ label.gsub(%r![^a-z0-9_\-.]!i, "")
+ end
+
+ # Produce a representation of this Collection for use in Liquid.
+ # Exposes two attributes:
+ # - label
+ # - docs
+ #
+ # Returns a representation of this collection for use in Liquid.
+ def to_liquid
+ Drops::CollectionDrop.new self
+ end
+
+ # Whether the collection's documents ought to be written as individual
+ # files in the output.
+ #
+ # Returns true if the 'write' metadata is true, false otherwise.
+ def write?
+ !!metadata.fetch("output", false)
+ end
+
+ # The URL template to render collection's documents at.
+ #
+ # Returns the URL template to render collection's documents at.
+ def url_template
+ @url_template ||= metadata.fetch("permalink") do
+ Utils.add_permalink_suffix("/:collection/:path", site.permalink_style)
+ end
+ end
+
+ # Extract options for this collection from the site configuration.
+ #
+ # Returns the metadata for this collection
+ def extract_metadata
+ if site.config["collections"].is_a?(Hash)
+ site.config["collections"][label] || {}
+ else
+ {}
+ end
+ end
+
+ private
+
+ def container
+ @container ||= site.config["collections_dir"]
+ end
+
+ def read_document(full_path)
+ doc = Document.new(full_path, :site => site, :collection => self)
+ doc.read
+ docs << doc if site.unpublished || doc.published?
+ end
+
+ def sort_docs!
+ if metadata["order"].is_a?(Array)
+ rearrange_docs!
+ elsif metadata["sort_by"].is_a?(String)
+ sort_docs_by_key!
+ else
+ docs.sort!
+ end
+ end
+
+ # A custom sort function based on Schwartzian transform
+ # Refer https://byparker.com/blog/2017/schwartzian-transform-faster-sorting/ for details
+ def sort_docs_by_key!
+ meta_key = metadata["sort_by"]
+ # Modify `docs` array to cache document's property along with the Document instance
+ docs.map! { |doc| [doc.data[meta_key], doc] }.sort! do |apples, olives|
+ order = determine_sort_order(meta_key, apples, olives)
+
+ # Fall back to `Document#<=>` if the properties were equal or were non-sortable
+ # Otherwise continue with current sort-order
+ if order.nil? || order.zero?
+ apples[-1] <=> olives[-1]
+ else
+ order
+ end
+
+ # Finally restore the `docs` array with just the Document objects themselves
+ end.map!(&:last)
+ end
+
+ def determine_sort_order(sort_key, apples, olives)
+ apple_property, apple_document = apples
+ olive_property, olive_document = olives
+
+ if apple_property.nil? && !olive_property.nil?
+ order_with_warning(sort_key, apple_document, 1)
+ elsif !apple_property.nil? && olive_property.nil?
+ order_with_warning(sort_key, olive_document, -1)
+ else
+ apple_property <=> olive_property
+ end
+ end
+
+ def order_with_warning(sort_key, document, order)
+ Jekyll.logger.warn "Sort warning:", "'#{sort_key}' not defined in #{document.relative_path}"
+ order
+ end
+
+ # Rearrange documents within the `docs` array as listed in the `metadata["order"]` array.
+ #
+ # Involves converting the two arrays into hashes based on relative_paths as keys first, then
+ # merging them to remove duplicates and finally retrieving the Document instances from the
+ # merged array.
+ def rearrange_docs!
+ docs_table = {}
+ custom_order = {}
+
+ # pre-sort to normalize default array across platforms and then proceed to create a Hash
+ # from that sorted array.
+ docs.sort.each do |doc|
+ docs_table[doc.relative_path] = doc
+ end
+
+ metadata["order"].each do |entry|
+ custom_order[File.join(relative_directory, entry)] = nil
+ end
+
+ result = Jekyll::Utils.deep_merge_hashes(custom_order, docs_table).values
+ result.compact!
+ self.docs = result
+ end
+
+ def read_static_file(file_path, full_path)
+ relative_dir = Jekyll.sanitized_path(
+ relative_directory,
+ File.dirname(file_path)
+ ).chomp("/.")
+
+ files << StaticFile.new(
+ site,
+ site.source,
+ relative_dir,
+ File.basename(full_path),
+ self
+ )
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/command.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/command.rb
new file mode 100644
index 0000000..be8890e
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/command.rb
@@ -0,0 +1,105 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Command
+ class << self
+ # A list of subclasses of Jekyll::Command
+ def subclasses
+ @subclasses ||= []
+ end
+
+ # Keep a list of subclasses of Jekyll::Command every time it's inherited
+ # Called automatically.
+ #
+ # base - the subclass
+ #
+ # Returns nothing
+ def inherited(base)
+ subclasses << base
+ super(base)
+ end
+
+ # Run Site#process and catch errors
+ #
+ # site - the Jekyll::Site object
+ #
+ # Returns nothing
+ def process_site(site)
+ site.process
+ rescue Jekyll::Errors::FatalException => e
+ Jekyll.logger.error "ERROR:", "YOUR SITE COULD NOT BE BUILT:"
+ Jekyll.logger.error "", "------------------------------------"
+ Jekyll.logger.error "", e.message
+ exit(1)
+ end
+
+ # Create a full Jekyll configuration with the options passed in as overrides
+ #
+ # options - the configuration overrides
+ #
+ # Returns a full Jekyll configuration
+ def configuration_from_options(options)
+ return options if options.is_a?(Jekyll::Configuration)
+
+ Jekyll.configuration(options)
+ end
+
+ # Add common options to a command for building configuration
+ #
+ # cmd - the Jekyll::Command to add these options to
+ #
+ # Returns nothing
+ # rubocop:disable Metrics/MethodLength
+ def add_build_options(cmd)
+ cmd.option "config", "--config CONFIG_FILE[,CONFIG_FILE2,...]",
+ Array, "Custom configuration file"
+ cmd.option "destination", "-d", "--destination DESTINATION",
+ "The current folder will be generated into DESTINATION"
+ cmd.option "source", "-s", "--source SOURCE", "Custom source directory"
+ cmd.option "future", "--future", "Publishes posts with a future date"
+ cmd.option "limit_posts", "--limit_posts MAX_POSTS", Integer,
+ "Limits the number of posts to parse and publish"
+ cmd.option "watch", "-w", "--[no-]watch", "Watch for changes and rebuild"
+ cmd.option "baseurl", "-b", "--baseurl URL",
+ "Serve the website from the given base URL"
+ cmd.option "force_polling", "--force_polling", "Force watch to use polling"
+ cmd.option "lsi", "--lsi", "Use LSI for improved related posts"
+ cmd.option "show_drafts", "-D", "--drafts", "Render posts in the _drafts folder"
+ cmd.option "unpublished", "--unpublished",
+ "Render posts that were marked as unpublished"
+ cmd.option "disable_disk_cache", "--disable-disk-cache",
+ "Disable caching to disk in non-safe mode"
+ cmd.option "quiet", "-q", "--quiet", "Silence output."
+ cmd.option "verbose", "-V", "--verbose", "Print verbose output."
+ cmd.option "incremental", "-I", "--incremental", "Enable incremental rebuild."
+ cmd.option "strict_front_matter", "--strict_front_matter",
+ "Fail if errors are present in front matter"
+ end
+ # rubocop:enable Metrics/MethodLength
+
+ # Run ::process method in a given set of Jekyll::Command subclasses and suggest
+ # re-running the associated command with --trace switch to obtain any additional
+ # information or backtrace regarding the encountered Exception.
+ #
+ # cmd - the Jekyll::Command to be handled
+ # options - configuration overrides
+ # klass - an array of Jekyll::Command subclasses associated with the command
+ #
+ # Note that all exceptions are rescued..
+ # rubocop: disable Lint/RescueException
+ def process_with_graceful_fail(cmd, options, *klass)
+ klass.each { |k| k.process(options) if k.respond_to?(:process) }
+ rescue Exception => e
+ raise e if cmd.trace
+
+ msg = " Please append `--trace` to the `#{cmd.name}` command "
+ dashes = "-" * msg.length
+ Jekyll.logger.error "", dashes
+ Jekyll.logger.error "Jekyll #{Jekyll::VERSION} ", msg
+ Jekyll.logger.error "", " for any additional information or backtrace. "
+ Jekyll.logger.abort_with "", dashes
+ end
+ # rubocop: enable Lint/RescueException
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/build.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/build.rb
new file mode 100644
index 0000000..204b2a1
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/build.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Commands
+ class Build < Command
+ class << self
+ # Create the Mercenary command for the Jekyll CLI for this Command
+ def init_with_program(prog)
+ prog.command(:build) do |c|
+ c.syntax "build [options]"
+ c.description "Build your site"
+ c.alias :b
+
+ add_build_options(c)
+
+ c.action do |_, options|
+ options["serving"] = false
+ process_with_graceful_fail(c, options, self)
+ end
+ end
+ end
+
+ # Build your jekyll site
+ # Continuously watch if `watch` is set to true in the config.
+ def process(options)
+ # Adjust verbosity quickly
+ Jekyll.logger.adjust_verbosity(options)
+
+ options = configuration_from_options(options)
+ site = Jekyll::Site.new(options)
+
+ if options.fetch("skip_initial_build", false)
+ Jekyll.logger.warn "Build Warning:",
+ "Skipping the initial build. This may result in an out-of-date site."
+ else
+ build(site, options)
+ end
+
+ if options.fetch("detach", false)
+ Jekyll.logger.info "Auto-regeneration:",
+ "disabled when running server detached."
+ elsif options.fetch("watch", false)
+ watch(site, options)
+ else
+ Jekyll.logger.info "Auto-regeneration:", "disabled. Use --watch to enable."
+ end
+ end
+
+ # Build your Jekyll site.
+ #
+ # site - the Jekyll::Site instance to build
+ # options - A Hash of options passed to the command
+ #
+ # Returns nothing.
+ def build(site, options)
+ t = Time.now
+ source = File.expand_path(options["source"])
+ destination = File.expand_path(options["destination"])
+ incremental = options["incremental"]
+ Jekyll.logger.info "Source:", source
+ Jekyll.logger.info "Destination:", destination
+ Jekyll.logger.info "Incremental build:",
+ (incremental ? "enabled" : "disabled. Enable with --incremental")
+ Jekyll.logger.info "Generating..."
+ process_site(site)
+ Jekyll.logger.info "", "done in #{(Time.now - t).round(3)} seconds."
+ end
+
+ # Private: Watch for file changes and rebuild the site.
+ #
+ # site - A Jekyll::Site instance
+ # options - A Hash of options passed to the command
+ #
+ # Returns nothing.
+ def watch(site, options)
+ External.require_with_graceful_fail "jekyll-watch"
+ Jekyll::Watcher.watch(options, site)
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/clean.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/clean.rb
new file mode 100644
index 0000000..9b657a4
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/clean.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Commands
+ class Clean < Command
+ class << self
+ def init_with_program(prog)
+ prog.command(:clean) do |c|
+ c.syntax "clean [subcommand]"
+ c.description "Clean the site (removes site output and metadata file) without building."
+
+ add_build_options(c)
+
+ c.action do |_, options|
+ Jekyll::Commands::Clean.process(options)
+ end
+ end
+ end
+
+ def process(options)
+ options = configuration_from_options(options)
+ destination = options["destination"]
+ metadata_file = File.join(options["source"], ".jekyll-metadata")
+ cache_dir = File.join(options["source"], options["cache_dir"])
+ sass_cache = ".sass-cache"
+
+ remove(destination, :checker_func => :directory?)
+ remove(metadata_file, :checker_func => :file?)
+ remove(cache_dir, :checker_func => :directory?)
+ remove(sass_cache, :checker_func => :directory?)
+ end
+
+ def remove(filename, checker_func: :file?)
+ if File.public_send(checker_func, filename)
+ Jekyll.logger.info "Cleaner:", "Removing #{filename}..."
+ FileUtils.rm_rf(filename)
+ else
+ Jekyll.logger.info "Cleaner:", "Nothing to do for #{filename}."
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/doctor.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/doctor.rb
new file mode 100644
index 0000000..eec7133
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/doctor.rb
@@ -0,0 +1,177 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Commands
+ class Doctor < Command
+ class << self
+ def init_with_program(prog)
+ prog.command(:doctor) do |c|
+ c.syntax "doctor"
+ c.description "Search site and print specific deprecation warnings"
+ c.alias(:hyde)
+
+ c.option "config", "--config CONFIG_FILE[,CONFIG_FILE2,...]", Array,
+ "Custom configuration file"
+
+ c.action do |_, options|
+ Jekyll::Commands::Doctor.process(options)
+ end
+ end
+ end
+
+ def process(options)
+ site = Jekyll::Site.new(configuration_from_options(options))
+ site.reset
+ site.read
+ site.generate
+
+ if healthy?(site)
+ Jekyll.logger.info "Your test results", "are in. Everything looks fine."
+ else
+ abort
+ end
+ end
+
+ def healthy?(site)
+ [
+ fsnotify_buggy?(site),
+ !deprecated_relative_permalinks(site),
+ !conflicting_urls(site),
+ !urls_only_differ_by_case(site),
+ proper_site_url?(site),
+ properly_gathered_posts?(site),
+ ].all?
+ end
+
+ def properly_gathered_posts?(site)
+ return true if site.config["collections_dir"].empty?
+
+ posts_at_root = site.in_source_dir("_posts")
+ return true unless File.directory?(posts_at_root)
+
+ Jekyll.logger.warn "Warning:",
+ "Detected '_posts' directory outside custom `collections_dir`!"
+ Jekyll.logger.warn "",
+ "Please move '#{posts_at_root}' into the custom directory at " \
+ "'#{site.in_source_dir(site.config["collections_dir"])}'"
+ false
+ end
+
+ def deprecated_relative_permalinks(site)
+ if site.config["relative_permalinks"]
+ Jekyll::Deprecator.deprecation_message "Your site still uses relative permalinks, " \
+ "which was removed in Jekyll v3.0.0."
+ true
+ end
+ end
+
+ def conflicting_urls(site)
+ conflicting_urls = false
+ destination_map(site).each do |dest, paths|
+ next unless paths.size > 1
+
+ conflicting_urls = true
+ Jekyll.logger.warn "Conflict:",
+ "The following destination is shared by multiple files."
+ Jekyll.logger.warn "", "The written file may end up with unexpected contents."
+ Jekyll.logger.warn "", dest.to_s.cyan
+ paths.each { |path| Jekyll.logger.warn "", " - #{path}" }
+ Jekyll.logger.warn ""
+ end
+ conflicting_urls
+ end
+
+ def fsnotify_buggy?(_site)
+ return true unless Utils::Platforms.osx?
+
+ if Dir.pwd != `pwd`.strip
+ Jekyll.logger.error <<~STR
+ We have detected that there might be trouble using fsevent on your
+ operating system, you can read https://github.com/thibaudgg/rb-fsevent/wiki/no-fsevents-fired-(OSX-bug)
+ for possible workarounds or you can work around it immediately
+ with `--force-polling`.
+ STR
+
+ false
+ end
+
+ true
+ end
+
+ def urls_only_differ_by_case(site)
+ urls_only_differ_by_case = false
+ urls = case_insensitive_urls(site.pages + site.docs_to_write, site.dest)
+ urls.each_value do |real_urls|
+ next unless real_urls.uniq.size > 1
+
+ urls_only_differ_by_case = true
+ Jekyll.logger.warn "Warning:", "The following URLs only differ by case. On a " \
+ "case-insensitive file system one of the URLs will be " \
+ "overwritten by the other: #{real_urls.join(", ")}"
+ end
+ urls_only_differ_by_case
+ end
+
+ def proper_site_url?(site)
+ url = site.config["url"]
+ [
+ url_exists?(url),
+ url_valid?(url),
+ url_absolute(url),
+ ].all?
+ end
+
+ private
+
+ def destination_map(site)
+ {}.tap do |result|
+ site.each_site_file do |thing|
+ next if allow_used_permalink?(thing)
+
+ dest_path = thing.destination(site.dest)
+ (result[dest_path] ||= []) << thing.path
+ end
+ end
+ end
+
+ def allow_used_permalink?(item)
+ defined?(JekyllRedirectFrom) && item.is_a?(JekyllRedirectFrom::RedirectPage)
+ end
+
+ def case_insensitive_urls(things, destination)
+ things.each_with_object({}) do |thing, memo|
+ dest = thing.destination(destination)
+ (memo[dest.downcase] ||= []) << dest
+ end
+ end
+
+ def url_exists?(url)
+ return true unless url.nil? || url.empty?
+
+ Jekyll.logger.warn "Warning:", "You didn't set an URL in the config file, you may " \
+ "encounter problems with some plugins."
+ false
+ end
+
+ def url_valid?(url)
+ Addressable::URI.parse(url)
+ true
+ # Addressable::URI#parse only raises a TypeError
+ # https://github.com/sporkmonger/addressable/blob/0a0e96acb17225f9b1c9cab0bad332b448934c9a/lib/addressable/uri.rb#L103
+ rescue TypeError
+ Jekyll.logger.warn "Warning:", "The site URL does not seem to be valid, " \
+ "check the value of `url` in your config file."
+ false
+ end
+
+ def url_absolute(url)
+ return true if url.is_a?(String) && Addressable::URI.parse(url).absolute?
+
+ Jekyll.logger.warn "Warning:", "Your site URL does not seem to be absolute, " \
+ "check the value of `url` in your config file."
+ false
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/help.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/help.rb
new file mode 100644
index 0000000..90403df
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/help.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Commands
+ class Help < Command
+ class << self
+ def init_with_program(prog)
+ prog.command(:help) do |c|
+ c.syntax "help [subcommand]"
+ c.description "Show the help message, optionally for a given subcommand."
+
+ c.action do |args, _|
+ cmd = (args.first || "").to_sym
+ if args.empty?
+ Jekyll.logger.info prog.to_s
+ elsif prog.has_command? cmd
+ Jekyll.logger.info prog.commands[cmd].to_s
+ else
+ invalid_command(prog, cmd)
+ abort
+ end
+ end
+ end
+ end
+
+ def invalid_command(prog, cmd)
+ Jekyll.logger.error "Error:",
+ "Hmm... we don't know what the '#{cmd}' command is."
+ Jekyll.logger.info "Valid commands:", prog.commands.keys.join(", ")
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/new.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/new.rb
new file mode 100644
index 0000000..161a3dd
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/new.rb
@@ -0,0 +1,168 @@
+# frozen_string_literal: true
+
+require "erb"
+
+module Jekyll
+ module Commands
+ class New < Command
+ class << self
+ def init_with_program(prog)
+ prog.command(:new) do |c|
+ c.syntax "new PATH"
+ c.description "Creates a new Jekyll site scaffold in PATH"
+
+ c.option "force", "--force", "Force creation even if PATH already exists"
+ c.option "blank", "--blank", "Creates scaffolding but with empty files"
+ c.option "skip-bundle", "--skip-bundle", "Skip 'bundle install'"
+
+ c.action do |args, options|
+ Jekyll::Commands::New.process(args, options)
+ end
+ end
+ end
+
+ def process(args, options = {})
+ raise ArgumentError, "You must specify a path." if args.empty?
+
+ new_blog_path = File.expand_path(args.join(" "), Dir.pwd)
+ FileUtils.mkdir_p new_blog_path
+ if preserve_source_location?(new_blog_path, options)
+ Jekyll.logger.error "Conflict:", "#{new_blog_path} exists and is not empty."
+ Jekyll.logger.abort_with "", "Ensure #{new_blog_path} is empty or else try again " \
+ "with `--force` to proceed and overwrite any files."
+ end
+
+ if options["blank"]
+ create_blank_site new_blog_path
+ else
+ create_site new_blog_path
+ end
+
+ after_install(new_blog_path, options)
+ end
+
+ def blank_template
+ File.expand_path("../../blank_template", __dir__)
+ end
+
+ def create_blank_site(path)
+ FileUtils.cp_r blank_template + "/.", path
+ FileUtils.chmod_R "u+w", path
+
+ Dir.chdir(path) do
+ FileUtils.mkdir(%w(_data _drafts _includes _posts))
+ end
+ end
+
+ def scaffold_post_content
+ ERB.new(File.read(File.expand_path(scaffold_path, site_template))).result
+ end
+
+ # Internal: Gets the filename of the sample post to be created
+ #
+ # Returns the filename of the sample post, as a String
+ def initialized_post_name
+ "_posts/#{Time.now.strftime("%Y-%m-%d")}-welcome-to-jekyll.markdown"
+ end
+
+ private
+
+ def gemfile_contents
+ <<~RUBY
+ source "https://rubygems.org"
+ # Hello! This is where you manage which Jekyll version is used to run.
+ # When you want to use a different version, change it below, save the
+ # file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
+ #
+ # bundle exec jekyll serve
+ #
+ # This will help ensure the proper Jekyll version is running.
+ # Happy Jekylling!
+ gem "jekyll", "~> #{Jekyll::VERSION}"
+ # This is the default theme for new Jekyll sites. You may change this to anything you like.
+ gem "minima", "~> 2.5"
+ # If you want to use GitHub Pages, remove the "gem "jekyll"" above and
+ # uncomment the line below. To upgrade, run `bundle update github-pages`.
+ # gem "github-pages", group: :jekyll_plugins
+ # If you have any plugins, put them here!
+ group :jekyll_plugins do
+ gem "jekyll-feed", "~> 0.12"
+ end
+
+ # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
+ # and associated library.
+ platforms :mingw, :x64_mingw, :mswin, :jruby do
+ gem "tzinfo", ">= 1", "< 3"
+ gem "tzinfo-data"
+ end
+
+ # Performance-booster for watching directories on Windows
+ gem "wdm", "~> 0.1", :platforms => [:mingw, :x64_mingw, :mswin]
+
+ # Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem
+ # do not have a Java counterpart.
+ gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby]
+ RUBY
+ end
+
+ def create_site(new_blog_path)
+ create_sample_files new_blog_path
+
+ File.write(File.expand_path(initialized_post_name, new_blog_path), scaffold_post_content)
+
+ File.write(File.expand_path("Gemfile", new_blog_path), gemfile_contents)
+ end
+
+ def preserve_source_location?(path, options)
+ !options["force"] && !Dir["#{path}/**/*"].empty?
+ end
+
+ def create_sample_files(path)
+ FileUtils.cp_r site_template + "/.", path
+ FileUtils.chmod_R "u+w", path
+ FileUtils.rm File.expand_path(scaffold_path, path)
+ end
+
+ def site_template
+ File.expand_path("../../site_template", __dir__)
+ end
+
+ def scaffold_path
+ "_posts/0000-00-00-welcome-to-jekyll.markdown.erb"
+ end
+
+ # After a new blog has been created, print a success notification and
+ # then automatically execute bundle install from within the new blog dir
+ # unless the user opts to generate a blank blog or skip 'bundle install'.
+
+ def after_install(path, options = {})
+ unless options["blank"] || options["skip-bundle"]
+ begin
+ require "bundler"
+ bundle_install path
+ rescue LoadError
+ Jekyll.logger.info "Could not load Bundler. Bundle install skipped."
+ end
+ end
+
+ Jekyll.logger.info "New jekyll site installed in #{path.cyan}."
+ Jekyll.logger.info "Bundle install skipped." if options["skip-bundle"]
+ end
+
+ def bundle_install(path)
+ Jekyll.logger.info "Running bundle install in #{path.cyan}..."
+ Dir.chdir(path) do
+ exe = Gem.bin_path("bundler", "bundle")
+ process, output = Jekyll::Utils::Exec.run("ruby", exe, "install")
+
+ output.to_s.each_line do |line|
+ Jekyll.logger.info("Bundler:".green, line.strip) unless line.to_s.empty?
+ end
+
+ raise SystemExit unless process.success?
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/new_theme.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/new_theme.rb
new file mode 100644
index 0000000..3419d17
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/new_theme.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require "erb"
+
+module Jekyll
+ module Commands
+ class NewTheme < Jekyll::Command
+ class << self
+ def init_with_program(prog)
+ prog.command(:"new-theme") do |c|
+ c.syntax "new-theme NAME"
+ c.description "Creates a new Jekyll theme scaffold"
+ c.option "code_of_conduct", "-c", "--code-of-conduct",
+ "Include a Code of Conduct. (defaults to false)"
+
+ c.action do |args, opts|
+ Jekyll::Commands::NewTheme.process(args, opts)
+ end
+ end
+ end
+
+ def process(args, opts)
+ if !args || args.empty?
+ raise Jekyll::Errors::InvalidThemeName, "You must specify a theme name."
+ end
+
+ new_theme_name = args.join("_")
+ theme = Jekyll::ThemeBuilder.new(new_theme_name, opts)
+ Jekyll.logger.abort_with "Conflict:", "#{theme.path} already exists." if theme.path.exist?
+
+ theme.create!
+ Jekyll.logger.info "Your new Jekyll theme, #{theme.name.cyan}, " \
+ "is ready for you in #{theme.path.to_s.cyan}!"
+ Jekyll.logger.info "For help getting started, read #{theme.path}/README.md."
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve.rb
new file mode 100644
index 0000000..6abd893
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve.rb
@@ -0,0 +1,372 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Commands
+ class Serve < Command
+ # Similar to the pattern in Utils::ThreadEvent except we are maintaining the
+ # state of @running instead of just signaling an event. We have to maintain this
+ # state since Serve is just called via class methods instead of an instance
+ # being created each time.
+ @mutex = Mutex.new
+ @run_cond = ConditionVariable.new
+ @running = false
+
+ class << self
+ COMMAND_OPTIONS = {
+ "ssl_cert" => ["--ssl-cert [CERT]", "X.509 (SSL) certificate."],
+ "host" => ["host", "-H", "--host [HOST]", "Host to bind to"],
+ "open_url" => ["-o", "--open-url", "Launch your site in a browser"],
+ "detach" => ["-B", "--detach",
+ "Run the server in the background",],
+ "ssl_key" => ["--ssl-key [KEY]", "X.509 (SSL) Private Key."],
+ "port" => ["-P", "--port [PORT]", "Port to listen on"],
+ "show_dir_listing" => ["--show-dir-listing",
+ "Show a directory listing instead of loading " \
+ "your index file.",],
+ "skip_initial_build" => ["skip_initial_build", "--skip-initial-build",
+ "Skips the initial site build which occurs before " \
+ "the server is started.",],
+ "livereload" => ["-l", "--livereload",
+ "Use LiveReload to automatically refresh browsers",],
+ "livereload_ignore" => ["--livereload-ignore GLOB1[,GLOB2[,...]]",
+ Array,
+ "Files for LiveReload to ignore. " \
+ "Remember to quote the values so your shell " \
+ "won't expand them",],
+ "livereload_min_delay" => ["--livereload-min-delay [SECONDS]",
+ "Minimum reload delay",],
+ "livereload_max_delay" => ["--livereload-max-delay [SECONDS]",
+ "Maximum reload delay",],
+ "livereload_port" => ["--livereload-port [PORT]", Integer,
+ "Port for LiveReload to listen on",],
+ }.freeze
+
+ DIRECTORY_INDEX = %w(
+ index.htm
+ index.html
+ index.rhtml
+ index.xht
+ index.xhtml
+ index.cgi
+ index.xml
+ index.json
+ ).freeze
+
+ LIVERELOAD_PORT = 35_729
+ LIVERELOAD_DIR = File.join(__dir__, "serve", "livereload_assets")
+
+ attr_reader :mutex, :run_cond, :running
+ alias_method :running?, :running
+
+ def init_with_program(prog)
+ prog.command(:serve) do |cmd|
+ cmd.description "Serve your site locally"
+ cmd.syntax "serve [options]"
+ cmd.alias :server
+ cmd.alias :s
+
+ add_build_options(cmd)
+ COMMAND_OPTIONS.each do |key, val|
+ cmd.option key, *val
+ end
+
+ cmd.action do |_, opts|
+ opts["serving"] = true
+ opts["watch"] = true unless opts.key?("watch")
+
+ # Set the reactor to nil so any old reactor will be GCed.
+ # We can't unregister a hook so while running tests we don't want to
+ # inadvertently keep using a reactor created by a previous test.
+ @reload_reactor = nil
+
+ config = configuration_from_options(opts)
+ config["url"] = default_url(config) if Jekyll.env == "development"
+
+ process_with_graceful_fail(cmd, config, Build, Serve)
+ end
+ end
+ end
+
+ #
+
+ def process(opts)
+ opts = configuration_from_options(opts)
+ destination = opts["destination"]
+ if opts["livereload"]
+ opts["livereload_port"] ||= LIVERELOAD_PORT
+ validate_options(opts)
+ register_reload_hooks(opts)
+ end
+ setup(destination)
+
+ start_up_webrick(opts, destination)
+ end
+
+ def shutdown
+ @server.shutdown if running?
+ end
+
+ # Perform logical validation of CLI options
+
+ private
+
+ def validate_options(opts)
+ if opts["livereload"]
+ if opts["detach"]
+ Jekyll.logger.warn "Warning:", "--detach and --livereload are mutually exclusive. " \
+ "Choosing --livereload"
+ opts["detach"] = false
+ end
+ if opts["ssl_cert"] || opts["ssl_key"]
+ # This is not technically true. LiveReload works fine over SSL, but
+ # EventMachine's SSL support in Windows requires building the gem's
+ # native extensions against OpenSSL and that proved to be a process
+ # so tedious that expecting users to do it is a non-starter.
+ Jekyll.logger.abort_with "Error:", "LiveReload does not support SSL"
+ end
+ unless opts["watch"]
+ # Using livereload logically implies you want to watch the files
+ opts["watch"] = true
+ end
+ elsif %w(livereload_min_delay
+ livereload_max_delay
+ livereload_ignore
+ livereload_port).any? { |o| opts[o] }
+ Jekyll.logger.abort_with "--livereload-min-delay, --livereload-max-delay, " \
+ "--livereload-ignore, and --livereload-port require " \
+ "the --livereload option."
+ end
+ end
+
+ def register_reload_hooks(opts)
+ require_relative "serve/live_reload_reactor"
+ @reload_reactor = LiveReloadReactor.new
+
+ Jekyll::Hooks.register(:site, :post_render) do |site|
+ @changed_pages = []
+ site.each_site_file do |item|
+ @changed_pages << item if site.regenerator.regenerate?(item)
+ end
+ end
+
+ # A note on ignoring files: LiveReload errs on the side of reloading when it
+ # comes to the message it gets. If, for example, a page is ignored but a CSS
+ # file linked in the page isn't, the page will still be reloaded if the CSS
+ # file is contained in the message sent to LiveReload. Additionally, the
+ # path matching is very loose so that a message to reload "/" will always
+ # lead the page to reload since every page starts with "/".
+ Jekyll::Hooks.register(:site, :post_write) do
+ if @changed_pages && @reload_reactor && @reload_reactor.running?
+ ignore, @changed_pages = @changed_pages.partition do |p|
+ Array(opts["livereload_ignore"]).any? do |filter|
+ File.fnmatch(filter, p.relative_path)
+ end
+ end
+ Jekyll.logger.debug "LiveReload:", "Ignoring #{ignore.map(&:relative_path)}"
+ @reload_reactor.reload(@changed_pages)
+ end
+ @changed_pages = nil
+ end
+ end
+
+ # Do a base pre-setup of WEBRick so that everything is in place
+ # when we get ready to party, checking for an setting up an error page
+ # and making sure our destination exists.
+ #
+ # rubocop:disable Security/IoMethods
+ def setup(destination)
+ require_relative "serve/servlet"
+
+ FileUtils.mkdir_p(destination)
+ if File.exist?(File.join(destination, "404.html"))
+ WEBrick::HTTPResponse.class_eval do
+ def create_error_page
+ @header["Content-Type"] = "text/html; charset=UTF-8"
+ @body = IO.read(File.join(@config[:DocumentRoot], "404.html"))
+ end
+ end
+ end
+ end
+ # rubocop:enable Security/IoMethods
+
+ def webrick_opts(opts)
+ opts = {
+ :JekyllOptions => opts,
+ :DoNotReverseLookup => true,
+ :MimeTypes => mime_types,
+ :MimeTypesCharset => mime_types_charset,
+ :DocumentRoot => opts["destination"],
+ :StartCallback => start_callback(opts["detach"]),
+ :StopCallback => stop_callback(opts["detach"]),
+ :BindAddress => opts["host"],
+ :Port => opts["port"],
+ :DirectoryIndex => DIRECTORY_INDEX,
+ }
+
+ opts[:DirectoryIndex] = [] if opts[:JekyllOptions]["show_dir_listing"]
+
+ enable_ssl(opts)
+ enable_logging(opts)
+ opts
+ end
+
+ def start_up_webrick(opts, destination)
+ @reload_reactor.start(opts) if opts["livereload"]
+
+ @server = WEBrick::HTTPServer.new(webrick_opts(opts)).tap { |o| o.unmount("") }
+ @server.mount(opts["baseurl"].to_s, Servlet, destination, file_handler_opts)
+
+ Jekyll.logger.info "Server address:", server_address(@server, opts)
+ launch_browser @server, opts if opts["open_url"]
+ boot_or_detach @server, opts
+ end
+
+ # Recreate NondisclosureName under utf-8 circumstance
+ def file_handler_opts
+ WEBrick::Config::FileHandler.merge(
+ :FancyIndexing => true,
+ :NondisclosureName => [
+ ".ht*", "~*",
+ ]
+ )
+ end
+
+ def server_address(server, options = {})
+ format_url(
+ server.config[:SSLEnable],
+ server.config[:BindAddress],
+ server.config[:Port],
+ options["baseurl"]
+ )
+ end
+
+ def format_url(ssl_enabled, address, port, baseurl = nil)
+ format("%<prefix>s://%<address>s:%<port>i%<baseurl>s",
+ :prefix => ssl_enabled ? "https" : "http",
+ :address => address,
+ :port => port,
+ :baseurl => baseurl ? "#{baseurl}/" : "")
+ end
+
+ def default_url(opts)
+ config = configuration_from_options(opts)
+ format_url(
+ config["ssl_cert"] && config["ssl_key"],
+ config["host"] == "127.0.0.1" ? "localhost" : config["host"],
+ config["port"]
+ )
+ end
+
+ def launch_browser(server, opts)
+ address = server_address(server, opts)
+ return system "start", address if Utils::Platforms.windows?
+ return system "xdg-open", address if Utils::Platforms.linux?
+ return system "open", address if Utils::Platforms.osx?
+
+ Jekyll.logger.error "Refusing to launch browser. Platform launcher unknown."
+ end
+
+ # Keep in our area with a thread or detach the server as requested
+ # by the user. This method determines what we do based on what you
+ # ask us to do.
+ def boot_or_detach(server, opts)
+ if opts["detach"]
+ pid = Process.fork do
+ # Detach the process from controlling terminal
+ $stdin.reopen("/dev/null", "r")
+ $stdout.reopen("/dev/null", "w")
+ $stderr.reopen("/dev/null", "w")
+ server.start
+ end
+
+ Process.detach(pid)
+ Jekyll.logger.info "Server detached with pid '#{pid}'.",
+ "Run `pkill -f jekyll' or `kill -9 #{pid}' to stop the server."
+
+ # Exit without running `at_exit` inherited by the forked process.
+ Process.exit! 0
+ else
+ t = Thread.new { server.start }
+ trap("INT") { server.shutdown }
+ t.join
+ end
+ end
+
+ # Make the stack verbose if the user requests it.
+ def enable_logging(opts)
+ opts[:AccessLog] = []
+ level = WEBrick::Log.const_get(opts[:JekyllOptions]["verbose"] ? :DEBUG : :WARN)
+ opts[:Logger] = WEBrick::Log.new($stdout, level)
+ end
+
+ # Add SSL to the stack if the user triggers --enable-ssl and they
+ # provide both types of certificates commonly needed. Raise if they
+ # forget to add one of the certificates.
+ def enable_ssl(opts)
+ cert, key, src =
+ opts[:JekyllOptions].values_at("ssl_cert", "ssl_key", "source")
+
+ return if cert.nil? && key.nil?
+ raise "Missing --ssl_cert or --ssl_key. Both are required." unless cert && key
+
+ require "openssl"
+ require "webrick/https"
+
+ opts[:SSLCertificate] = OpenSSL::X509::Certificate.new(read_file(src, cert))
+ begin
+ opts[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(read_file(src, key))
+ rescue StandardError
+ if defined?(OpenSSL::PKey::EC)
+ opts[:SSLPrivateKey] = OpenSSL::PKey::EC.new(read_file(src, key))
+ else
+ raise
+ end
+ end
+ opts[:SSLEnable] = true
+ end
+
+ def start_callback(detached)
+ unless detached
+ proc do
+ mutex.synchronize do
+ # Block until EventMachine reactor starts
+ @reload_reactor&.started_event&.wait
+ @running = true
+ Jekyll.logger.info("Server running...", "press ctrl-c to stop.")
+ @run_cond.broadcast
+ end
+ end
+ end
+ end
+
+ def stop_callback(detached)
+ unless detached
+ proc do
+ mutex.synchronize do
+ unless @reload_reactor.nil?
+ @reload_reactor.stop
+ @reload_reactor.stopped_event.wait
+ end
+ @running = false
+ @run_cond.broadcast
+ end
+ end
+ end
+ end
+
+ def mime_types
+ file = File.expand_path("../mime.types", __dir__)
+ WEBrick::HTTPUtils.load_mime_types(file)
+ end
+
+ def mime_types_charset
+ SafeYAML.load_file(File.expand_path("serve/mime_types_charset.json", __dir__))
+ end
+
+ def read_file(source_dir, file_path)
+ File.read(Jekyll.sanitized_path(source_dir, file_path))
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/live_reload_reactor.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/live_reload_reactor.rb
new file mode 100644
index 0000000..78f9408
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/live_reload_reactor.rb
@@ -0,0 +1,119 @@
+# frozen_string_literal: true
+
+require "em-websocket"
+
+require_relative "websockets"
+
+module Jekyll
+ module Commands
+ class Serve
+ class LiveReloadReactor
+ attr_reader :started_event, :stopped_event, :thread
+
+ def initialize
+ @websockets = []
+ @connections_count = 0
+ @started_event = Utils::ThreadEvent.new
+ @stopped_event = Utils::ThreadEvent.new
+ end
+
+ def stop
+ # There is only one EventMachine instance per Ruby process so stopping
+ # it here will stop the reactor thread we have running.
+ EM.stop if EM.reactor_running?
+ Jekyll.logger.debug "LiveReload Server:", "halted"
+ end
+
+ def running?
+ EM.reactor_running?
+ end
+
+ def handle_websockets_event(websocket)
+ websocket.onopen { |handshake| connect(websocket, handshake) }
+ websocket.onclose { disconnect(websocket) }
+ websocket.onmessage { |msg| print_message(msg) }
+ websocket.onerror { |error| log_error(error) }
+ end
+
+ def start(opts)
+ @thread = Thread.new do
+ # Use epoll if the kernel supports it
+ EM.epoll
+ EM.run do
+ EM.error_handler { |e| log_error(e) }
+
+ EM.start_server(
+ opts["host"],
+ opts["livereload_port"],
+ HttpAwareConnection,
+ opts
+ ) do |ws|
+ handle_websockets_event(ws)
+ end
+
+ # Notify blocked threads that EventMachine has started or shutdown
+ EM.schedule { @started_event.set }
+ EM.add_shutdown_hook { @stopped_event.set }
+
+ Jekyll.logger.info "LiveReload address:",
+ "http://#{opts["host"]}:#{opts["livereload_port"]}"
+ end
+ end
+ @thread.abort_on_exception = true
+ end
+
+ # For a description of the protocol see
+ # http://feedback.livereload.com/knowledgebase/articles/86174-livereload-protocol
+ def reload(pages)
+ pages.each do |p|
+ json_message = JSON.dump(
+ :command => "reload",
+ :path => p.url,
+ :liveCSS => true
+ )
+
+ Jekyll.logger.debug "LiveReload:", "Reloading URL #{p.url.inspect}"
+ @websockets.each { |ws| ws.send(json_message) }
+ end
+ end
+
+ private
+
+ def connect(websocket, handshake)
+ @connections_count += 1
+ if @connections_count == 1
+ message = "Browser connected"
+ message += " over SSL/TLS" if handshake.secure?
+ Jekyll.logger.info "LiveReload:", message
+ end
+ websocket.send(
+ JSON.dump(
+ :command => "hello",
+ :protocols => ["http://livereload.com/protocols/official-7"],
+ :serverName => "jekyll"
+ )
+ )
+
+ @websockets << websocket
+ end
+
+ def disconnect(websocket)
+ @websockets.delete(websocket)
+ end
+
+ def print_message(json_message)
+ msg = JSON.parse(json_message)
+ # Not sure what the 'url' command even does in LiveReload. The spec is silent
+ # on its purpose.
+ Jekyll.logger.info "LiveReload:", "Browser URL: #{msg["url"]}" if msg["command"] == "url"
+ end
+
+ def log_error(error)
+ Jekyll.logger.error "LiveReload experienced an error. " \
+ "Run with --trace for more information."
+ raise error
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/livereload_assets/livereload.js b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/livereload_assets/livereload.js
new file mode 100644
index 0000000..eee60ec
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/livereload_assets/livereload.js
@@ -0,0 +1,1183 @@
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+(function() {
+ var Connector, PROTOCOL_6, PROTOCOL_7, Parser, Version, _ref;
+
+ _ref = require('./protocol'), Parser = _ref.Parser, PROTOCOL_6 = _ref.PROTOCOL_6, PROTOCOL_7 = _ref.PROTOCOL_7;
+
+ Version = '2.2.2';
+
+ exports.Connector = Connector = (function() {
+ function Connector(options, WebSocket, Timer, handlers) {
+ this.options = options;
+ this.WebSocket = WebSocket;
+ this.Timer = Timer;
+ this.handlers = handlers;
+ this._uri = "ws" + (this.options.https ? "s" : "") + "://" + this.options.host + ":" + this.options.port + "/livereload";
+ this._nextDelay = this.options.mindelay;
+ this._connectionDesired = false;
+ this.protocol = 0;
+ this.protocolParser = new Parser({
+ connected: (function(_this) {
+ return function(protocol) {
+ _this.protocol = protocol;
+ _this._handshakeTimeout.stop();
+ _this._nextDelay = _this.options.mindelay;
+ _this._disconnectionReason = 'broken';
+ return _this.handlers.connected(protocol);
+ };
+ })(this),
+ error: (function(_this) {
+ return function(e) {
+ _this.handlers.error(e);
+ return _this._closeOnError();
+ };
+ })(this),
+ message: (function(_this) {
+ return function(message) {
+ return _this.handlers.message(message);
+ };
+ })(this)
+ });
+ this._handshakeTimeout = new Timer((function(_this) {
+ return function() {
+ if (!_this._isSocketConnected()) {
+ return;
+ }
+ _this._disconnectionReason = 'handshake-timeout';
+ return _this.socket.close();
+ };
+ })(this));
+ this._reconnectTimer = new Timer((function(_this) {
+ return function() {
+ if (!_this._connectionDesired) {
+ return;
+ }
+ return _this.connect();
+ };
+ })(this));
+ this.connect();
+ }
+
+ Connector.prototype._isSocketConnected = function() {
+ return this.socket && this.socket.readyState === this.WebSocket.OPEN;
+ };
+
+ Connector.prototype.connect = function() {
+ this._connectionDesired = true;
+ if (this._isSocketConnected()) {
+ return;
+ }
+ this._reconnectTimer.stop();
+ this._disconnectionReason = 'cannot-connect';
+ this.protocolParser.reset();
+ this.handlers.connecting();
+ this.socket = new this.WebSocket(this._uri);
+ this.socket.onopen = (function(_this) {
+ return function(e) {
+ return _this._onopen(e);
+ };
+ })(this);
+ this.socket.onclose = (function(_this) {
+ return function(e) {
+ return _this._onclose(e);
+ };
+ })(this);
+ this.socket.onmessage = (function(_this) {
+ return function(e) {
+ return _this._onmessage(e);
+ };
+ })(this);
+ return this.socket.onerror = (function(_this) {
+ return function(e) {
+ return _this._onerror(e);
+ };
+ })(this);
+ };
+
+ Connector.prototype.disconnect = function() {
+ this._connectionDesired = false;
+ this._reconnectTimer.stop();
+ if (!this._isSocketConnected()) {
+ return;
+ }
+ this._disconnectionReason = 'manual';
+ return this.socket.close();
+ };
+
+ Connector.prototype._scheduleReconnection = function() {
+ if (!this._connectionDesired) {
+ return;
+ }
+ if (!this._reconnectTimer.running) {
+ this._reconnectTimer.start(this._nextDelay);
+ return this._nextDelay = Math.min(this.options.maxdelay, this._nextDelay * 2);
+ }
+ };
+
+ Connector.prototype.sendCommand = function(command) {
+ if (this.protocol == null) {
+ return;
+ }
+ return this._sendCommand(command);
+ };
+
+ Connector.prototype._sendCommand = function(command) {
+ return this.socket.send(JSON.stringify(command));
+ };
+
+ Connector.prototype._closeOnError = function() {
+ this._handshakeTimeout.stop();
+ this._disconnectionReason = 'error';
+ return this.socket.close();
+ };
+
+ Connector.prototype._onopen = function(e) {
+ var hello;
+ this.handlers.socketConnected();
+ this._disconnectionReason = 'handshake-failed';
+ hello = {
+ command: 'hello',
+ protocols: [PROTOCOL_6, PROTOCOL_7]
+ };
+ hello.ver = Version;
+ if (this.options.ext) {
+ hello.ext = this.options.ext;
+ }
+ if (this.options.extver) {
+ hello.extver = this.options.extver;
+ }
+ if (this.options.snipver) {
+ hello.snipver = this.options.snipver;
+ }
+ this._sendCommand(hello);
+ return this._handshakeTimeout.start(this.options.handshake_timeout);
+ };
+
+ Connector.prototype._onclose = function(e) {
+ this.protocol = 0;
+ this.handlers.disconnected(this._disconnectionReason, this._nextDelay);
+ return this._scheduleReconnection();
+ };
+
+ Connector.prototype._onerror = function(e) {};
+
+ Connector.prototype._onmessage = function(e) {
+ return this.protocolParser.process(e.data);
+ };
+
+ return Connector;
+
+ })();
+
+}).call(this);
+
+},{"./protocol":6}],2:[function(require,module,exports){
+(function() {
+ var CustomEvents;
+
+ CustomEvents = {
+ bind: function(element, eventName, handler) {
+ if (element.addEventListener) {
+ return element.addEventListener(eventName, handler, false);
+ } else if (element.attachEvent) {
+ element[eventName] = 1;
+ return element.attachEvent('onpropertychange', function(event) {
+ if (event.propertyName === eventName) {
+ return handler();
+ }
+ });
+ } else {
+ throw new Error("Attempt to attach custom event " + eventName + " to something which isn't a DOMElement");
+ }
+ },
+ fire: function(element, eventName) {
+ var event;
+ if (element.addEventListener) {
+ event = document.createEvent('HTMLEvents');
+ event.initEvent(eventName, true, true);
+ return document.dispatchEvent(event);
+ } else if (element.attachEvent) {
+ if (element[eventName]) {
+ return element[eventName]++;
+ }
+ } else {
+ throw new Error("Attempt to fire custom event " + eventName + " on something which isn't a DOMElement");
+ }
+ }
+ };
+
+ exports.bind = CustomEvents.bind;
+
+ exports.fire = CustomEvents.fire;
+
+}).call(this);
+
+},{}],3:[function(require,module,exports){
+(function() {
+ var LessPlugin;
+
+ module.exports = LessPlugin = (function() {
+ LessPlugin.identifier = 'less';
+
+ LessPlugin.version = '1.0';
+
+ function LessPlugin(window, host) {
+ this.window = window;
+ this.host = host;
+ }
+
+ LessPlugin.prototype.reload = function(path, options) {
+ if (this.window.less && this.window.less.refresh) {
+ if (path.match(/\.less$/i)) {
+ return this.reloadLess(path);
+ }
+ if (options.originalPath.match(/\.less$/i)) {
+ return this.reloadLess(options.originalPath);
+ }
+ }
+ return false;
+ };
+
+ LessPlugin.prototype.reloadLess = function(path) {
+ var link, links, _i, _len;
+ links = (function() {
+ var _i, _len, _ref, _results;
+ _ref = document.getElementsByTagName('link');
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ link = _ref[_i];
+ if (link.href && link.rel.match(/^stylesheet\/less$/i) || (link.rel.match(/stylesheet/i) && link.type.match(/^text\/(x-)?less$/i))) {
+ _results.push(link);
+ }
+ }
+ return _results;
+ })();
+ if (links.length === 0) {
+ return false;
+ }
+ for (_i = 0, _len = links.length; _i < _len; _i++) {
+ link = links[_i];
+ link.href = this.host.generateCacheBustUrl(link.href);
+ }
+ this.host.console.log("LiveReload is asking LESS to recompile all stylesheets");
+ this.window.less.refresh(true);
+ return true;
+ };
+
+ LessPlugin.prototype.analyze = function() {
+ return {
+ disable: !!(this.window.less && this.window.less.refresh)
+ };
+ };
+
+ return LessPlugin;
+
+ })();
+
+}).call(this);
+
+},{}],4:[function(require,module,exports){
+(function() {
+ var Connector, LiveReload, Options, Reloader, Timer,
+ __hasProp = {}.hasOwnProperty;
+
+ Connector = require('./connector').Connector;
+
+ Timer = require('./timer').Timer;
+
+ Options = require('./options').Options;
+
+ Reloader = require('./reloader').Reloader;
+
+ exports.LiveReload = LiveReload = (function() {
+ function LiveReload(window) {
+ var k, v, _ref;
+ this.window = window;
+ this.listeners = {};
+ this.plugins = [];
+ this.pluginIdentifiers = {};
+ this.console = this.window.console && this.window.console.log && this.window.console.error ? this.window.location.href.match(/LR-verbose/) ? this.window.console : {
+ log: function() {},
+ error: this.window.console.error.bind(this.window.console)
+ } : {
+ log: function() {},
+ error: function() {}
+ };
+ if (!(this.WebSocket = this.window.WebSocket || this.window.MozWebSocket)) {
+ this.console.error("LiveReload disabled because the browser does not seem to support web sockets");
+ return;
+ }
+ if ('LiveReloadOptions' in window) {
+ this.options = new Options();
+ _ref = window['LiveReloadOptions'];
+ for (k in _ref) {
+ if (!__hasProp.call(_ref, k)) continue;
+ v = _ref[k];
+ this.options.set(k, v);
+ }
+ } else {
+ this.options = Options.extract(this.window.document);
+ if (!this.options) {
+ this.console.error("LiveReload disabled because it could not find its own <SCRIPT> tag");
+ return;
+ }
+ }
+ this.reloader = new Reloader(this.window, this.console, Timer);
+ this.connector = new Connector(this.options, this.WebSocket, Timer, {
+ connecting: (function(_this) {
+ return function() {};
+ })(this),
+ socketConnected: (function(_this) {
+ return function() {};
+ })(this),
+ connected: (function(_this) {
+ return function(protocol) {
+ var _base;
+ if (typeof (_base = _this.listeners).connect === "function") {
+ _base.connect();
+ }
+ _this.log("LiveReload is connected to " + _this.options.host + ":" + _this.options.port + " (protocol v" + protocol + ").");
+ return _this.analyze();
+ };
+ })(this),
+ error: (function(_this) {
+ return function(e) {
+ if (e instanceof ProtocolError) {
+ if (typeof console !== "undefined" && console !== null) {
+ return console.log("" + e.message + ".");
+ }
+ } else {
+ if (typeof console !== "undefined" && console !== null) {
+ return console.log("LiveReload internal error: " + e.message);
+ }
+ }
+ };
+ })(this),
+ disconnected: (function(_this) {
+ return function(reason, nextDelay) {
+ var _base;
+ if (typeof (_base = _this.listeners).disconnect === "function") {
+ _base.disconnect();
+ }
+ switch (reason) {
+ case 'cannot-connect':
+ return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + ", will retry in " + nextDelay + " sec.");
+ case 'broken':
+ return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + ", reconnecting in " + nextDelay + " sec.");
+ case 'handshake-timeout':
+ return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake timeout), will retry in " + nextDelay + " sec.");
+ case 'handshake-failed':
+ return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake failed), will retry in " + nextDelay + " sec.");
+ case 'manual':
+ break;
+ case 'error':
+ break;
+ default:
+ return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + " (" + reason + "), reconnecting in " + nextDelay + " sec.");
+ }
+ };
+ })(this),
+ message: (function(_this) {
+ return function(message) {
+ switch (message.command) {
+ case 'reload':
+ return _this.performReload(message);
+ case 'alert':
+ return _this.performAlert(message);
+ }
+ };
+ })(this)
+ });
+ this.initialized = true;
+ }
+
+ LiveReload.prototype.on = function(eventName, handler) {
+ return this.listeners[eventName] = handler;
+ };
+
+ LiveReload.prototype.log = function(message) {
+ return this.console.log("" + message);
+ };
+
+ LiveReload.prototype.performReload = function(message) {
+ var _ref, _ref1;
+ this.log("LiveReload received reload request: " + (JSON.stringify(message, null, 2)));
+ return this.reloader.reload(message.path, {
+ liveCSS: (_ref = message.liveCSS) != null ? _ref : true,
+ liveImg: (_ref1 = message.liveImg) != null ? _ref1 : true,
+ originalPath: message.originalPath || '',
+ overrideURL: message.overrideURL || '',
+ serverURL: "http://" + this.options.host + ":" + this.options.port
+ });
+ };
+
+ LiveReload.prototype.performAlert = function(message) {
+ return alert(message.message);
+ };
+
+ LiveReload.prototype.shutDown = function() {
+ var _base;
+ if (!this.initialized) {
+ return;
+ }
+ this.connector.disconnect();
+ this.log("LiveReload disconnected.");
+ return typeof (_base = this.listeners).shutdown === "function" ? _base.shutdown() : void 0;
+ };
+
+ LiveReload.prototype.hasPlugin = function(identifier) {
+ return !!this.pluginIdentifiers[identifier];
+ };
+
+ LiveReload.prototype.addPlugin = function(pluginClass) {
+ var plugin;
+ if (!this.initialized) {
+ return;
+ }
+ if (this.hasPlugin(pluginClass.identifier)) {
+ return;
+ }
+ this.pluginIdentifiers[pluginClass.identifier] = true;
+ plugin = new pluginClass(this.window, {
+ _livereload: this,
+ _reloader: this.reloader,
+ _connector: this.connector,
+ console: this.console,
+ Timer: Timer,
+ generateCacheBustUrl: (function(_this) {
+ return function(url) {
+ return _this.reloader.generateCacheBustUrl(url);
+ };
+ })(this)
+ });
+ this.plugins.push(plugin);
+ this.reloader.addPlugin(plugin);
+ };
+
+ LiveReload.prototype.analyze = function() {
+ var plugin, pluginData, pluginsData, _i, _len, _ref;
+ if (!this.initialized) {
+ return;
+ }
+ if (!(this.connector.protocol >= 7)) {
+ return;
+ }
+ pluginsData = {};
+ _ref = this.plugins;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ plugin = _ref[_i];
+ pluginsData[plugin.constructor.identifier] = pluginData = (typeof plugin.analyze === "function" ? plugin.analyze() : void 0) || {};
+ pluginData.version = plugin.constructor.version;
+ }
+ this.connector.sendCommand({
+ command: 'info',
+ plugins: pluginsData,
+ url: this.window.location.href
+ });
+ };
+
+ return LiveReload;
+
+ })();
+
+}).call(this);
+
+},{"./connector":1,"./options":5,"./reloader":7,"./timer":9}],5:[function(require,module,exports){
+(function() {
+ var Options;
+
+ exports.Options = Options = (function() {
+ function Options() {
+ this.https = false;
+ this.host = null;
+ this.port = 35729;
+ this.snipver = null;
+ this.ext = null;
+ this.extver = null;
+ this.mindelay = 1000;
+ this.maxdelay = 60000;
+ this.handshake_timeout = 5000;
+ }
+
+ Options.prototype.set = function(name, value) {
+ if (typeof value === 'undefined') {
+ return;
+ }
+ if (!isNaN(+value)) {
+ value = +value;
+ }
+ return this[name] = value;
+ };
+
+ return Options;
+
+ })();
+
+ Options.extract = function(document) {
+ var element, keyAndValue, m, mm, options, pair, src, _i, _j, _len, _len1, _ref, _ref1;
+ _ref = document.getElementsByTagName('script');
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ element = _ref[_i];
+ if ((src = element.src) && (m = src.match(/^[^:]+:\/\/(.*)\/z?livereload\.js(?:\?(.*))?$/))) {
+ options = new Options();
+ options.https = src.indexOf("https") === 0;
+ if (mm = m[1].match(/^([^\/:]+)(?::(\d+))?$/)) {
+ options.host = mm[1];
+ if (mm[2]) {
+ options.port = parseInt(mm[2], 10);
+ }
+ }
+ if (m[2]) {
+ _ref1 = m[2].split('&');
+ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
+ pair = _ref1[_j];
+ if ((keyAndValue = pair.split('=')).length > 1) {
+ options.set(keyAndValue[0].replace(/-/g, '_'), keyAndValue.slice(1).join('='));
+ }
+ }
+ }
+ return options;
+ }
+ }
+ return null;
+ };
+
+}).call(this);
+
+},{}],6:[function(require,module,exports){
+(function() {
+ var PROTOCOL_6, PROTOCOL_7, Parser, ProtocolError,
+ __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+ exports.PROTOCOL_6 = PROTOCOL_6 = 'http://livereload.com/protocols/official-6';
+
+ exports.PROTOCOL_7 = PROTOCOL_7 = 'http://livereload.com/protocols/official-7';
+
+ exports.ProtocolError = ProtocolError = (function() {
+ function ProtocolError(reason, data) {
+ this.message = "LiveReload protocol error (" + reason + ") after receiving data: \"" + data + "\".";
+ }
+
+ return ProtocolError;
+
+ })();
+
+ exports.Parser = Parser = (function() {
+ function Parser(handlers) {
+ this.handlers = handlers;
+ this.reset();
+ }
+
+ Parser.prototype.reset = function() {
+ return this.protocol = null;
+ };
+
+ Parser.prototype.process = function(data) {
+ var command, e, message, options, _ref;
+ try {
+ if (this.protocol == null) {
+ if (data.match(/^!!ver:([\d.]+)$/)) {
+ this.protocol = 6;
+ } else if (message = this._parseMessage(data, ['hello'])) {
+ if (!message.protocols.length) {
+ throw new ProtocolError("no protocols specified in handshake message");
+ } else if (__indexOf.call(message.protocols, PROTOCOL_7) >= 0) {
+ this.protocol = 7;
+ } else if (__indexOf.call(message.protocols, PROTOCOL_6) >= 0) {
+ this.protocol = 6;
+ } else {
+ throw new ProtocolError("no supported protocols found");
+ }
+ }
+ return this.handlers.connected(this.protocol);
+ } else if (this.protocol === 6) {
+ message = JSON.parse(data);
+ if (!message.length) {
+ throw new ProtocolError("protocol 6 messages must be arrays");
+ }
+ command = message[0], options = message[1];
+ if (command !== 'refresh') {
+ throw new ProtocolError("unknown protocol 6 command");
+ }
+ return this.handlers.message({
+ command: 'reload',
+ path: options.path,
+ liveCSS: (_ref = options.apply_css_live) != null ? _ref : true
+ });
+ } else {
+ message = this._parseMessage(data, ['reload', 'alert']);
+ return this.handlers.message(message);
+ }
+ } catch (_error) {
+ e = _error;
+ if (e instanceof ProtocolError) {
+ return this.handlers.error(e);
+ } else {
+ throw e;
+ }
+ }
+ };
+
+ Parser.prototype._parseMessage = function(data, validCommands) {
+ var e, message, _ref;
+ try {
+ message = JSON.parse(data);
+ } catch (_error) {
+ e = _error;
+ throw new ProtocolError('unparsable JSON', data);
+ }
+ if (!message.command) {
+ throw new ProtocolError('missing "command" key', data);
+ }
+ if (_ref = message.command, __indexOf.call(validCommands, _ref) < 0) {
+ throw new ProtocolError("invalid command '" + message.command + "', only valid commands are: " + (validCommands.join(', ')) + ")", data);
+ }
+ return message;
+ };
+
+ return Parser;
+
+ })();
+
+}).call(this);
+
+},{}],7:[function(require,module,exports){
+(function() {
+ var IMAGE_STYLES, Reloader, numberOfMatchingSegments, pathFromUrl, pathsMatch, pickBestMatch, splitUrl;
+
+ splitUrl = function(url) {
+ var hash, index, params;
+ if ((index = url.indexOf('#')) >= 0) {
+ hash = url.slice(index);
+ url = url.slice(0, index);
+ } else {
+ hash = '';
+ }
+ if ((index = url.indexOf('?')) >= 0) {
+ params = url.slice(index);
+ url = url.slice(0, index);
+ } else {
+ params = '';
+ }
+ return {
+ url: url,
+ params: params,
+ hash: hash
+ };
+ };
+
+ pathFromUrl = function(url) {
+ var path;
+ url = splitUrl(url).url;
+ if (url.indexOf('file://') === 0) {
+ path = url.replace(/^file:\/\/(localhost)?/, '');
+ } else {
+ path = url.replace(/^([^:]+:)?\/\/([^:\/]+)(:\d*)?\//, '/');
+ }
+ return decodeURIComponent(path);
+ };
+
+ pickBestMatch = function(path, objects, pathFunc) {
+ var bestMatch, object, score, _i, _len;
+ bestMatch = {
+ score: 0
+ };
+ for (_i = 0, _len = objects.length; _i < _len; _i++) {
+ object = objects[_i];
+ score = numberOfMatchingSegments(path, pathFunc(object));
+ if (score > bestMatch.score) {
+ bestMatch = {
+ object: object,
+ score: score
+ };
+ }
+ }
+ if (bestMatch.score > 0) {
+ return bestMatch;
+ } else {
+ return null;
+ }
+ };
+
+ numberOfMatchingSegments = function(path1, path2) {
+ var comps1, comps2, eqCount, len;
+ path1 = path1.replace(/^\/+/, '').toLowerCase();
+ path2 = path2.replace(/^\/+/, '').toLowerCase();
+ if (path1 === path2) {
+ return 10000;
+ }
+ comps1 = path1.split('/').reverse();
+ comps2 = path2.split('/').reverse();
+ len = Math.min(comps1.length, comps2.length);
+ eqCount = 0;
+ while (eqCount < len && comps1[eqCount] === comps2[eqCount]) {
+ ++eqCount;
+ }
+ return eqCount;
+ };
+
+ pathsMatch = function(path1, path2) {
+ return numberOfMatchingSegments(path1, path2) > 0;
+ };
+
+ IMAGE_STYLES = [
+ {
+ selector: 'background',
+ styleNames: ['backgroundImage']
+ }, {
+ selector: 'border',
+ styleNames: ['borderImage', 'webkitBorderImage', 'MozBorderImage']
+ }
+ ];
+
+ exports.Reloader = Reloader = (function() {
+ function Reloader(window, console, Timer) {
+ this.window = window;
+ this.console = console;
+ this.Timer = Timer;
+ this.document = this.window.document;
+ this.importCacheWaitPeriod = 200;
+ this.plugins = [];
+ }
+
+ Reloader.prototype.addPlugin = function(plugin) {
+ return this.plugins.push(plugin);
+ };
+
+ Reloader.prototype.analyze = function(callback) {
+ return results;
+ };
+
+ Reloader.prototype.reload = function(path, options) {
+ var plugin, _base, _i, _len, _ref;
+ this.options = options;
+ if ((_base = this.options).stylesheetReloadTimeout == null) {
+ _base.stylesheetReloadTimeout = 15000;
+ }
+ _ref = this.plugins;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ plugin = _ref[_i];
+ if (plugin.reload && plugin.reload(path, options)) {
+ return;
+ }
+ }
+ if (options.liveCSS) {
+ if (path.match(/\.css$/i)) {
+ if (this.reloadStylesheet(path)) {
+ return;
+ }
+ }
+ }
+ if (options.liveImg) {
+ if (path.match(/\.(jpe?g|png|gif)$/i)) {
+ this.reloadImages(path);
+ return;
+ }
+ }
+ return this.reloadPage();
+ };
+
+ Reloader.prototype.reloadPage = function() {
+ return this.window.document.location.reload();
+ };
+
+ Reloader.prototype.reloadImages = function(path) {
+ var expando, img, selector, styleNames, styleSheet, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _results;
+ expando = this.generateUniqueString();
+ _ref = this.document.images;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ img = _ref[_i];
+ if (pathsMatch(path, pathFromUrl(img.src))) {
+ img.src = this.generateCacheBustUrl(img.src, expando);
+ }
+ }
+ if (this.document.querySelectorAll) {
+ for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) {
+ _ref1 = IMAGE_STYLES[_j], selector = _ref1.selector, styleNames = _ref1.styleNames;
+ _ref2 = this.document.querySelectorAll("[style*=" + selector + "]");
+ for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
+ img = _ref2[_k];
+ this.reloadStyleImages(img.style, styleNames, path, expando);
+ }
+ }
+ }
+ if (this.document.styleSheets) {
+ _ref3 = this.document.styleSheets;
+ _results = [];
+ for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
+ styleSheet = _ref3[_l];
+ _results.push(this.reloadStylesheetImages(styleSheet, path, expando));
+ }
+ return _results;
+ }
+ };
+
+ Reloader.prototype.reloadStylesheetImages = function(styleSheet, path, expando) {
+ var e, rule, rules, styleNames, _i, _j, _len, _len1;
+ try {
+ rules = styleSheet != null ? styleSheet.cssRules : void 0;
+ } catch (_error) {
+ e = _error;
+ }
+ if (!rules) {
+ return;
+ }
+ for (_i = 0, _len = rules.length; _i < _len; _i++) {
+ rule = rules[_i];
+ switch (rule.type) {
+ case CSSRule.IMPORT_RULE:
+ this.reloadStylesheetImages(rule.styleSheet, path, expando);
+ break;
+ case CSSRule.STYLE_RULE:
+ for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) {
+ styleNames = IMAGE_STYLES[_j].styleNames;
+ this.reloadStyleImages(rule.style, styleNames, path, expando);
+ }
+ break;
+ case CSSRule.MEDIA_RULE:
+ this.reloadStylesheetImages(rule, path, expando);
+ }
+ }
+ };
+
+ Reloader.prototype.reloadStyleImages = function(style, styleNames, path, expando) {
+ var newValue, styleName, value, _i, _len;
+ for (_i = 0, _len = styleNames.length; _i < _len; _i++) {
+ styleName = styleNames[_i];
+ value = style[styleName];
+ if (typeof value === 'string') {
+ newValue = value.replace(/\burl\s*\(([^)]*)\)/, (function(_this) {
+ return function(match, src) {
+ if (pathsMatch(path, pathFromUrl(src))) {
+ return "url(" + (_this.generateCacheBustUrl(src, expando)) + ")";
+ } else {
+ return match;
+ }
+ };
+ })(this));
+ if (newValue !== value) {
+ style[styleName] = newValue;
+ }
+ }
+ }
+ };
+
+ Reloader.prototype.reloadStylesheet = function(path) {
+ var imported, link, links, match, style, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1;
+ links = (function() {
+ var _i, _len, _ref, _results;
+ _ref = this.document.getElementsByTagName('link');
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ link = _ref[_i];
+ if (link.rel.match(/^stylesheet$/i) && !link.__LiveReload_pendingRemoval) {
+ _results.push(link);
+ }
+ }
+ return _results;
+ }).call(this);
+ imported = [];
+ _ref = this.document.getElementsByTagName('style');
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ style = _ref[_i];
+ if (style.sheet) {
+ this.collectImportedStylesheets(style, style.sheet, imported);
+ }
+ }
+ for (_j = 0, _len1 = links.length; _j < _len1; _j++) {
+ link = links[_j];
+ this.collectImportedStylesheets(link, link.sheet, imported);
+ }
+ if (this.window.StyleFix && this.document.querySelectorAll) {
+ _ref1 = this.document.querySelectorAll('style[data-href]');
+ for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) {
+ style = _ref1[_k];
+ links.push(style);
+ }
+ }
+ this.console.log("LiveReload found " + links.length + " LINKed stylesheets, " + imported.length + " @imported stylesheets");
+ match = pickBestMatch(path, links.concat(imported), (function(_this) {
+ return function(l) {
+ return pathFromUrl(_this.linkHref(l));
+ };
+ })(this));
+ if (match) {
+ if (match.object.rule) {
+ this.console.log("LiveReload is reloading imported stylesheet: " + match.object.href);
+ this.reattachImportedRule(match.object);
+ } else {
+ this.console.log("LiveReload is reloading stylesheet: " + (this.linkHref(match.object)));
+ this.reattachStylesheetLink(match.object);
+ }
+ } else {
+ this.console.log("LiveReload will reload all stylesheets because path '" + path + "' did not match any specific one");
+ for (_l = 0, _len3 = links.length; _l < _len3; _l++) {
+ link = links[_l];
+ this.reattachStylesheetLink(link);
+ }
+ }
+ return true;
+ };
+
+ Reloader.prototype.collectImportedStylesheets = function(link, styleSheet, result) {
+ var e, index, rule, rules, _i, _len;
+ try {
+ rules = styleSheet != null ? styleSheet.cssRules : void 0;
+ } catch (_error) {
+ e = _error;
+ }
+ if (rules && rules.length) {
+ for (index = _i = 0, _len = rules.length; _i < _len; index = ++_i) {
+ rule = rules[index];
+ switch (rule.type) {
+ case CSSRule.CHARSET_RULE:
+ continue;
+ case CSSRule.IMPORT_RULE:
+ result.push({
+ link: link,
+ rule: rule,
+ index: index,
+ href: rule.href
+ });
+ this.collectImportedStylesheets(link, rule.styleSheet, result);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ };
+
+ Reloader.prototype.waitUntilCssLoads = function(clone, func) {
+ var callbackExecuted, executeCallback, poll;
+ callbackExecuted = false;
+ executeCallback = (function(_this) {
+ return function() {
+ if (callbackExecuted) {
+ return;
+ }
+ callbackExecuted = true;
+ return func();
+ };
+ })(this);
+ clone.onload = (function(_this) {
+ return function() {
+ _this.console.log("LiveReload: the new stylesheet has finished loading");
+ _this.knownToSupportCssOnLoad = true;
+ return executeCallback();
+ };
+ })(this);
+ if (!this.knownToSupportCssOnLoad) {
+ (poll = (function(_this) {
+ return function() {
+ if (clone.sheet) {
+ _this.console.log("LiveReload is polling until the new CSS finishes loading...");
+ return executeCallback();
+ } else {
+ return _this.Timer.start(50, poll);
+ }
+ };
+ })(this))();
+ }
+ return this.Timer.start(this.options.stylesheetReloadTimeout, executeCallback);
+ };
+
+ Reloader.prototype.linkHref = function(link) {
+ return link.href || link.getAttribute('data-href');
+ };
+
+ Reloader.prototype.reattachStylesheetLink = function(link) {
+ var clone, parent;
+ if (link.__LiveReload_pendingRemoval) {
+ return;
+ }
+ link.__LiveReload_pendingRemoval = true;
+ if (link.tagName === 'STYLE') {
+ clone = this.document.createElement('link');
+ clone.rel = 'stylesheet';
+ clone.media = link.media;
+ clone.disabled = link.disabled;
+ } else {
+ clone = link.cloneNode(false);
+ }
+ clone.href = this.generateCacheBustUrl(this.linkHref(link));
+ parent = link.parentNode;
+ if (parent.lastChild === link) {
+ parent.appendChild(clone);
+ } else {
+ parent.insertBefore(clone, link.nextSibling);
+ }
+ return this.waitUntilCssLoads(clone, (function(_this) {
+ return function() {
+ var additionalWaitingTime;
+ if (/AppleWebKit/.test(navigator.userAgent)) {
+ additionalWaitingTime = 5;
+ } else {
+ additionalWaitingTime = 200;
+ }
+ return _this.Timer.start(additionalWaitingTime, function() {
+ var _ref;
+ if (!link.parentNode) {
+ return;
+ }
+ link.parentNode.removeChild(link);
+ clone.onreadystatechange = null;
+ return (_ref = _this.window.StyleFix) != null ? _ref.link(clone) : void 0;
+ });
+ };
+ })(this));
+ };
+
+ Reloader.prototype.reattachImportedRule = function(_arg) {
+ var href, index, link, media, newRule, parent, rule, tempLink;
+ rule = _arg.rule, index = _arg.index, link = _arg.link;
+ parent = rule.parentStyleSheet;
+ href = this.generateCacheBustUrl(rule.href);
+ media = rule.media.length ? [].join.call(rule.media, ', ') : '';
+ newRule = "@import url(\"" + href + "\") " + media + ";";
+ rule.__LiveReload_newHref = href;
+ tempLink = this.document.createElement("link");
+ tempLink.rel = 'stylesheet';
+ tempLink.href = href;
+ tempLink.__LiveReload_pendingRemoval = true;
+ if (link.parentNode) {
+ link.parentNode.insertBefore(tempLink, link);
+ }
+ return this.Timer.start(this.importCacheWaitPeriod, (function(_this) {
+ return function() {
+ if (tempLink.parentNode) {
+ tempLink.parentNode.removeChild(tempLink);
+ }
+ if (rule.__LiveReload_newHref !== href) {
+ return;
+ }
+ parent.insertRule(newRule, index);
+ parent.deleteRule(index + 1);
+ rule = parent.cssRules[index];
+ rule.__LiveReload_newHref = href;
+ return _this.Timer.start(_this.importCacheWaitPeriod, function() {
+ if (rule.__LiveReload_newHref !== href) {
+ return;
+ }
+ parent.insertRule(newRule, index);
+ return parent.deleteRule(index + 1);
+ });
+ };
+ })(this));
+ };
+
+ Reloader.prototype.generateUniqueString = function() {
+ return 'livereload=' + Date.now();
+ };
+
+ Reloader.prototype.generateCacheBustUrl = function(url, expando) {
+ var hash, oldParams, originalUrl, params, _ref;
+ if (expando == null) {
+ expando = this.generateUniqueString();
+ }
+ _ref = splitUrl(url), url = _ref.url, hash = _ref.hash, oldParams = _ref.params;
+ if (this.options.overrideURL) {
+ if (url.indexOf(this.options.serverURL) < 0) {
+ originalUrl = url;
+ url = this.options.serverURL + this.options.overrideURL + "?url=" + encodeURIComponent(url);
+ this.console.log("LiveReload is overriding source URL " + originalUrl + " with " + url);
+ }
+ }
+ params = oldParams.replace(/(\?|&)livereload=(\d+)/, function(match, sep) {
+ return "" + sep + expando;
+ });
+ if (params === oldParams) {
+ if (oldParams.length === 0) {
+ params = "?" + expando;
+ } else {
+ params = "" + oldParams + "&" + expando;
+ }
+ }
+ return url + params + hash;
+ };
+
+ return Reloader;
+
+ })();
+
+}).call(this);
+
+},{}],8:[function(require,module,exports){
+(function() {
+ var CustomEvents, LiveReload, k;
+
+ CustomEvents = require('./customevents');
+
+ LiveReload = window.LiveReload = new (require('./livereload').LiveReload)(window);
+
+ for (k in window) {
+ if (k.match(/^LiveReloadPlugin/)) {
+ LiveReload.addPlugin(window[k]);
+ }
+ }
+
+ LiveReload.addPlugin(require('./less'));
+
+ LiveReload.on('shutdown', function() {
+ return delete window.LiveReload;
+ });
+
+ LiveReload.on('connect', function() {
+ return CustomEvents.fire(document, 'LiveReloadConnect');
+ });
+
+ LiveReload.on('disconnect', function() {
+ return CustomEvents.fire(document, 'LiveReloadDisconnect');
+ });
+
+ CustomEvents.bind(document, 'LiveReloadShutDown', function() {
+ return LiveReload.shutDown();
+ });
+
+}).call(this);
+
+},{"./customevents":2,"./less":3,"./livereload":4}],9:[function(require,module,exports){
+(function() {
+ var Timer;
+
+ exports.Timer = Timer = (function() {
+ function Timer(func) {
+ this.func = func;
+ this.running = false;
+ this.id = null;
+ this._handler = (function(_this) {
+ return function() {
+ _this.running = false;
+ _this.id = null;
+ return _this.func();
+ };
+ })(this);
+ }
+
+ Timer.prototype.start = function(timeout) {
+ if (this.running) {
+ clearTimeout(this.id);
+ }
+ this.id = setTimeout(this._handler, timeout);
+ return this.running = true;
+ };
+
+ Timer.prototype.stop = function() {
+ if (this.running) {
+ clearTimeout(this.id);
+ this.running = false;
+ return this.id = null;
+ }
+ };
+
+ return Timer;
+
+ })();
+
+ Timer.start = function(timeout, func) {
+ return setTimeout(func, timeout);
+ };
+
+}).call(this);
+
+},{}]},{},[8]);
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/mime_types_charset.json b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/mime_types_charset.json
new file mode 100644
index 0000000..017469b
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/mime_types_charset.json
@@ -0,0 +1,71 @@
+{
+ "application/javascript": "UTF-8",
+ "application/json": "UTF-8",
+ "application/manifest+json": "UTF-8",
+ "application/vnd.syncml+xml": "UTF-8",
+ "application/vnd.syncml.dm+wbxml": "UTF-8",
+ "application/vnd.syncml.dm+xml": "UTF-8",
+ "application/vnd.syncml.dmddf+xml": "UTF-8",
+ "application/vnd.wap.wbxml": "UTF-8",
+ "text/cache-manifest": "UTF-8",
+ "text/calendar": "UTF-8",
+ "text/coffeescript": "UTF-8",
+ "text/css": "UTF-8",
+ "text/csv": "UTF-8",
+ "text/html": "UTF-8",
+ "text/jade": "UTF-8",
+ "text/jsx": "UTF-8",
+ "text/less": "UTF-8",
+ "text/markdown": "UTF-8",
+ "text/mathml": "UTF-8",
+ "text/mdx": "UTF-8",
+ "text/n3": "UTF-8",
+ "text/plain": "UTF-8",
+ "text/prs.lines.tag": "UTF-8",
+ "text/richtext": "UTF-8",
+ "text/sgml": "UTF-8",
+ "text/shex": "UTF-8",
+ "text/slim": "UTF-8",
+ "text/spdx": "UTF-8",
+ "text/stylus": "UTF-8",
+ "text/tab-separated-values": "UTF-8",
+ "text/troff": "UTF-8",
+ "text/turtle": "UTF-8",
+ "text/uri-list": "UTF-8",
+ "text/vcard": "UTF-8",
+ "text/vnd.curl": "UTF-8",
+ "text/vnd.curl.dcurl": "UTF-8",
+ "text/vnd.curl.mcurl": "UTF-8",
+ "text/vnd.curl.scurl": "UTF-8",
+ "text/vnd.familysearch.gedcom": "UTF-8",
+ "text/vnd.fly": "UTF-8",
+ "text/vnd.fmi.flexstor": "UTF-8",
+ "text/vnd.graphviz": "UTF-8",
+ "text/vnd.in3d.3dml": "UTF-8",
+ "text/vnd.in3d.spot": "UTF-8",
+ "text/vnd.sun.j2me.app-descriptor": "UTF-8",
+ "text/vnd.wap.wml": "UTF-8",
+ "text/vnd.wap.wmlscript": "UTF-8",
+ "text/vtt": "UTF-8",
+ "text/x-asm": "UTF-8",
+ "text/x-c": "UTF-8",
+ "text/x-component": "UTF-8",
+ "text/x-fortran": "UTF-8",
+ "text/x-handlebars-template": "UTF-8",
+ "text/x-java-source": "UTF-8",
+ "text/x-lua": "UTF-8",
+ "text/x-markdown": "UTF-8",
+ "text/x-nfo": "UTF-8",
+ "text/x-opml": "UTF-8",
+ "text/x-pascal": "UTF-8",
+ "text/x-processing": "UTF-8",
+ "text/x-sass": "UTF-8",
+ "text/x-scss": "UTF-8",
+ "text/x-setext": "UTF-8",
+ "text/x-sfv": "UTF-8",
+ "text/x-suse-ymp": "UTF-8",
+ "text/x-uuencode": "UTF-8",
+ "text/x-vcalendar": "UTF-8",
+ "text/x-vcard": "UTF-8",
+ "text/yaml": "UTF-8"
+}
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/servlet.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/servlet.rb
new file mode 100644
index 0000000..c8895e5
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/servlet.rb
@@ -0,0 +1,206 @@
+# frozen_string_literal: true
+
+require "webrick"
+
+module Jekyll
+ module Commands
+ class Serve
+ # This class is used to determine if the Servlet should modify a served file
+ # to insert the LiveReload script tags
+ class SkipAnalyzer
+ BAD_USER_AGENTS = [%r!MSIE!].freeze
+
+ def self.skip_processing?(request, response, options)
+ new(request, response, options).skip_processing?
+ end
+
+ def initialize(request, response, options)
+ @options = options
+ @request = request
+ @response = response
+ end
+
+ def skip_processing?
+ !html? || chunked? || inline? || bad_browser?
+ end
+
+ def chunked?
+ @response["Transfer-Encoding"] == "chunked"
+ end
+
+ def inline?
+ @response["Content-Disposition"].to_s.start_with?("inline")
+ end
+
+ def bad_browser?
+ BAD_USER_AGENTS.any? { |pattern| pattern.match?(@request["User-Agent"]) }
+ end
+
+ def html?
+ @response["Content-Type"].to_s.include?("text/html")
+ end
+ end
+
+ # This class inserts the LiveReload script tags into HTML as it is served
+ class BodyProcessor
+ HEAD_TAG_REGEX = %r!<head>|<head[^(er)][^<]*>!.freeze
+
+ attr_reader :content_length, :new_body, :livereload_added
+
+ def initialize(body, options)
+ @body = body
+ @options = options
+ @processed = false
+ end
+
+ def processed?
+ @processed
+ end
+
+ # rubocop:disable Metrics/MethodLength
+ def process!
+ @new_body = []
+ # @body will usually be a File object but Strings occur in rare cases
+ if @body.respond_to?(:each)
+ begin
+ @body.each { |line| @new_body << line.to_s }
+ ensure
+ @body.close
+ end
+ else
+ @new_body = @body.lines
+ end
+
+ @content_length = 0
+ @livereload_added = false
+
+ @new_body.each do |line|
+ if !@livereload_added && line["<head"]
+ line.gsub!(HEAD_TAG_REGEX) do |match|
+ %(#{match}#{template.result(binding)})
+ end
+
+ @livereload_added = true
+ end
+
+ @content_length += line.bytesize
+ @processed = true
+ end
+ @new_body = @new_body.join
+ end
+ # rubocop:enable Metrics/MethodLength
+
+ def template
+ # Unclear what "snipver" does. Doc at
+ # https://github.com/livereload/livereload-js states that the recommended
+ # setting is 1.
+
+ # Complicated JavaScript to ensure that livereload.js is loaded from the
+ # same origin as the page. Mostly useful for dealing with the browser's
+ # distinction between 'localhost' and 127.0.0.1
+ @template ||= ERB.new(<<~TEMPLATE)
+ <script>
+ document.write(
+ '<script src="' + location.protocol + '//' +
+ (location.host || 'localhost').split(':')[0] +
+ ':<%=@options["livereload_port"] %>/livereload.js?snipver=1<%= livereload_args %>"' +
+ '></' +
+ 'script>');
+ </script>
+ TEMPLATE
+ end
+
+ def livereload_args
+ # XHTML standard requires ampersands to be encoded as entities when in
+ # attributes. See http://stackoverflow.com/a/2190292
+ src = ""
+ if @options["livereload_min_delay"]
+ src += "&amp;mindelay=#{@options["livereload_min_delay"]}"
+ end
+ if @options["livereload_max_delay"]
+ src += "&amp;maxdelay=#{@options["livereload_max_delay"]}"
+ end
+ src += "&amp;port=#{@options["livereload_port"]}" if @options["livereload_port"]
+ src
+ end
+ end
+
+ class Servlet < WEBrick::HTTPServlet::FileHandler
+ DEFAULTS = {
+ "Cache-Control" => "private, max-age=0, proxy-revalidate, " \
+ "no-store, no-cache, must-revalidate",
+ }.freeze
+
+ def initialize(server, root, callbacks)
+ # So we can access them easily.
+ @jekyll_opts = server.config[:JekyllOptions]
+ @mime_types_charset = server.config[:MimeTypesCharset]
+ set_defaults
+ super
+ end
+
+ def search_index_file(req, res)
+ super ||
+ search_file(req, res, ".html") ||
+ search_file(req, res, ".xhtml")
+ end
+
+ # Add the ability to tap file.html the same way that Nginx does on our
+ # Docker images (or on GitHub Pages.) The difference is that we might end
+ # up with a different preference on which comes first.
+
+ def search_file(req, res, basename)
+ # /file.* > /file/index.html > /file.html
+ super ||
+ super(req, res, "#{basename}.html") ||
+ super(req, res, "#{basename}.xhtml")
+ end
+
+ # rubocop:disable Naming/MethodName
+ def do_GET(req, res)
+ rtn = super
+
+ if @jekyll_opts["livereload"]
+ return rtn if SkipAnalyzer.skip_processing?(req, res, @jekyll_opts)
+
+ processor = BodyProcessor.new(res.body, @jekyll_opts)
+ processor.process!
+ res.body = processor.new_body
+ res.content_length = processor.content_length.to_s
+
+ if processor.livereload_added
+ # Add a header to indicate that the page content has been modified
+ res["X-Rack-LiveReload"] = "1"
+ end
+ end
+
+ conditionally_inject_charset(res)
+ res.header.merge!(@headers)
+ rtn
+ end
+ # rubocop:enable Naming/MethodName
+
+ private
+
+ # Inject charset based on Jekyll config only if our mime-types database contains
+ # the charset metadata.
+ #
+ # Refer `script/vendor-mimes` in the repository for further details.
+ def conditionally_inject_charset(res)
+ typ = res.header["content-type"]
+ return unless @mime_types_charset.key?(typ)
+ return if %r!;\s*charset=!.match?(typ)
+
+ res.header["content-type"] = "#{typ}; charset=#{@jekyll_opts["encoding"]}"
+ end
+
+ def set_defaults
+ hash_ = @jekyll_opts.fetch("webrick", {}).fetch("headers", {})
+ DEFAULTS.each_with_object(@headers = hash_) do |(key, val), hash|
+ hash[key] = val unless hash.key?(key)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/websockets.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/websockets.rb
new file mode 100644
index 0000000..6aa522c
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/commands/serve/websockets.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require "http/parser"
+
+module Jekyll
+ module Commands
+ class Serve
+ # The LiveReload protocol requires the server to serve livereload.js over HTTP
+ # despite the fact that the protocol itself uses WebSockets. This custom connection
+ # class addresses the dual protocols that the server needs to understand.
+ class HttpAwareConnection < EventMachine::WebSocket::Connection
+ attr_reader :reload_body, :reload_size
+
+ def initialize(_opts)
+ # If EventMachine SSL support on Windows ever gets better, the code below will
+ # set up the reactor to handle SSL
+ #
+ # @ssl_enabled = opts["ssl_cert"] && opts["ssl_key"]
+ # if @ssl_enabled
+ # em_opts[:tls_options] = {
+ # :private_key_file => Jekyll.sanitized_path(opts["source"], opts["ssl_key"]),
+ # :cert_chain_file => Jekyll.sanitized_path(opts["source"], opts["ssl_cert"])
+ # }
+ # em_opts[:secure] = true
+ # end
+
+ # This is too noisy even for --verbose, but uncomment if you need it for
+ # a specific WebSockets issue. Adding ?LR-verbose=true onto the URL will
+ # enable logging on the client side.
+ # em_opts[:debug] = true
+
+ em_opts = {}
+ super(em_opts)
+
+ reload_file = File.join(Serve.singleton_class::LIVERELOAD_DIR, "livereload.js")
+
+ @reload_body = File.read(reload_file)
+ @reload_size = @reload_body.bytesize
+ end
+
+ # rubocop:disable Metrics/MethodLength
+ def dispatch(data)
+ parser = Http::Parser.new
+ parser << data
+
+ # WebSockets requests will have a Connection: Upgrade header
+ if parser.http_method != "GET" || parser.upgrade?
+ super
+ elsif parser.request_url.start_with?("/livereload.js")
+ headers = [
+ "HTTP/1.1 200 OK",
+ "Content-Type: application/javascript",
+ "Content-Length: #{reload_size}",
+ "",
+ "",
+ ].join("\r\n")
+ send_data(headers)
+
+ # stream_file_data would free us from keeping livereload.js in memory
+ # but JRuby blocks on that call and never returns
+ send_data(reload_body)
+ close_connection_after_writing
+ else
+ body = "This port only serves livereload.js over HTTP.\n"
+ headers = [
+ "HTTP/1.1 400 Bad Request",
+ "Content-Type: text/plain",
+ "Content-Length: #{body.bytesize}",
+ "",
+ "",
+ ].join("\r\n")
+ send_data(headers)
+ send_data(body)
+ close_connection_after_writing
+ end
+ end
+ # rubocop:enable Metrics/MethodLength
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/configuration.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/configuration.rb
new file mode 100644
index 0000000..9b2fbff
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/configuration.rb
@@ -0,0 +1,313 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Configuration < Hash
+ # Default options. Overridden by values in _config.yml.
+ # Strings rather than symbols are used for compatibility with YAML.
+ DEFAULTS = {
+ # Where things are
+ "source" => Dir.pwd,
+ "destination" => File.join(Dir.pwd, "_site"),
+ "collections_dir" => "",
+ "cache_dir" => ".jekyll-cache",
+ "plugins_dir" => "_plugins",
+ "layouts_dir" => "_layouts",
+ "data_dir" => "_data",
+ "includes_dir" => "_includes",
+ "collections" => {},
+
+ # Handling Reading
+ "safe" => false,
+ "include" => [".htaccess"],
+ "exclude" => [],
+ "keep_files" => [".git", ".svn"],
+ "encoding" => "utf-8",
+ "markdown_ext" => "markdown,mkdown,mkdn,mkd,md",
+ "strict_front_matter" => false,
+
+ # Filtering Content
+ "show_drafts" => nil,
+ "limit_posts" => 0,
+ "future" => false,
+ "unpublished" => false,
+
+ # Plugins
+ "whitelist" => [],
+ "plugins" => [],
+
+ # Conversion
+ "markdown" => "kramdown",
+ "highlighter" => "rouge",
+ "lsi" => false,
+ "excerpt_separator" => "\n\n",
+ "incremental" => false,
+
+ # Serving
+ "detach" => false, # default to not detaching the server
+ "port" => "4000",
+ "host" => "127.0.0.1",
+ "baseurl" => nil, # this mounts at /, i.e. no subdirectory
+ "show_dir_listing" => false,
+
+ # Output Configuration
+ "permalink" => "date",
+ "paginate_path" => "/page:num",
+ "timezone" => nil, # use the local timezone
+
+ "quiet" => false,
+ "verbose" => false,
+ "defaults" => [],
+
+ "liquid" => {
+ "error_mode" => "warn",
+ "strict_filters" => false,
+ "strict_variables" => false,
+ },
+
+ "kramdown" => {
+ "auto_ids" => true,
+ "toc_levels" => (1..6).to_a,
+ "entity_output" => "as_char",
+ "smart_quotes" => "lsquo,rsquo,ldquo,rdquo",
+ "input" => "GFM",
+ "hard_wrap" => false,
+ "guess_lang" => true,
+ "footnote_nr" => 1,
+ "show_warnings" => false,
+ },
+ }.each_with_object(Configuration.new) { |(k, v), hsh| hsh[k] = v.freeze }.freeze
+
+ class << self
+ # Static: Produce a Configuration ready for use in a Site.
+ # It takes the input, fills in the defaults where values do not exist.
+ #
+ # user_config - a Hash or Configuration of overrides.
+ #
+ # Returns a Configuration filled with defaults.
+ def from(user_config)
+ Utils.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys)
+ .add_default_collections.add_default_excludes
+ end
+ end
+
+ # Public: Turn all keys into string
+ #
+ # Return a copy of the hash where all its keys are strings
+ def stringify_keys
+ each_with_object({}) { |(k, v), hsh| hsh[k.to_s] = v }
+ end
+
+ def get_config_value_with_override(config_key, override)
+ override[config_key] || self[config_key] || DEFAULTS[config_key]
+ end
+
+ # Public: Directory of the Jekyll source folder
+ #
+ # override - the command-line options hash
+ #
+ # Returns the path to the Jekyll source directory
+ def source(override)
+ get_config_value_with_override("source", override)
+ end
+
+ def quiet(override = {})
+ get_config_value_with_override("quiet", override)
+ end
+ alias_method :quiet?, :quiet
+
+ def verbose(override = {})
+ get_config_value_with_override("verbose", override)
+ end
+ alias_method :verbose?, :verbose
+
+ def safe_load_file(filename)
+ case File.extname(filename)
+ when %r!\.toml!i
+ Jekyll::External.require_with_graceful_fail("tomlrb") unless defined?(Tomlrb)
+ Tomlrb.load_file(filename)
+ when %r!\.ya?ml!i
+ SafeYAML.load_file(filename) || {}
+ else
+ raise ArgumentError,
+ "No parser for '#{filename}' is available. Use a .y(a)ml or .toml file instead."
+ end
+ end
+
+ # Public: Generate list of configuration files from the override
+ #
+ # override - the command-line options hash
+ #
+ # Returns an Array of config files
+ def config_files(override)
+ # Adjust verbosity quickly
+ Jekyll.logger.adjust_verbosity(
+ :quiet => quiet?(override),
+ :verbose => verbose?(override)
+ )
+
+ # Get configuration from <source>/_config.yml or <source>/<config_file>
+ config_files = override["config"]
+ if config_files.to_s.empty?
+ default = %w(yml yaml toml).find(-> { "yml" }) do |ext|
+ File.exist?(Jekyll.sanitized_path(source(override), "_config.#{ext}"))
+ end
+ config_files = Jekyll.sanitized_path(source(override), "_config.#{default}")
+ @default_config_file = true
+ end
+ Array(config_files)
+ end
+
+ # Public: Read configuration and return merged Hash
+ #
+ # file - the path to the YAML file to be read in
+ #
+ # Returns this configuration, overridden by the values in the file
+ def read_config_file(file)
+ file = File.expand_path(file)
+ next_config = safe_load_file(file)
+
+ unless next_config.is_a?(Hash)
+ raise ArgumentError, "Configuration file: (INVALID) #{file}".yellow
+ end
+
+ Jekyll.logger.info "Configuration file:", file
+ next_config
+ rescue SystemCallError
+ if @default_config_file ||= nil
+ Jekyll.logger.warn "Configuration file:", "none"
+ {}
+ else
+ Jekyll.logger.error "Fatal:", "The configuration file '#{file}' could not be found."
+ raise LoadError, "The Configuration file '#{file}' could not be found."
+ end
+ end
+
+ # Public: Read in a list of configuration files and merge with this hash
+ #
+ # files - the list of configuration file paths
+ #
+ # Returns the full configuration, with the defaults overridden by the values in the
+ # configuration files
+ def read_config_files(files)
+ configuration = clone
+
+ begin
+ files.each do |config_file|
+ next if config_file.nil? || config_file.empty?
+
+ new_config = read_config_file(config_file)
+ configuration = Utils.deep_merge_hashes(configuration, new_config)
+ end
+ rescue ArgumentError => e
+ Jekyll.logger.warn "WARNING:", "Error reading configuration. Using defaults (and options)."
+ warn e
+ end
+
+ configuration.validate.add_default_collections
+ end
+
+ # Public: Split a CSV string into an array containing its values
+ #
+ # csv - the string of comma-separated values
+ #
+ # Returns an array of the values contained in the CSV
+ def csv_to_array(csv)
+ csv.split(",").map(&:strip)
+ end
+
+ # Public: Ensure the proper options are set in the configuration
+ #
+ # Returns the configuration Hash
+ def validate
+ config = clone
+
+ check_plugins(config)
+ check_include_exclude(config)
+
+ config
+ end
+
+ def add_default_collections
+ config = clone
+
+ # It defaults to `{}`, so this is only if someone sets it to null manually.
+ return config if config["collections"].nil?
+
+ # Ensure we have a hash.
+ if config["collections"].is_a?(Array)
+ config["collections"] = config["collections"].each_with_object({}) do |collection, hash|
+ hash[collection] = {}
+ end
+ end
+
+ config["collections"] = Utils.deep_merge_hashes(
+ { "posts" => {} }, config["collections"]
+ ).tap do |collections|
+ collections["posts"]["output"] = true
+ if config["permalink"]
+ collections["posts"]["permalink"] ||= style_to_permalink(config["permalink"])
+ end
+ end
+
+ config
+ end
+
+ DEFAULT_EXCLUDES = %w(
+ .sass-cache .jekyll-cache
+ gemfiles Gemfile Gemfile.lock
+ node_modules
+ vendor/bundle/ vendor/cache/ vendor/gems/ vendor/ruby/
+ ).freeze
+
+ def add_default_excludes
+ config = clone
+ return config if config["exclude"].nil?
+
+ config["exclude"].concat(DEFAULT_EXCLUDES).uniq!
+ config
+ end
+
+ private
+
+ STYLE_TO_PERMALINK = {
+ :none => "/:categories/:title:output_ext",
+ :date => "/:categories/:year/:month/:day/:title:output_ext",
+ :ordinal => "/:categories/:year/:y_day/:title:output_ext",
+ :pretty => "/:categories/:year/:month/:day/:title/",
+ :weekdate => "/:categories/:year/W:week/:short_day/:title:output_ext",
+ }.freeze
+
+ private_constant :STYLE_TO_PERMALINK
+
+ def style_to_permalink(permalink_style)
+ STYLE_TO_PERMALINK[permalink_style.to_sym] || permalink_style.to_s
+ end
+
+ def check_include_exclude(config)
+ %w(include exclude).each do |option|
+ next unless config.key?(option)
+ next if config[option].is_a?(Array)
+
+ raise Jekyll::Errors::InvalidConfigurationError,
+ "'#{option}' should be set as an array, but was: #{config[option].inspect}."
+ end
+ end
+
+ # Private: Checks if the `plugins` config is a String
+ #
+ # config - the config hash
+ #
+ # Raises a Jekyll::Errors::InvalidConfigurationError if the config `plugins`
+ # is not an Array.
+ def check_plugins(config)
+ return unless config.key?("plugins")
+ return if config["plugins"].is_a?(Array)
+
+ Jekyll.logger.error "'plugins' should be set as an array of gem-names, but was: " \
+ "#{config["plugins"].inspect}. Use 'plugins_dir' instead to set " \
+ "the directory for your non-gemified Ruby plugins."
+ raise Jekyll::Errors::InvalidConfigurationError,
+ "'plugins' should be set as an array, but was: #{config["plugins"].inspect}."
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converter.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converter.rb
new file mode 100644
index 0000000..3cb74de
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converter.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Converter < Plugin
+ # Public: Get or set the highlighter prefix. When an argument is specified,
+ # the prefix will be set. If no argument is specified, the current prefix
+ # will be returned.
+ #
+ # highlighter_prefix - The String prefix (default: nil).
+ #
+ # Returns the String prefix.
+ def self.highlighter_prefix(highlighter_prefix = nil)
+ unless defined?(@highlighter_prefix) && highlighter_prefix.nil?
+ @highlighter_prefix = highlighter_prefix
+ end
+ @highlighter_prefix
+ end
+
+ # Public: Get or set the highlighter suffix. When an argument is specified,
+ # the suffix will be set. If no argument is specified, the current suffix
+ # will be returned.
+ #
+ # highlighter_suffix - The String suffix (default: nil).
+ #
+ # Returns the String suffix.
+ def self.highlighter_suffix(highlighter_suffix = nil)
+ unless defined?(@highlighter_suffix) && highlighter_suffix.nil?
+ @highlighter_suffix = highlighter_suffix
+ end
+ @highlighter_suffix
+ end
+
+ # Initialize the converter.
+ #
+ # Returns an initialized Converter.
+ def initialize(config = {})
+ @config = config
+ end
+
+ # Get the highlighter prefix.
+ #
+ # Returns the String prefix.
+ def highlighter_prefix
+ self.class.highlighter_prefix
+ end
+
+ # Get the highlighter suffix.
+ #
+ # Returns the String suffix.
+ def highlighter_suffix
+ self.class.highlighter_suffix
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/identity.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/identity.rb
new file mode 100644
index 0000000..7579b33
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/identity.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Converters
+ # Identity converter. Returns same content as given.
+ # For more info on converters see https://jekyllrb.com/docs/plugins/converters/
+ class Identity < Converter
+ safe true
+
+ priority :lowest
+
+ # Public: Does the given extension match this converter's list of acceptable extensions?
+ # Takes one argument: the file's extension (including the dot).
+ #
+ # _ext - The String extension to check (not relevant here)
+ #
+ # Returns true since it always matches.
+ def matches(_ext)
+ true
+ end
+
+ # Public: The extension to be given to the output file (including the dot).
+ #
+ # ext - The String extension or original file.
+ #
+ # Returns The String output file extension.
+ def output_ext(ext)
+ ext
+ end
+
+ # Logic to do the content conversion.
+ #
+ # content - String content of file (without front matter).
+ #
+ # Returns a String of the converted content.
+ def convert(content)
+ content
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/markdown.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/markdown.rb
new file mode 100644
index 0000000..da1f1ce
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/markdown.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Converters
+ # Markdown converter.
+ # For more info on converters see https://jekyllrb.com/docs/plugins/converters/
+ class Markdown < Converter
+ highlighter_prefix "\n"
+ highlighter_suffix "\n"
+ safe true
+
+ def setup
+ return if @setup ||= false
+
+ unless (@parser = get_processor)
+ if @config["safe"]
+ Jekyll.logger.warn "Build Warning:", "Custom processors are not loaded in safe mode"
+ end
+
+ Jekyll.logger.error "Markdown processor:",
+ "#{@config["markdown"].inspect} is not a valid Markdown processor."
+ Jekyll.logger.error "", "Available processors are: #{valid_processors.join(", ")}"
+ Jekyll.logger.error ""
+ raise Errors::FatalException, "Invalid Markdown processor given: #{@config["markdown"]}"
+ end
+
+ @cache = Jekyll::Cache.new("Jekyll::Converters::Markdown")
+ @setup = true
+ end
+
+ # RuboCop does not allow reader methods to have names starting with `get_`
+ # To ensure compatibility, this check has been disabled on this method
+ #
+ # rubocop:disable Naming/AccessorMethodName
+ def get_processor
+ case @config["markdown"].downcase
+ when "kramdown" then KramdownParser.new(@config)
+ else
+ custom_processor
+ end
+ end
+ # rubocop:enable Naming/AccessorMethodName
+
+ # Public: Provides you with a list of processors comprised of the ones we support internally
+ # and the ones that you have provided to us (if they're whitelisted for use in safe mode).
+ #
+ # Returns an array of symbols.
+ def valid_processors
+ [:kramdown] + third_party_processors
+ end
+
+ # Public: A list of processors that you provide via plugins.
+ #
+ # Returns an array of symbols
+ def third_party_processors
+ self.class.constants - [:KramdownParser, :PRIORITIES]
+ end
+
+ # Does the given extension match this converter's list of acceptable extensions?
+ # Takes one argument: the file's extension (including the dot).
+ #
+ # ext - The String extension to check.
+ #
+ # Returns true if it matches, false otherwise.
+ def matches(ext)
+ extname_list.include?(ext.downcase)
+ end
+
+ # Public: The extension to be given to the output file (including the dot).
+ #
+ # ext - The String extension or original file.
+ #
+ # Returns The String output file extension.
+ def output_ext(_ext)
+ ".html"
+ end
+
+ # Logic to do the content conversion.
+ #
+ # content - String content of file (without front matter).
+ #
+ # Returns a String of the converted content.
+ def convert(content)
+ setup
+ @cache.getset(content) do
+ @parser.convert(content)
+ end
+ end
+
+ def extname_list
+ @extname_list ||= @config["markdown_ext"].split(",").map! { |e| ".#{e.downcase}" }
+ end
+
+ private
+
+ def custom_processor
+ converter_name = @config["markdown"]
+ self.class.const_get(converter_name).new(@config) if custom_class_allowed?(converter_name)
+ end
+
+ # Private: Determine whether a class name is an allowed custom
+ # markdown class name.
+ #
+ # parser_name - the name of the parser class
+ #
+ # Returns true if the parser name contains only alphanumeric characters and is defined
+ # within Jekyll::Converters::Markdown
+ def custom_class_allowed?(parser_name)
+ parser_name !~ %r![^A-Za-z0-9_]! && self.class.constants.include?(parser_name.to_sym)
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/markdown/kramdown_parser.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/markdown/kramdown_parser.rb
new file mode 100644
index 0000000..1e6a1de
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/markdown/kramdown_parser.rb
@@ -0,0 +1,197 @@
+# frozen_string_literal: true
+
+module Kramdown
+ # A Kramdown::Document subclass meant to optimize memory usage from initializing
+ # a kramdown document for parsing.
+ #
+ # The optimization is by using the same options Hash (and its derivatives) for
+ # converting all Markdown documents in a Jekyll site.
+ class JekyllDocument < Document
+ class << self
+ attr_reader :options, :parser
+
+ # The implementation is basically the core logic in +Kramdown::Document#initialize+
+ #
+ # rubocop:disable Naming/MemoizedInstanceVariableName
+ def setup(options)
+ @cache ||= {}
+
+ # reset variables on a subsequent set up with a different options Hash
+ unless @cache[:id] == options.hash
+ @options = @parser = nil
+ @cache[:id] = options.hash
+ end
+
+ @options ||= Options.merge(options).freeze
+ @parser ||= begin
+ parser_name = (@options[:input] || "kramdown").to_s
+ parser_name = parser_name[0..0].upcase + parser_name[1..-1]
+ try_require("parser", parser_name)
+
+ if Parser.const_defined?(parser_name)
+ Parser.const_get(parser_name)
+ else
+ raise Kramdown::Error, "kramdown has no parser to handle the specified " \
+ "input format: #{@options[:input]}"
+ end
+ end
+ end
+ # rubocop:enable Naming/MemoizedInstanceVariableName
+
+ private
+
+ def try_require(type, name)
+ require "kramdown/#{type}/#{Utils.snake_case(name)}"
+ rescue LoadError
+ false
+ end
+ end
+
+ def initialize(source, options = {})
+ JekyllDocument.setup(options)
+
+ @options = JekyllDocument.options
+ @root, @warnings = JekyllDocument.parser.parse(source, @options)
+ end
+
+ # Use Kramdown::Converter::Html class to convert this document into HTML.
+ #
+ # The implementation is basically an optimized version of core logic in
+ # +Kramdown::Document#method_missing+ from kramdown-2.1.0.
+ def to_html
+ output, warnings = Kramdown::Converter::Html.convert(@root, @options)
+ @warnings.concat(warnings)
+ output
+ end
+ end
+end
+
+#
+
+module Jekyll
+ module Converters
+ class Markdown
+ class KramdownParser
+ CODERAY_DEFAULTS = {
+ "css" => "style",
+ "bold_every" => 10,
+ "line_numbers" => "inline",
+ "line_number_start" => 1,
+ "tab_width" => 4,
+ "wrap" => "div",
+ }.freeze
+
+ def initialize(config)
+ @main_fallback_highlighter = config["highlighter"] || "rouge"
+ @config = config["kramdown"] || {}
+ @highlighter = nil
+ setup
+ load_dependencies
+ end
+
+ # Setup and normalize the configuration:
+ # * Create Kramdown if it doesn't exist.
+ # * Set syntax_highlighter, detecting enable_coderay and merging
+ # highlighter if none.
+ # * Merge kramdown[coderay] into syntax_highlighter_opts stripping coderay_.
+ # * Make sure `syntax_highlighter_opts` exists.
+
+ def setup
+ @config["syntax_highlighter"] ||= highlighter
+ @config["syntax_highlighter_opts"] ||= {}
+ @config["syntax_highlighter_opts"]["default_lang"] ||= "plaintext"
+ @config["syntax_highlighter_opts"]["guess_lang"] = @config["guess_lang"]
+ @config["coderay"] ||= {} # XXX: Legacy.
+ modernize_coderay_config
+ end
+
+ def convert(content)
+ document = Kramdown::JekyllDocument.new(content, @config)
+ html_output = document.to_html
+ if @config["show_warnings"]
+ document.warnings.each do |warning|
+ Jekyll.logger.warn "Kramdown warning:", warning
+ end
+ end
+ html_output
+ end
+
+ private
+
+ def load_dependencies
+ require "kramdown-parser-gfm" if @config["input"] == "GFM"
+
+ if highlighter == "coderay"
+ Jekyll::External.require_with_graceful_fail("kramdown-syntax-coderay")
+ end
+
+ # `mathjax` engine is bundled within kramdown-2.x and will be handled by
+ # kramdown itself.
+ if (math_engine = @config["math_engine"]) && math_engine != "mathjax"
+ Jekyll::External.require_with_graceful_fail("kramdown-math-#{math_engine}")
+ end
+ end
+
+ # config[kramdown][syntax_highlighter] >
+ # config[kramdown][enable_coderay] >
+ # config[highlighter]
+ # Where `enable_coderay` is now deprecated because Kramdown
+ # supports Rouge now too.
+ def highlighter
+ return @highlighter if @highlighter
+
+ if @config["syntax_highlighter"]
+ return @highlighter = @config[
+ "syntax_highlighter"
+ ]
+ end
+
+ @highlighter = if @config.key?("enable_coderay") && @config["enable_coderay"]
+ Jekyll::Deprecator.deprecation_message(
+ "You are using 'enable_coderay', " \
+ "use syntax_highlighter: coderay in your configuration file."
+ )
+
+ "coderay"
+ else
+ @main_fallback_highlighter
+ end
+ end
+
+ def strip_coderay_prefix(hash)
+ hash.each_with_object({}) do |(key, val), hsh|
+ cleaned_key = key.to_s.delete_prefix("coderay_")
+
+ if key != cleaned_key
+ Jekyll::Deprecator.deprecation_message(
+ "You are using '#{key}'. Normalizing to #{cleaned_key}."
+ )
+ end
+
+ hsh[cleaned_key] = val
+ end
+ end
+
+ # If our highlighter is CodeRay we go in to merge the CodeRay defaults
+ # with your "coderay" key if it's there, deprecating it in the
+ # process of you using it.
+ def modernize_coderay_config
+ unless @config["coderay"].empty?
+ Jekyll::Deprecator.deprecation_message(
+ "You are using 'kramdown.coderay' in your configuration, " \
+ "please use 'syntax_highlighter_opts' instead."
+ )
+
+ @config["syntax_highlighter_opts"] = begin
+ strip_coderay_prefix(
+ @config["syntax_highlighter_opts"] \
+ .merge(CODERAY_DEFAULTS) \
+ .merge(@config["coderay"])
+ )
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/smartypants.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/smartypants.rb
new file mode 100644
index 0000000..606afdc
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/converters/smartypants.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+module Kramdown
+ module Parser
+ class SmartyPants < Kramdown::Parser::Kramdown
+ def initialize(source, options)
+ super
+ @block_parsers = [:block_html, :content]
+ @span_parsers = [:smart_quotes, :html_entity, :typographic_syms, :span_html]
+ end
+
+ def parse_content
+ add_text @src.scan(%r!\A.*\n!)
+ end
+ define_parser(:content, %r!\A!)
+ end
+ end
+end
+
+module Jekyll
+ module Converters
+ # SmartyPants converter.
+ # For more info on converters see https://jekyllrb.com/docs/plugins/converters/
+ class SmartyPants < Converter
+ safe true
+ priority :low
+
+ def initialize(config)
+ Jekyll::External.require_with_graceful_fail "kramdown" unless defined?(Kramdown)
+ @config = config["kramdown"].dup || {}
+ @config[:input] = :SmartyPants
+ end
+
+ # Does the given extension match this converter's list of acceptable extensions?
+ # Takes one argument: the file's extension (including the dot).
+ #
+ # ext - The String extension to check.
+ #
+ # Returns true if it matches, false otherwise.
+ def matches(_ext)
+ false
+ end
+
+ # Public: The extension to be given to the output file (including the dot).
+ #
+ # ext - The String extension or original file.
+ #
+ # Returns The String output file extension.
+ def output_ext(_ext)
+ nil
+ end
+
+ # Logic to do the content conversion.
+ #
+ # content - String content of file (without front matter).
+ #
+ # Returns a String of the converted content.
+ def convert(content)
+ document = Kramdown::Document.new(content, @config)
+ html_output = document.to_html.chomp
+ if @config["show_warnings"]
+ document.warnings.each do |warning|
+ Jekyll.logger.warn "Kramdown warning:", warning.sub(%r!^Warning:\s+!, "")
+ end
+ end
+ html_output
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/convertible.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/convertible.rb
new file mode 100644
index 0000000..b9f7a93
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/convertible.rb
@@ -0,0 +1,257 @@
+# frozen_string_literal: true
+
+# Convertible provides methods for converting a pagelike item
+# from a certain type of markup into actual content
+#
+# Requires
+# self.site -> Jekyll::Site
+# self.content
+# self.content=
+# self.data=
+# self.ext=
+# self.output=
+# self.name
+# self.path
+# self.type -> :page, :post or :draft
+
+module Jekyll
+ module Convertible
+ # Returns the contents as a String.
+ def to_s
+ content || ""
+ end
+
+ # Whether the file is published or not, as indicated in YAML front-matter
+ def published?
+ !(data.key?("published") && data["published"] == false)
+ end
+
+ # Read the YAML frontmatter.
+ #
+ # base - The String path to the dir containing the file.
+ # name - The String filename of the file.
+ # opts - optional parameter to File.read, default at site configs
+ #
+ # Returns nothing.
+ # rubocop:disable Metrics/AbcSize
+ def read_yaml(base, name, opts = {})
+ filename = @path || site.in_source_dir(base, name)
+ Jekyll.logger.debug "Reading:", relative_path
+
+ begin
+ self.content = File.read(filename, **Utils.merged_file_read_opts(site, opts))
+ if content =~ Document::YAML_FRONT_MATTER_REGEXP
+ self.content = Regexp.last_match.post_match
+ self.data = SafeYAML.load(Regexp.last_match(1))
+ end
+ rescue Psych::SyntaxError => e
+ Jekyll.logger.warn "YAML Exception reading #{filename}: #{e.message}"
+ raise e if site.config["strict_front_matter"]
+ rescue StandardError => e
+ Jekyll.logger.warn "Error reading file #{filename}: #{e.message}"
+ raise e if site.config["strict_front_matter"]
+ end
+
+ self.data ||= {}
+
+ validate_data! filename
+ validate_permalink! filename
+
+ self.data
+ end
+ # rubocop:enable Metrics/AbcSize
+
+ def validate_data!(filename)
+ unless self.data.is_a?(Hash)
+ raise Errors::InvalidYAMLFrontMatterError,
+ "Invalid YAML front matter in #{filename}"
+ end
+ end
+
+ def validate_permalink!(filename)
+ if self.data["permalink"] == ""
+ raise Errors::InvalidPermalinkError, "Invalid permalink in #{filename}"
+ end
+ end
+
+ # Transform the contents based on the content type.
+ #
+ # Returns the transformed contents.
+ def transform
+ renderer.convert(content)
+ end
+
+ # Determine the extension depending on content_type.
+ #
+ # Returns the String extension for the output file.
+ # e.g. ".html" for an HTML output file.
+ def output_ext
+ renderer.output_ext
+ end
+
+ # Determine which converter to use based on this convertible's
+ # extension.
+ #
+ # Returns the Converter instance.
+ def converters
+ renderer.converters
+ end
+
+ # Render Liquid in the content
+ #
+ # content - the raw Liquid content to render
+ # payload - the payload for Liquid
+ # info - the info for Liquid
+ #
+ # Returns the converted content
+ def render_liquid(content, payload, info, path)
+ renderer.render_liquid(content, payload, info, path)
+ end
+
+ # Convert this Convertible's data to a Hash suitable for use by Liquid.
+ #
+ # Returns the Hash representation of this Convertible.
+ def to_liquid(attrs = nil)
+ further_data = \
+ (attrs || self.class::ATTRIBUTES_FOR_LIQUID).each_with_object({}) do |attribute, hsh|
+ hsh[attribute] = send(attribute)
+ end
+
+ Utils.deep_merge_hashes defaults, Utils.deep_merge_hashes(data, further_data)
+ end
+
+ # The type of a document,
+ # i.e., its classname downcase'd and to_sym'd.
+ #
+ # Returns the type of self.
+ def type
+ :pages if is_a?(Page)
+ end
+
+ # returns the owner symbol for hook triggering
+ def hook_owner
+ :pages if is_a?(Page)
+ end
+
+ # Determine whether the document is an asset file.
+ # Asset files include CoffeeScript files and Sass/SCSS files.
+ #
+ # Returns true if the extname belongs to the set of extensions
+ # that asset files use.
+ def asset_file?
+ sass_file? || coffeescript_file?
+ end
+
+ # Determine whether the document is a Sass file.
+ #
+ # Returns true if extname == .sass or .scss, false otherwise.
+ def sass_file?
+ Jekyll::Document::SASS_FILE_EXTS.include?(ext)
+ end
+
+ # Determine whether the document is a CoffeeScript file.
+ #
+ # Returns true if extname == .coffee, false otherwise.
+ def coffeescript_file?
+ ext == ".coffee"
+ end
+
+ # Determine whether the file should be rendered with Liquid.
+ #
+ # Returns true if the file has Liquid Tags or Variables, false otherwise.
+ def render_with_liquid?
+ return false if data["render_with_liquid"] == false
+
+ Jekyll::Utils.has_liquid_construct?(content)
+ end
+
+ # Determine whether the file should be placed into layouts.
+ #
+ # Returns false if the document is an asset file or if the front matter
+ # specifies `layout: none`
+ def place_in_layout?
+ !(asset_file? || no_layout?)
+ end
+
+ # Checks if the layout specified in the document actually exists
+ #
+ # layout - the layout to check
+ #
+ # Returns true if the layout is invalid, false if otherwise
+ def invalid_layout?(layout)
+ !data["layout"].nil? && layout.nil? && !(is_a? Jekyll::Excerpt)
+ end
+
+ # Recursively render layouts
+ #
+ # layouts - a list of the layouts
+ # payload - the payload for Liquid
+ # info - the info for Liquid
+ #
+ # Returns nothing
+ def render_all_layouts(layouts, payload, info)
+ renderer.layouts = layouts
+ self.output = renderer.place_in_layouts(output, payload, info)
+ ensure
+ @renderer = nil # this will allow the modifications above to disappear
+ end
+
+ # Add any necessary layouts to this convertible document.
+ #
+ # payload - The site payload Drop or Hash.
+ # layouts - A Hash of {"name" => "layout"}.
+ #
+ # Returns nothing.
+ def do_layout(payload, layouts)
+ self.output = renderer.tap do |doc_renderer|
+ doc_renderer.layouts = layouts
+ doc_renderer.payload = payload
+ end.run
+
+ Jekyll.logger.debug "Post-Render Hooks:", relative_path
+ Jekyll::Hooks.trigger hook_owner, :post_render, self
+ ensure
+ @renderer = nil # this will allow the modifications above to disappear
+ end
+
+ # Write the generated page file to the destination directory.
+ #
+ # dest - The String path to the destination dir.
+ #
+ # Returns nothing.
+ def write(dest)
+ path = destination(dest)
+ FileUtils.mkdir_p(File.dirname(path))
+ Jekyll.logger.debug "Writing:", path
+ File.write(path, output, :mode => "wb")
+ Jekyll::Hooks.trigger hook_owner, :post_write, self
+ end
+
+ # Accessor for data properties by Liquid.
+ #
+ # property - The String name of the property to retrieve.
+ #
+ # Returns the String value or nil if the property isn't included.
+ def [](property)
+ if self.class::ATTRIBUTES_FOR_LIQUID.include?(property)
+ send(property)
+ else
+ data[property]
+ end
+ end
+
+ def renderer
+ @renderer ||= Jekyll::Renderer.new(site, self)
+ end
+
+ private
+
+ def defaults
+ @defaults ||= site.frontmatter_defaults.all(relative_path, type)
+ end
+
+ def no_layout?
+ data["layout"] == "none"
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/deprecator.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/deprecator.rb
new file mode 100644
index 0000000..4ecb656
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/deprecator.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Deprecator
+ extend self
+
+ def process(args)
+ arg_is_present? args, "--server", "The --server command has been replaced by the \
+ 'serve' subcommand."
+ arg_is_present? args, "--serve", "The --serve command has been replaced by the \
+ 'serve' subcommand."
+ arg_is_present? args, "--no-server", "To build Jekyll without launching a server, \
+ use the 'build' subcommand."
+ arg_is_present? args, "--auto", "The switch '--auto' has been replaced with \
+ '--watch'."
+ arg_is_present? args, "--no-auto", "To disable auto-replication, simply leave off \
+ the '--watch' switch."
+ arg_is_present? args, "--pygments", "The 'pygments' settings has been removed in \
+ favour of 'highlighter'."
+ arg_is_present? args, "--paginate", "The 'paginate' setting can only be set in \
+ your config files."
+ arg_is_present? args, "--url", "The 'url' setting can only be set in your \
+ config files."
+ no_subcommand(args)
+ end
+
+ def no_subcommand(args)
+ unless args.empty? ||
+ args.first !~ %r(!/^--/!) || %w(--help --version).include?(args.first)
+ deprecation_message "Jekyll now uses subcommands instead of just switches. \
+ Run `jekyll help` to find out more."
+ abort
+ end
+ end
+
+ def arg_is_present?(args, deprecated_argument, message)
+ deprecation_message(message) if args.include?(deprecated_argument)
+ end
+
+ def deprecation_message(message)
+ Jekyll.logger.warn "Deprecation:", message
+ end
+
+ def defaults_deprecate_type(old, current)
+ Jekyll.logger.warn "Defaults:", "The '#{old}' type has become '#{current}'."
+ Jekyll.logger.warn "Defaults:", "Please update your front-matter defaults to use \
+ 'type: #{current}'."
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/document.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/document.rb
new file mode 100644
index 0000000..2e39024
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/document.rb
@@ -0,0 +1,543 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Document
+ include Comparable
+ extend Forwardable
+
+ attr_reader :path, :site, :extname, :collection, :type
+ attr_accessor :content, :output
+
+ def_delegator :self, :read_post_data, :post_read
+
+ YAML_FRONT_MATTER_REGEXP = %r!\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)!m.freeze
+ DATELESS_FILENAME_MATCHER = %r!^(?:.+/)*(.*)(\.[^.]+)$!.freeze
+ DATE_FILENAME_MATCHER = %r!^(?>.+/)*?(\d{2,4}-\d{1,2}-\d{1,2})-([^/]*)(\.[^.]+)$!.freeze
+
+ SASS_FILE_EXTS = %w(.sass .scss).freeze
+ YAML_FILE_EXTS = %w(.yaml .yml).freeze
+
+ #
+
+ # Class-wide cache to stash and retrieve regexp to detect "super-directories"
+ # of a particular Jekyll::Document object.
+ #
+ # dirname - The *special directory* for the Document.
+ # e.g. "_posts" or "_drafts" for Documents from the `site.posts` collection.
+ def self.superdirs_regex(dirname)
+ @superdirs_regex ||= {}
+ @superdirs_regex[dirname] ||= %r!#{dirname}.*!
+ end
+
+ #
+
+ # Create a new Document.
+ #
+ # path - the path to the file
+ # relations - a hash with keys :site and :collection, the values of which
+ # are the Jekyll::Site and Jekyll::Collection to which this
+ # Document belong.
+ #
+ # Returns nothing.
+ def initialize(path, relations = {})
+ @site = relations[:site]
+ @path = path
+ @extname = File.extname(path)
+ @collection = relations[:collection]
+ @type = @collection.label.to_sym
+
+ @has_yaml_header = nil
+
+ if draft?
+ categories_from_path("_drafts")
+ else
+ categories_from_path(collection.relative_directory)
+ end
+
+ data.default_proc = proc do |_, key|
+ site.frontmatter_defaults.find(relative_path, type, key)
+ end
+
+ trigger_hooks(:post_init)
+ end
+
+ # Fetch the Document's data.
+ #
+ # Returns a Hash containing the data. An empty hash is returned if
+ # no data was read.
+ def data
+ @data ||= {}
+ end
+
+ # Merge some data in with this document's data.
+ #
+ # Returns the merged data.
+ def merge_data!(other, source: "YAML front matter")
+ merge_categories!(other)
+ Utils.deep_merge_hashes!(data, other)
+ merge_date!(source)
+ data
+ end
+
+ # Returns the document date. If metadata is not present then calculates it
+ # based on Jekyll::Site#time or the document file modification time.
+ #
+ # Return document date string.
+ def date
+ data["date"] ||= (draft? ? source_file_mtime : site.time)
+ end
+
+ # Return document file modification time in the form of a Time object.
+ #
+ # Return document file modification Time object.
+ def source_file_mtime
+ File.mtime(path)
+ end
+
+ # Returns whether the document is a draft. This is only the case if
+ # the document is in the 'posts' collection but in a different
+ # directory than '_posts'.
+ #
+ # Returns whether the document is a draft.
+ def draft?
+ data["draft"] ||= relative_path.index(collection.relative_directory).nil? &&
+ collection.label == "posts"
+ end
+
+ # The path to the document, relative to the collections_dir.
+ #
+ # Returns a String path which represents the relative path from the collections_dir
+ # to this document.
+ def relative_path
+ @relative_path ||= path.sub("#{site.collections_path}/", "")
+ end
+
+ # The output extension of the document.
+ #
+ # Returns the output extension
+ def output_ext
+ renderer.output_ext
+ end
+
+ # The base filename of the document, without the file extname.
+ #
+ # Returns the basename without the file extname.
+ def basename_without_ext
+ @basename_without_ext ||= File.basename(path, ".*")
+ end
+
+ # The base filename of the document.
+ #
+ # Returns the base filename of the document.
+ def basename
+ @basename ||= File.basename(path)
+ end
+
+ def renderer
+ @renderer ||= Jekyll::Renderer.new(site, self)
+ end
+
+ # Produces a "cleaned" relative path.
+ # The "cleaned" relative path is the relative path without the extname
+ # and with the collection's directory removed as well.
+ # This method is useful when building the URL of the document.
+ #
+ # NOTE: `String#gsub` removes all trailing periods (in comparison to `String#chomp`)
+ #
+ # Examples:
+ # When relative_path is "_methods/site/generate...md":
+ # cleaned_relative_path
+ # # => "/site/generate"
+ #
+ # Returns the cleaned relative path of the document.
+ def cleaned_relative_path
+ @cleaned_relative_path ||=
+ relative_path[0..-extname.length - 1]
+ .sub(collection.relative_directory, "")
+ .gsub(%r!\.*\z!, "")
+ end
+
+ # Determine whether the document is a YAML file.
+ #
+ # Returns true if the extname is either .yml or .yaml, false otherwise.
+ def yaml_file?
+ YAML_FILE_EXTS.include?(extname)
+ end
+
+ # Determine whether the document is an asset file.
+ # Asset files include CoffeeScript files and Sass/SCSS files.
+ #
+ # Returns true if the extname belongs to the set of extensions
+ # that asset files use.
+ def asset_file?
+ sass_file? || coffeescript_file?
+ end
+
+ # Determine whether the document is a Sass file.
+ #
+ # Returns true if extname == .sass or .scss, false otherwise.
+ def sass_file?
+ SASS_FILE_EXTS.include?(extname)
+ end
+
+ # Determine whether the document is a CoffeeScript file.
+ #
+ # Returns true if extname == .coffee, false otherwise.
+ def coffeescript_file?
+ extname == ".coffee"
+ end
+
+ # Determine whether the file should be rendered with Liquid.
+ #
+ # Returns false if the document is either an asset file or a yaml file,
+ # or if the document doesn't contain any Liquid Tags or Variables,
+ # true otherwise.
+ def render_with_liquid?
+ return false if data["render_with_liquid"] == false
+
+ !(coffeescript_file? || yaml_file? || !Utils.has_liquid_construct?(content))
+ end
+
+ # Determine whether the file should be rendered with a layout.
+ #
+ # Returns true if the Front Matter specifies that `layout` is set to `none`.
+ def no_layout?
+ data["layout"] == "none"
+ end
+
+ # Determine whether the file should be placed into layouts.
+ #
+ # Returns false if the document is set to `layouts: none`, or is either an
+ # asset file or a yaml file. Returns true otherwise.
+ def place_in_layout?
+ !(asset_file? || yaml_file? || no_layout?)
+ end
+
+ # The URL template where the document would be accessible.
+ #
+ # Returns the URL template for the document.
+ def url_template
+ collection.url_template
+ end
+
+ # Construct a Hash of key-value pairs which contain a mapping between
+ # a key in the URL template and the corresponding value for this document.
+ #
+ # Returns the Hash of key-value pairs for replacement in the URL.
+ def url_placeholders
+ @url_placeholders ||= Drops::UrlDrop.new(self)
+ end
+
+ # The permalink for this Document.
+ # Permalink is set via the data Hash.
+ #
+ # Returns the permalink or nil if no permalink was set in the data.
+ def permalink
+ data && data.is_a?(Hash) && data["permalink"]
+ end
+
+ # The computed URL for the document. See `Jekyll::URL#to_s` for more details.
+ #
+ # Returns the computed URL for the document.
+ def url
+ @url ||= URL.new(
+ :template => url_template,
+ :placeholders => url_placeholders,
+ :permalink => permalink
+ ).to_s
+ end
+
+ def [](key)
+ data[key]
+ end
+
+ # The full path to the output file.
+ #
+ # base_directory - the base path of the output directory
+ #
+ # Returns the full path to the output file of this document.
+ def destination(base_directory)
+ @destination ||= {}
+ @destination[base_directory] ||= begin
+ path = site.in_dest_dir(base_directory, URL.unescape_path(url))
+ if url.end_with? "/"
+ path = File.join(path, "index.html")
+ else
+ path << output_ext unless path.end_with? output_ext
+ end
+ path
+ end
+ end
+
+ # Write the generated Document file to the destination directory.
+ #
+ # dest - The String path to the destination dir.
+ #
+ # Returns nothing.
+ def write(dest)
+ path = destination(dest)
+ FileUtils.mkdir_p(File.dirname(path))
+ Jekyll.logger.debug "Writing:", path
+ File.write(path, output, :mode => "wb")
+
+ trigger_hooks(:post_write)
+ end
+
+ # Whether the file is published or not, as indicated in YAML front-matter
+ #
+ # Returns 'false' if the 'published' key is specified in the
+ # YAML front-matter and is 'false'. Otherwise returns 'true'.
+ def published?
+ !(data.key?("published") && data["published"] == false)
+ end
+
+ # Read in the file and assign the content and data based on the file contents.
+ # Merge the frontmatter of the file with the frontmatter default
+ # values
+ #
+ # Returns nothing.
+ def read(opts = {})
+ Jekyll.logger.debug "Reading:", relative_path
+
+ if yaml_file?
+ @data = SafeYAML.load_file(path)
+ else
+ begin
+ merge_defaults
+ read_content(**opts)
+ read_post_data
+ rescue StandardError => e
+ handle_read_error(e)
+ end
+ end
+ end
+
+ # Create a Liquid-understandable version of this Document.
+ #
+ # Returns a Hash representing this Document's data.
+ def to_liquid
+ @to_liquid ||= Drops::DocumentDrop.new(self)
+ end
+
+ # The inspect string for this document.
+ # Includes the relative path and the collection label.
+ #
+ # Returns the inspect string for this document.
+ def inspect
+ "#<#{self.class} #{relative_path} collection=#{collection.label}>"
+ end
+
+ # The string representation for this document.
+ #
+ # Returns the content of the document
+ def to_s
+ output || content || "NO CONTENT"
+ end
+
+ # Compare this document against another document.
+ # Comparison is a comparison between the 2 paths of the documents.
+ #
+ # Returns -1, 0, +1 or nil depending on whether this doc's path is less than,
+ # equal or greater than the other doc's path. See String#<=> for more details.
+ def <=>(other)
+ return nil unless other.respond_to?(:data)
+
+ cmp = data["date"] <=> other.data["date"]
+ cmp = path <=> other.path if cmp.nil? || cmp.zero?
+ cmp
+ end
+
+ # Determine whether this document should be written.
+ # Based on the Collection to which it belongs.
+ #
+ # True if the document has a collection and if that collection's #write?
+ # method returns true, and if the site's Publisher will publish the document.
+ # False otherwise.
+ #
+ # rubocop:disable Naming/MemoizedInstanceVariableName
+ def write?
+ return @write_p if defined?(@write_p)
+
+ @write_p = collection&.write? && site.publisher.publish?(self)
+ end
+ # rubocop:enable Naming/MemoizedInstanceVariableName
+
+ # The Document excerpt_separator, from the YAML Front-Matter or site
+ # default excerpt_separator value
+ #
+ # Returns the document excerpt_separator
+ def excerpt_separator
+ @excerpt_separator ||= (data["excerpt_separator"] || site.config["excerpt_separator"]).to_s
+ end
+
+ # Whether to generate an excerpt
+ #
+ # Returns true if the excerpt separator is configured.
+ def generate_excerpt?
+ !excerpt_separator.empty?
+ end
+
+ def next_doc
+ pos = collection.docs.index { |post| post.equal?(self) }
+ collection.docs[pos + 1] if pos && pos < collection.docs.length - 1
+ end
+
+ def previous_doc
+ pos = collection.docs.index { |post| post.equal?(self) }
+ collection.docs[pos - 1] if pos && pos.positive?
+ end
+
+ def trigger_hooks(hook_name, *args)
+ Jekyll::Hooks.trigger collection.label.to_sym, hook_name, self, *args if collection
+ Jekyll::Hooks.trigger :documents, hook_name, self, *args
+ end
+
+ def id
+ @id ||= File.join(File.dirname(url), (data["slug"] || basename_without_ext).to_s)
+ end
+
+ # Calculate related posts.
+ #
+ # Returns an Array of related Posts.
+ def related_posts
+ @related_posts ||= Jekyll::RelatedPosts.new(self).build
+ end
+
+ # Override of method_missing to check in @data for the key.
+ def method_missing(method, *args, &blck)
+ if data.key?(method.to_s)
+ Jekyll::Deprecator.deprecation_message "Document##{method} is now a key in the #data hash."
+ Jekyll.logger.warn "", "Called by #{caller(1..1)[0]}."
+ data[method.to_s]
+ else
+ super
+ end
+ end
+
+ def respond_to_missing?(method, *)
+ data.key?(method.to_s) || super
+ end
+
+ # Add superdirectories of the special_dir to categories.
+ # In the case of es/_posts, 'es' is added as a category.
+ # In the case of _posts/es, 'es' is NOT added as a category.
+ #
+ # Returns nothing.
+ def categories_from_path(special_dir)
+ if relative_path.start_with?(special_dir)
+ superdirs = []
+ else
+ superdirs = relative_path.sub(Document.superdirs_regex(special_dir), "")
+ superdirs = superdirs.split(File::SEPARATOR)
+ superdirs.reject! { |c| c.empty? || c == special_dir || c == basename }
+ end
+
+ merge_data!({ "categories" => superdirs }, :source => "file path")
+ end
+
+ def populate_categories
+ categories = Array(data["categories"]) + Utils.pluralized_array_from_hash(
+ data, "category", "categories"
+ )
+ categories.map!(&:to_s)
+ categories.flatten!
+ categories.uniq!
+
+ merge_data!({ "categories" => categories })
+ end
+
+ def populate_tags
+ tags = Utils.pluralized_array_from_hash(data, "tag", "tags")
+ tags.flatten!
+
+ merge_data!({ "tags" => tags })
+ end
+
+ private
+
+ def merge_categories!(other)
+ if other.key?("categories") && !other["categories"].nil?
+ other["categories"] = other["categories"].split if other["categories"].is_a?(String)
+
+ if data["categories"].is_a?(Array)
+ other["categories"] = data["categories"] | other["categories"]
+ end
+ end
+ end
+
+ def merge_date!(source)
+ if data.key?("date")
+ data["date"] = Utils.parse_date(
+ data["date"].to_s,
+ "Document '#{relative_path}' does not have a valid date in the #{source}."
+ )
+ end
+ end
+
+ def merge_defaults
+ defaults = @site.frontmatter_defaults.all(relative_path, type)
+ merge_data!(defaults, :source => "front matter defaults") unless defaults.empty?
+ end
+
+ def read_content(**opts)
+ self.content = File.read(path, **Utils.merged_file_read_opts(site, opts))
+ if content =~ YAML_FRONT_MATTER_REGEXP
+ self.content = Regexp.last_match.post_match
+ data_file = SafeYAML.load(Regexp.last_match(1))
+ merge_data!(data_file, :source => "YAML front matter") if data_file
+ end
+ end
+
+ def read_post_data
+ populate_title
+ populate_categories
+ populate_tags
+ generate_excerpt
+ end
+
+ def handle_read_error(error)
+ if error.is_a? Psych::SyntaxError
+ Jekyll.logger.error "Error:", "YAML Exception reading #{path}: #{error.message}"
+ else
+ Jekyll.logger.error "Error:", "could not read file #{path}: #{error.message}"
+ end
+
+ if site.config["strict_front_matter"] || error.is_a?(Jekyll::Errors::FatalException)
+ raise error
+ end
+ end
+
+ def populate_title
+ if relative_path =~ DATE_FILENAME_MATCHER
+ date, slug, ext = Regexp.last_match.captures
+ modify_date(date)
+ elsif relative_path =~ DATELESS_FILENAME_MATCHER
+ slug, ext = Regexp.last_match.captures
+ end
+ # `slug` will be nil for documents without an extension since the regex patterns
+ # above tests for an extension as well.
+ # In such cases, assign `basename_without_ext` as the slug.
+ slug ||= basename_without_ext
+
+ # slugs shouldn't end with a period
+ # `String#gsub!` removes all trailing periods (in comparison to `String#chomp!`)
+ slug.gsub!(%r!\.*\z!, "")
+
+ # Try to ensure the user gets a title.
+ data["title"] ||= Utils.titleize_slug(slug)
+ # Only overwrite slug & ext if they aren't specified.
+ data["slug"] ||= slug
+ data["ext"] ||= ext
+ end
+
+ def modify_date(date)
+ if !data["date"] || data["date"].to_i == site.time.to_i
+ merge_data!({ "date" => date }, :source => "filename")
+ end
+ end
+
+ def generate_excerpt
+ data["excerpt"] ||= Jekyll::Excerpt.new(self) if generate_excerpt?
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/collection_drop.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/collection_drop.rb
new file mode 100644
index 0000000..4fe95a5
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/collection_drop.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Drops
+ class CollectionDrop < Drop
+ extend Forwardable
+
+ mutable false
+
+ delegate_method_as :write?, :output
+ delegate_methods :label, :docs, :files, :directory, :relative_directory
+
+ private delegate_method_as :metadata, :fallback_data
+
+ def to_s
+ docs.to_s
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/document_drop.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/document_drop.rb
new file mode 100644
index 0000000..0cff374
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/document_drop.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Drops
+ class DocumentDrop < Drop
+ extend Forwardable
+
+ NESTED_OBJECT_FIELD_BLACKLIST = %w(
+ content output excerpt next previous
+ ).freeze
+
+ mutable false
+
+ delegate_method_as :relative_path, :path
+ private delegate_method_as :data, :fallback_data
+
+ delegate_methods :id, :output, :content, :to_s, :relative_path, :url, :date
+ data_delegators "title", "categories", "tags"
+
+ def collection
+ @obj.collection.label
+ end
+
+ def excerpt
+ fallback_data["excerpt"].to_s
+ end
+
+ def name
+ fallback_data["name"] || @obj.basename
+ end
+
+ def <=>(other)
+ return nil unless other.is_a? DocumentDrop
+
+ cmp = self["date"] <=> other["date"]
+ cmp = self["path"] <=> other["path"] if cmp.nil? || cmp.zero?
+ cmp
+ end
+
+ def previous
+ @obj.previous_doc.to_liquid
+ end
+
+ def next
+ @obj.next_doc.to_liquid
+ end
+
+ # Generate a Hash for use in generating JSON.
+ # This is useful if fields need to be cleared before the JSON can generate.
+ #
+ # state - the JSON::State object which determines the state of current processing.
+ #
+ # Returns a Hash ready for JSON generation.
+ def hash_for_json(state = nil)
+ to_h.tap do |hash|
+ if state && state.depth >= 2
+ hash["previous"] = collapse_document(hash["previous"]) if hash["previous"]
+ hash["next"] = collapse_document(hash["next"]) if hash["next"]
+ end
+ end
+ end
+
+ # Generate a Hash which breaks the recursive chain.
+ # Certain fields which are normally available are omitted.
+ #
+ # Returns a Hash with only non-recursive fields present.
+ def collapse_document(doc)
+ doc.keys.each_with_object({}) do |(key, _), result|
+ result[key] = doc[key] unless NESTED_OBJECT_FIELD_BLACKLIST.include?(key)
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/drop.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/drop.rb
new file mode 100644
index 0000000..b82c7b4
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/drop.rb
@@ -0,0 +1,294 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Drops
+ class Drop < Liquid::Drop
+ include Enumerable
+
+ NON_CONTENT_METHODS = [:fallback_data, :collapse_document].freeze
+ NON_CONTENT_METHOD_NAMES = NON_CONTENT_METHODS.map(&:to_s).freeze
+ private_constant :NON_CONTENT_METHOD_NAMES
+
+ # A private stash to avoid repeatedly generating the setter method name string for
+ # a call to `Drops::Drop#[]=`.
+ # The keys of the stash below have a very high probability of being called upon during
+ # the course of various `Jekyll::Renderer#run` calls.
+ SETTER_KEYS_STASH = {
+ "content" => "content=",
+ "layout" => "layout=",
+ "page" => "page=",
+ "paginator" => "paginator=",
+ "highlighter_prefix" => "highlighter_prefix=",
+ "highlighter_suffix" => "highlighter_suffix=",
+ }.freeze
+ private_constant :SETTER_KEYS_STASH
+
+ class << self
+ # Get or set whether the drop class is mutable.
+ # Mutability determines whether or not pre-defined fields may be
+ # overwritten.
+ #
+ # is_mutable - Boolean set mutability of the class (default: nil)
+ #
+ # Returns the mutability of the class
+ def mutable(is_mutable = nil)
+ @is_mutable = is_mutable || false
+ end
+
+ def mutable?
+ @is_mutable
+ end
+
+ # public delegation helper methods that calls onto Drop's instance
+ # variable `@obj`.
+
+ # Generate private Drop instance_methods for each symbol in the given list.
+ #
+ # Returns nothing.
+ def private_delegate_methods(*symbols)
+ symbols.each { |symbol| private delegate_method(symbol) }
+ nil
+ end
+
+ # Generate public Drop instance_methods for each symbol in the given list.
+ #
+ # Returns nothing.
+ def delegate_methods(*symbols)
+ symbols.each { |symbol| delegate_method(symbol) }
+ nil
+ end
+
+ # Generate public Drop instance_method for given symbol that calls `@obj.<sym>`.
+ #
+ # Returns delegated method symbol.
+ def delegate_method(symbol)
+ define_method(symbol) { @obj.send(symbol) }
+ end
+
+ # Generate public Drop instance_method named `delegate` that calls `@obj.<original>`.
+ #
+ # Returns delegated method symbol.
+ def delegate_method_as(original, delegate)
+ define_method(delegate) { @obj.send(original) }
+ end
+
+ # Generate public Drop instance_methods for each string entry in the given list.
+ # The generated method(s) access(es) `@obj`'s data hash.
+ #
+ # Returns nothing.
+ def data_delegators(*strings)
+ strings.each do |key|
+ data_delegator(key) if key.is_a?(String)
+ end
+ nil
+ end
+
+ # Generate public Drop instance_methods for given string `key`.
+ # The generated method access(es) `@obj`'s data hash.
+ #
+ # Returns method symbol.
+ def data_delegator(key)
+ define_method(key.to_sym) { @obj.data[key] }
+ end
+
+ # Array of stringified instance methods that do not end with the assignment operator.
+ #
+ # (<klass>.instance_methods always generates a new Array object so it can be mutated)
+ #
+ # Returns array of strings.
+ def getter_method_names
+ @getter_method_names ||= instance_methods.map!(&:to_s).tap do |list|
+ list.reject! { |item| item.end_with?("=") }
+ end
+ end
+ end
+
+ # Create a new Drop
+ #
+ # obj - the Jekyll Site, Collection, or Document required by the
+ # drop.
+ #
+ # Returns nothing
+ def initialize(obj)
+ @obj = obj
+ end
+
+ # Access a method in the Drop or a field in the underlying hash data.
+ # If mutable, checks the mutations first. Then checks the methods,
+ # and finally check the underlying hash (e.g. document front matter)
+ # if all the previous places didn't match.
+ #
+ # key - the string key whose value to fetch
+ #
+ # Returns the value for the given key, or nil if none exists
+ def [](key)
+ if self.class.mutable? && mutations.key?(key)
+ mutations[key]
+ elsif self.class.invokable? key
+ public_send key
+ else
+ fallback_data[key]
+ end
+ end
+ alias_method :invoke_drop, :[]
+
+ # Set a field in the Drop. If mutable, sets in the mutations and
+ # returns. If not mutable, checks first if it's trying to override a
+ # Drop method and raises a DropMutationException if so. If not
+ # mutable and the key is not a method on the Drop, then it sets the
+ # key to the value in the underlying hash (e.g. document front
+ # matter)
+ #
+ # key - the String key whose value to set
+ # val - the Object to set the key's value to
+ #
+ # Returns the value the key was set to unless the Drop is not mutable
+ # and the key matches a method in which case it raises a
+ # DropMutationException.
+ def []=(key, val)
+ setter = SETTER_KEYS_STASH[key] || "#{key}="
+ if respond_to?(setter)
+ public_send(setter, val)
+ elsif respond_to?(key.to_s)
+ if self.class.mutable?
+ mutations[key] = val
+ else
+ raise Errors::DropMutationException, "Key #{key} cannot be set in the drop."
+ end
+ else
+ fallback_data[key] = val
+ end
+ end
+
+ # Generates a list of strings which correspond to content getter
+ # methods.
+ #
+ # Returns an Array of strings which represent method-specific keys.
+ def content_methods
+ @content_methods ||= \
+ self.class.getter_method_names \
+ - Jekyll::Drops::Drop.getter_method_names \
+ - NON_CONTENT_METHOD_NAMES
+ end
+
+ # Check if key exists in Drop
+ #
+ # key - the string key whose value to fetch
+ #
+ # Returns true if the given key is present
+ def key?(key)
+ return false if key.nil?
+ return true if self.class.mutable? && mutations.key?(key)
+
+ respond_to?(key) || fallback_data.key?(key)
+ end
+
+ # Generates a list of keys with user content as their values.
+ # This gathers up the Drop methods and keys of the mutations and
+ # underlying data hashes and performs a set union to ensure a list
+ # of unique keys for the Drop.
+ #
+ # Returns an Array of unique keys for content for the Drop.
+ def keys
+ (content_methods |
+ mutations.keys |
+ fallback_data.keys).flatten
+ end
+
+ # Generate a Hash representation of the Drop by resolving each key's
+ # value. It includes Drop methods, mutations, and the underlying object's
+ # data. See the documentation for Drop#keys for more.
+ #
+ # Returns a Hash with all the keys and values resolved.
+ def to_h
+ keys.each_with_object({}) do |(key, _), result|
+ result[key] = self[key]
+ end
+ end
+ alias_method :to_hash, :to_h
+
+ # Inspect the drop's keys and values through a JSON representation
+ # of its keys and values.
+ #
+ # Returns a pretty generation of the hash representation of the Drop.
+ def inspect
+ JSON.pretty_generate to_h
+ end
+
+ # Generate a Hash for use in generating JSON.
+ # This is useful if fields need to be cleared before the JSON can generate.
+ #
+ # Returns a Hash ready for JSON generation.
+ def hash_for_json(*)
+ to_h
+ end
+
+ # Generate a JSON representation of the Drop.
+ #
+ # state - the JSON::State object which determines the state of current processing.
+ #
+ # Returns a JSON representation of the Drop in a String.
+ def to_json(state = nil)
+ JSON.generate(hash_for_json(state), state)
+ end
+
+ # Collects all the keys and passes each to the block in turn.
+ #
+ # block - a block which accepts one argument, the key
+ #
+ # Returns nothing.
+ def each_key(&block)
+ keys.each(&block)
+ end
+
+ def each
+ each_key.each do |key|
+ yield key, self[key]
+ end
+ end
+
+ def merge(other, &block)
+ dup.tap do |me|
+ if block.nil?
+ me.merge!(other)
+ else
+ me.merge!(other, block)
+ end
+ end
+ end
+
+ def merge!(other)
+ other.each_key do |key|
+ if block_given?
+ self[key] = yield key, self[key], other[key]
+ else
+ if Utils.mergable?(self[key]) && Utils.mergable?(other[key])
+ self[key] = Utils.deep_merge_hashes(self[key], other[key])
+ next
+ end
+
+ self[key] = other[key] unless other[key].nil?
+ end
+ end
+ end
+
+ # Imitate Hash.fetch method in Drop
+ #
+ # Returns value if key is present in Drop, otherwise returns default value
+ # KeyError is raised if key is not present and no default value given
+ def fetch(key, default = nil, &block)
+ return self[key] if key?(key)
+ raise KeyError, %(key not found: "#{key}") if default.nil? && block.nil?
+ return yield(key) unless block.nil?
+
+ default unless default.nil?
+ end
+
+ private
+
+ def mutations
+ @mutations ||= {}
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/excerpt_drop.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/excerpt_drop.rb
new file mode 100644
index 0000000..82d3cdf
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/excerpt_drop.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Drops
+ class ExcerptDrop < DocumentDrop
+ def layout
+ @obj.doc.data["layout"]
+ end
+
+ def date
+ @obj.doc.date
+ end
+
+ def excerpt
+ nil
+ end
+
+ def name
+ @obj.doc.data["name"] || @obj.doc.basename
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/jekyll_drop.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/jekyll_drop.rb
new file mode 100644
index 0000000..63187cc
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/jekyll_drop.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Drops
+ class JekyllDrop < Liquid::Drop
+ class << self
+ def global
+ @global ||= JekyllDrop.new
+ end
+ end
+
+ def version
+ Jekyll::VERSION
+ end
+
+ def environment
+ Jekyll.env
+ end
+
+ def to_h
+ @to_h ||= {
+ "version" => version,
+ "environment" => environment,
+ }
+ end
+
+ def to_json(state = nil)
+ JSON.generate(to_h, state)
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/site_drop.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/site_drop.rb
new file mode 100644
index 0000000..cc3c60f
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/site_drop.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Drops
+ class SiteDrop < Drop
+ extend Forwardable
+
+ mutable false
+
+ delegate_method_as :site_data, :data
+ delegate_methods :time, :pages, :static_files, :tags, :categories
+
+ private delegate_method_as :config, :fallback_data
+
+ def [](key)
+ if key != "posts" && @obj.collections.key?(key)
+ @obj.collections[key].docs
+ else
+ super(key)
+ end
+ end
+
+ def key?(key)
+ (key != "posts" && @obj.collections.key?(key)) || super
+ end
+
+ def posts
+ @site_posts ||= @obj.posts.docs.sort { |a, b| b <=> a }
+ end
+
+ def html_pages
+ @site_html_pages ||= @obj.pages.select do |page|
+ page.html? || page.url.end_with?("/")
+ end
+ end
+
+ def collections
+ @site_collections ||= @obj.collections.values.sort_by(&:label).map(&:to_liquid)
+ end
+
+ # `Site#documents` cannot be memoized so that `Site#docs_to_write` can access the
+ # latest state of the attribute.
+ #
+ # Since this method will be called after `Site#pre_render` hook, the `Site#documents`
+ # array shouldn't thereafter change and can therefore be safely memoized to prevent
+ # additional computation of `Site#documents`.
+ def documents
+ @documents ||= @obj.documents
+ end
+
+ # `{{ site.related_posts }}` is how posts can get posts related to
+ # them, either through LSI if it's enabled, or through the most
+ # recent posts.
+ # We should remove this in 4.0 and switch to `{{ post.related_posts }}`.
+ def related_posts
+ return nil unless @current_document.is_a?(Jekyll::Document)
+
+ @current_document.related_posts
+ end
+ attr_writer :current_document
+
+ # return nil for `{{ site.config }}` even if --config was passed via CLI
+ def config; end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/static_file_drop.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/static_file_drop.rb
new file mode 100644
index 0000000..d00973b
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/static_file_drop.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Drops
+ class StaticFileDrop < Drop
+ extend Forwardable
+ delegate_methods :name, :extname, :modified_time, :basename
+ delegate_method_as :relative_path, :path
+ delegate_method_as :type, :collection
+
+ private delegate_method_as :data, :fallback_data
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/theme_drop.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/theme_drop.rb
new file mode 100644
index 0000000..dd5b281
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/theme_drop.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Drops
+ class ThemeDrop < Drop
+ delegate_method_as :runtime_dependencies, :dependencies
+
+ def root
+ @root ||= ENV["JEKYLL_ENV"] == "development" ? @obj.root : ""
+ end
+
+ def authors
+ @authors ||= gemspec.authors.join(", ")
+ end
+
+ def version
+ @version ||= gemspec.version.to_s
+ end
+
+ def description
+ @description ||= gemspec.description || gemspec.summary
+ end
+
+ def metadata
+ @metadata ||= gemspec.metadata
+ end
+
+ private
+
+ def gemspec
+ @gemspec ||= @obj.send(:gemspec)
+ end
+
+ def fallback_data
+ @fallback_data ||= {}
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/unified_payload_drop.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/unified_payload_drop.rb
new file mode 100644
index 0000000..709ad71
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/unified_payload_drop.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Drops
+ class UnifiedPayloadDrop < Drop
+ mutable true
+
+ attr_accessor :content, :page, :layout, :paginator,
+ :highlighter_prefix, :highlighter_suffix
+
+ def jekyll
+ JekyllDrop.global
+ end
+
+ def site
+ @site_drop ||= SiteDrop.new(@obj)
+ end
+
+ def theme
+ @theme_drop ||= ThemeDrop.new(@obj.theme) if @obj.theme
+ end
+
+ private
+
+ def fallback_data
+ @fallback_data ||= {}
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/url_drop.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/url_drop.rb
new file mode 100644
index 0000000..de58c95
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/drops/url_drop.rb
@@ -0,0 +1,140 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Drops
+ class UrlDrop < Drop
+ extend Forwardable
+
+ mutable false
+
+ delegate_method :output_ext
+ delegate_method_as :cleaned_relative_path, :path
+
+ def collection
+ @obj.collection.label
+ end
+
+ def name
+ Utils.slugify(@obj.basename_without_ext)
+ end
+
+ def title
+ Utils.slugify(@obj.data["slug"], :mode => "pretty", :cased => true) ||
+ Utils.slugify(@obj.basename_without_ext, :mode => "pretty", :cased => true)
+ end
+
+ def slug
+ Utils.slugify(@obj.data["slug"]) || Utils.slugify(@obj.basename_without_ext)
+ end
+
+ def categories
+ category_set = Set.new
+ Array(@obj.data["categories"]).each do |category|
+ category_set << category.to_s.downcase
+ end
+ category_set.to_a.join("/")
+ end
+
+ # Similar to output from #categories, but each category will be downcased and
+ # all non-alphanumeric characters of the category replaced with a hyphen.
+ def slugified_categories
+ Array(@obj.data["categories"]).each_with_object(Set.new) do |category, set|
+ set << Utils.slugify(category.to_s)
+ end.to_a.join("/")
+ end
+
+ # CCYY
+ def year
+ @obj.date.strftime("%Y")
+ end
+
+ # MM: 01..12
+ def month
+ @obj.date.strftime("%m")
+ end
+
+ # DD: 01..31
+ def day
+ @obj.date.strftime("%d")
+ end
+
+ # hh: 00..23
+ def hour
+ @obj.date.strftime("%H")
+ end
+
+ # mm: 00..59
+ def minute
+ @obj.date.strftime("%M")
+ end
+
+ # ss: 00..59
+ def second
+ @obj.date.strftime("%S")
+ end
+
+ # D: 1..31
+ def i_day
+ @obj.date.strftime("%-d")
+ end
+
+ # M: 1..12
+ def i_month
+ @obj.date.strftime("%-m")
+ end
+
+ # MMM: Jan..Dec
+ def short_month
+ @obj.date.strftime("%b")
+ end
+
+ # MMMM: January..December
+ def long_month
+ @obj.date.strftime("%B")
+ end
+
+ # YY: 00..99
+ def short_year
+ @obj.date.strftime("%y")
+ end
+
+ # CCYYw, ISO week year
+ # may differ from CCYY for the first days of January and last days of December
+ def w_year
+ @obj.date.strftime("%G")
+ end
+
+ # WW: 01..53
+ # %W and %U do not comply with ISO 8601-1
+ def week
+ @obj.date.strftime("%V")
+ end
+
+ # d: 1..7 (Monday..Sunday)
+ def w_day
+ @obj.date.strftime("%u")
+ end
+
+ # dd: Mon..Sun
+ def short_day
+ @obj.date.strftime("%a")
+ end
+
+ # ddd: Monday..Sunday
+ def long_day
+ @obj.date.strftime("%A")
+ end
+
+ # DDD: 001..366
+ def y_day
+ @obj.date.strftime("%j")
+ end
+
+ private
+
+ def fallback_data
+ @fallback_data ||= {}
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/entry_filter.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/entry_filter.rb
new file mode 100644
index 0000000..4e70a5d
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/entry_filter.rb
@@ -0,0 +1,117 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class EntryFilter
+ attr_reader :site
+
+ SPECIAL_LEADING_CHAR_REGEX = %r!\A#{Regexp.union([".", "_", "#", "~"])}!o.freeze
+
+ def initialize(site, base_directory = nil)
+ @site = site
+ @base_directory = derive_base_directory(
+ @site, base_directory.to_s.dup
+ )
+ end
+
+ def base_directory
+ @base_directory.to_s
+ end
+
+ def derive_base_directory(site, base_dir)
+ base_dir[site.source] = "" if base_dir.start_with?(site.source)
+ base_dir
+ end
+
+ def relative_to_source(entry)
+ File.join(
+ base_directory, entry
+ )
+ end
+
+ def filter(entries)
+ entries.reject do |e|
+ # Reject this entry if it is just a "dot" representation.
+ # e.g.: '.', '..', '_movies/.', 'music/..', etc
+ next true if e.end_with?(".")
+
+ # Check if the current entry is explicitly included and cache the result
+ included = included?(e)
+
+ # Reject current entry if it is excluded but not explicitly included as well.
+ next true if excluded?(e) && !included
+
+ # Reject current entry if it is a symlink.
+ next true if symlink?(e)
+
+ # Do not reject current entry if it is explicitly included.
+ next false if included
+
+ # Reject current entry if it is special or a backup file.
+ special?(e) || backup?(e)
+ end
+ end
+
+ def included?(entry)
+ glob_include?(site.include, entry) ||
+ glob_include?(site.include, File.basename(entry))
+ end
+
+ def special?(entry)
+ SPECIAL_LEADING_CHAR_REGEX.match?(entry) ||
+ SPECIAL_LEADING_CHAR_REGEX.match?(File.basename(entry))
+ end
+
+ def backup?(entry)
+ entry.end_with?("~")
+ end
+
+ def excluded?(entry)
+ glob_include?(site.exclude - site.include, relative_to_source(entry)).tap do |excluded|
+ if excluded
+ Jekyll.logger.debug(
+ "EntryFilter:",
+ "excluded #{relative_to_source(entry)}"
+ )
+ end
+ end
+ end
+
+ # --
+ # Check if a file is a symlink.
+ # NOTE: This can be converted to allowing even in safe,
+ # since we use Pathutil#in_path? now.
+ # --
+ def symlink?(entry)
+ site.safe && File.symlink?(entry) && symlink_outside_site_source?(entry)
+ end
+
+ # --
+ # Check if given path is outside of current site's configured source directory.
+ # --
+ def symlink_outside_site_source?(entry)
+ !File.realpath(entry).start_with?(site.in_source_dir)
+ end
+
+ # Check if an entry matches a specific pattern.
+ # Returns true if path matches against any glob pattern, else false.
+ def glob_include?(enumerator, entry)
+ entry_with_source = PathManager.join(site.source, entry)
+ entry_is_directory = File.directory?(entry_with_source)
+
+ enumerator.any? do |pattern|
+ case pattern
+ when String
+ pattern_with_source = PathManager.join(site.source, pattern)
+
+ File.fnmatch?(pattern_with_source, entry_with_source) ||
+ entry_with_source.start_with?(pattern_with_source) ||
+ (pattern_with_source == "#{entry_with_source}/" if entry_is_directory)
+ when Regexp
+ pattern.match?(entry_with_source)
+ else
+ false
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/errors.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/errors.rb
new file mode 100644
index 0000000..8d659e8
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/errors.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Errors
+ FatalException = Class.new(::RuntimeError)
+
+ InvalidThemeName = Class.new(FatalException)
+
+ DropMutationException = Class.new(FatalException)
+ InvalidPermalinkError = Class.new(FatalException)
+ InvalidYAMLFrontMatterError = Class.new(FatalException)
+ MissingDependencyException = Class.new(FatalException)
+
+ InvalidDateError = Class.new(FatalException)
+ InvalidPostNameError = Class.new(FatalException)
+ PostURLError = Class.new(FatalException)
+ InvalidURLError = Class.new(FatalException)
+ InvalidConfigurationError = Class.new(FatalException)
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/excerpt.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/excerpt.rb
new file mode 100644
index 0000000..6318520
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/excerpt.rb
@@ -0,0 +1,200 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Excerpt
+ extend Forwardable
+
+ attr_accessor :content, :doc, :ext
+ attr_writer :output
+
+ def_delegators :@doc,
+ :site, :name, :ext, :extname,
+ :collection, :related_posts, :type,
+ :coffeescript_file?, :yaml_file?,
+ :url, :next_doc, :previous_doc
+
+ private :coffeescript_file?, :yaml_file?
+
+ # Initialize this Excerpt instance.
+ #
+ # doc - The Document.
+ #
+ # Returns the new Excerpt.
+ def initialize(doc)
+ self.doc = doc
+ self.content = extract_excerpt(doc.content)
+ end
+
+ # Fetch YAML front-matter data from related doc, without layout key
+ #
+ # Returns Hash of doc data
+ def data
+ @data ||= doc.data.dup
+ @data.delete("layout")
+ @data.delete("excerpt")
+ @data
+ end
+
+ def trigger_hooks(*); end
+
+ # 'Path' of the excerpt.
+ #
+ # Returns the path for the doc this excerpt belongs to with #excerpt appended
+ def path
+ File.join(doc.path, "#excerpt")
+ end
+
+ # 'Relative Path' of the excerpt.
+ #
+ # Returns the relative_path for the doc this excerpt belongs to with #excerpt appended
+ def relative_path
+ @relative_path ||= File.join(doc.relative_path, "#excerpt")
+ end
+
+ # Check if excerpt includes a string
+ #
+ # Returns true if the string passed in
+ def include?(something)
+ output&.include?(something) || content.include?(something)
+ end
+
+ # The UID for this doc (useful in feeds).
+ # e.g. /2008/11/05/my-awesome-doc
+ #
+ # Returns the String UID.
+ def id
+ "#{doc.id}#excerpt"
+ end
+
+ def to_s
+ output || content
+ end
+
+ def to_liquid
+ Jekyll::Drops::ExcerptDrop.new(self)
+ end
+
+ # Returns the shorthand String identifier of this doc.
+ def inspect
+ "<#{self.class} id=#{id}>"
+ end
+
+ def output
+ @output ||= Renderer.new(doc.site, self, site.site_payload).run
+ end
+
+ def place_in_layout?
+ false
+ end
+
+ def render_with_liquid?
+ return false if data["render_with_liquid"] == false
+
+ !(coffeescript_file? || yaml_file? || !Utils.has_liquid_construct?(content))
+ end
+
+ protected
+
+ # Internal: Extract excerpt from the content
+ #
+ # By default excerpt is your first paragraph of a doc: everything before
+ # the first two new lines:
+ #
+ # ---
+ # title: Example
+ # ---
+ #
+ # First paragraph with [link][1].
+ #
+ # Second paragraph.
+ #
+ # [1]: http://example.com/
+ #
+ # This is fairly good option for Markdown and Textile files. But might cause
+ # problems for HTML docs (which is quite unusual for Jekyll). If default
+ # excerpt delimiter is not good for you, you might want to set your own via
+ # configuration option `excerpt_separator`. For example, following is a good
+ # alternative for HTML docs:
+ #
+ # # file: _config.yml
+ # excerpt_separator: "<!-- more -->"
+ #
+ # Notice that all markdown-style link references will be appended to the
+ # excerpt. So the example doc above will have this excerpt source:
+ #
+ # First paragraph with [link][1].
+ #
+ # [1]: http://example.com/
+ #
+ # Excerpts are rendered same time as content is rendered.
+ #
+ # Returns excerpt String
+
+ LIQUID_TAG_REGEX = %r!{%-?\s*(\w+)\s*.*?-?%}!m.freeze
+ MKDWN_LINK_REF_REGEX = %r!^ {0,3}(?:(\[[^\]]+\])(:.+))$!.freeze
+
+ def extract_excerpt(doc_content)
+ head, _, tail = doc_content.to_s.partition(doc.excerpt_separator)
+ return head if tail.empty?
+
+ head = sanctify_liquid_tags(head) if head.include?("{%")
+ definitions = extract_markdown_link_reference_definitions(head, tail)
+ return head if definitions.empty?
+
+ head << "\n\n" << definitions.join("\n")
+ end
+
+ private
+
+ # append appropriate closing tag(s) (for each Liquid block), to the `head` if the
+ # partitioning resulted in leaving the closing tag somewhere in the `tail` partition.
+ def sanctify_liquid_tags(head)
+ modified = false
+ tag_names = head.scan(LIQUID_TAG_REGEX)
+ tag_names.flatten!
+ tag_names.reverse_each do |tag_name|
+ next unless liquid_block?(tag_name)
+ next if endtag_regex_stash(tag_name).match?(head)
+
+ modified = true
+ head << "\n{% end#{tag_name} %}"
+ end
+
+ print_build_warning if modified
+ head
+ end
+
+ def extract_markdown_link_reference_definitions(head, tail)
+ [].tap do |definitions|
+ tail.scan(MKDWN_LINK_REF_REGEX).each do |segments|
+ definitions << segments.join if head.include?(segments[0])
+ end
+ end
+ end
+
+ def endtag_regex_stash(tag_name)
+ @endtag_regex_stash ||= {}
+ @endtag_regex_stash[tag_name] ||= %r!{%-?\s*end#{tag_name}.*?\s*-?%}!m
+ end
+
+ def liquid_block?(tag_name)
+ return false unless tag_name.is_a?(String)
+ return false unless Liquid::Template.tags[tag_name]
+
+ Liquid::Template.tags[tag_name].ancestors.include?(Liquid::Block)
+ rescue NoMethodError
+ Jekyll.logger.error "Error:",
+ "A Liquid tag in the excerpt of #{doc.relative_path} couldn't be parsed."
+ raise
+ end
+
+ def print_build_warning
+ Jekyll.logger.warn "Warning:", "Excerpt modified in #{doc.relative_path}!"
+ Jekyll.logger.warn "", "Found a Liquid block containing the excerpt separator " \
+ "#{doc.excerpt_separator.inspect}."
+ Jekyll.logger.warn "", "The block has been modified with the appropriate closing tag."
+ Jekyll.logger.warn "", "Feel free to define a custom excerpt or excerpt_separator in the"
+ Jekyll.logger.warn "", "document's Front Matter if the generated excerpt is unsatisfactory."
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/external.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/external.rb
new file mode 100644
index 0000000..b484160
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/external.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module External
+ class << self
+ #
+ # Gems that, if installed, should be loaded.
+ # Usually contain subcommands.
+ #
+ def blessed_gems
+ %w(
+ jekyll-compose
+ jekyll-docs
+ jekyll-import
+ )
+ end
+
+ #
+ # Require a gem or file if it's present, otherwise silently fail.
+ #
+ # names - a string gem name or array of gem names
+ #
+ def require_if_present(names)
+ Array(names).each do |name|
+ require name
+ rescue LoadError
+ Jekyll.logger.debug "Couldn't load #{name}. Skipping."
+ yield(name, version_constraint(name)) if block_given?
+ false
+ end
+ end
+
+ #
+ # The version constraint required to activate a given gem.
+ # Usually the gem version requirement is "> 0," because any version
+ # will do. In the case of jekyll-docs, however, we require the exact
+ # same version as Jekyll.
+ #
+ # Returns a String version constraint in a parseable form for
+ # RubyGems.
+ def version_constraint(gem_name)
+ return "= #{Jekyll::VERSION}" if gem_name.to_s.eql?("jekyll-docs")
+
+ "> 0"
+ end
+
+ #
+ # Require a gem or gems. If it's not present, show a very nice error
+ # message that explains everything and is much more helpful than the
+ # normal LoadError.
+ #
+ # names - a string gem name or array of gem names
+ #
+ def require_with_graceful_fail(names)
+ Array(names).each do |name|
+ Jekyll.logger.debug "Requiring:", name.to_s
+ require name
+ rescue LoadError => e
+ Jekyll.logger.error "Dependency Error:", <<~MSG
+ Yikes! It looks like you don't have #{name} or one of its dependencies installed.
+ In order to use Jekyll as currently configured, you'll need to install this gem.
+
+ If you've run Jekyll with `bundle exec`, ensure that you have included the #{name}
+ gem in your Gemfile as well.
+
+ The full error message from Ruby is: '#{e.message}'
+
+ If you run into trouble, you can find helpful resources at https://jekyllrb.com/help/!
+ MSG
+ raise Jekyll::Errors::MissingDependencyException, name
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters.rb
new file mode 100644
index 0000000..7a79eec
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters.rb
@@ -0,0 +1,540 @@
+# frozen_string_literal: true
+
+require_all "jekyll/filters"
+
+module Jekyll
+ module Filters
+ include URLFilters
+ include GroupingFilters
+ include DateFilters
+
+ # Convert a Markdown string into HTML output.
+ #
+ # input - The Markdown String to convert.
+ #
+ # Returns the HTML formatted String.
+ def markdownify(input)
+ @context.registers[:site].find_converter_instance(
+ Jekyll::Converters::Markdown
+ ).convert(input.to_s)
+ end
+
+ # Convert quotes into smart quotes.
+ #
+ # input - The String to convert.
+ #
+ # Returns the smart-quotified String.
+ def smartify(input)
+ @context.registers[:site].find_converter_instance(
+ Jekyll::Converters::SmartyPants
+ ).convert(input.to_s)
+ end
+
+ # Convert a Sass string into CSS output.
+ #
+ # input - The Sass String to convert.
+ #
+ # Returns the CSS formatted String.
+ def sassify(input)
+ @context.registers[:site].find_converter_instance(
+ Jekyll::Converters::Sass
+ ).convert(input)
+ end
+
+ # Convert a Scss string into CSS output.
+ #
+ # input - The Scss String to convert.
+ #
+ # Returns the CSS formatted String.
+ def scssify(input)
+ @context.registers[:site].find_converter_instance(
+ Jekyll::Converters::Scss
+ ).convert(input)
+ end
+
+ # Slugify a filename or title.
+ #
+ # input - The filename or title to slugify.
+ # mode - how string is slugified
+ #
+ # Returns the given filename or title as a lowercase URL String.
+ # See Utils.slugify for more detail.
+ def slugify(input, mode = nil)
+ Utils.slugify(input, :mode => mode)
+ end
+
+ # XML escape a string for use. Replaces any special characters with
+ # appropriate HTML entity replacements.
+ #
+ # input - The String to escape.
+ #
+ # Examples
+ #
+ # xml_escape('foo "bar" <baz>')
+ # # => "foo &quot;bar&quot; &lt;baz&gt;"
+ #
+ # Returns the escaped String.
+ def xml_escape(input)
+ input.to_s.encode(:xml => :attr).gsub(%r!\A"|"\Z!, "")
+ end
+
+ # CGI escape a string for use in a URL. Replaces any special characters
+ # with appropriate %XX replacements.
+ #
+ # input - The String to escape.
+ #
+ # Examples
+ #
+ # cgi_escape('foo,bar;baz?')
+ # # => "foo%2Cbar%3Bbaz%3F"
+ #
+ # Returns the escaped String.
+ def cgi_escape(input)
+ CGI.escape(input)
+ end
+
+ # URI escape a string.
+ #
+ # input - The String to escape.
+ #
+ # Examples
+ #
+ # uri_escape('foo, bar \\baz?')
+ # # => "foo,%20bar%20%5Cbaz?"
+ #
+ # Returns the escaped String.
+ def uri_escape(input)
+ Addressable::URI.normalize_component(input)
+ end
+
+ # Replace any whitespace in the input string with a single space
+ #
+ # input - The String on which to operate.
+ #
+ # Returns the formatted String
+ def normalize_whitespace(input)
+ input.to_s.gsub(%r!\s+!, " ").tap(&:strip!)
+ end
+
+ # Count the number of words in the input string.
+ #
+ # input - The String on which to operate.
+ #
+ # Returns the Integer word count.
+ def number_of_words(input, mode = nil)
+ cjk_charset = '\p{Han}\p{Katakana}\p{Hiragana}\p{Hangul}'
+ cjk_regex = %r![#{cjk_charset}]!o
+ word_regex = %r![^#{cjk_charset}\s]+!o
+
+ case mode
+ when "cjk"
+ input.scan(cjk_regex).length + input.scan(word_regex).length
+ when "auto"
+ cjk_count = input.scan(cjk_regex).length
+ cjk_count.zero? ? input.split.length : cjk_count + input.scan(word_regex).length
+ else
+ input.split.length
+ end
+ end
+
+ # Join an array of things into a string by separating with commas and the
+ # word "and" for the last one.
+ #
+ # array - The Array of Strings to join.
+ # connector - Word used to connect the last 2 items in the array
+ #
+ # Examples
+ #
+ # array_to_sentence_string(["apples", "oranges", "grapes"])
+ # # => "apples, oranges, and grapes"
+ #
+ # Returns the formatted String.
+ def array_to_sentence_string(array, connector = "and")
+ case array.length
+ when 0
+ ""
+ when 1
+ array[0].to_s
+ when 2
+ "#{array[0]} #{connector} #{array[1]}"
+ else
+ "#{array[0...-1].join(", ")}, #{connector} #{array[-1]}"
+ end
+ end
+
+ # Convert the input into json string
+ #
+ # input - The Array or Hash to be converted
+ #
+ # Returns the converted json string
+ def jsonify(input)
+ as_liquid(input).to_json
+ end
+
+ # Filter an array of objects
+ #
+ # input - the object array.
+ # property - the property within each object to filter by.
+ # value - the desired value.
+ # Cannot be an instance of Array nor Hash since calling #to_s on them returns
+ # their `#inspect` string object.
+ #
+ # Returns the filtered array of objects
+ def where(input, property, value)
+ return input if !property || value.is_a?(Array) || value.is_a?(Hash)
+ return input unless input.respond_to?(:select)
+
+ input = input.values if input.is_a?(Hash)
+ input_id = input.hash
+
+ # implement a hash based on method parameters to cache the end-result
+ # for given parameters.
+ @where_filter_cache ||= {}
+ @where_filter_cache[input_id] ||= {}
+ @where_filter_cache[input_id][property] ||= {}
+
+ # stash or retrieve results to return
+ @where_filter_cache[input_id][property][value] ||= input.select do |object|
+ compare_property_vs_target(item_property(object, property), value)
+ end.to_a
+ end
+
+ # Filters an array of objects against an expression
+ #
+ # input - the object array
+ # variable - the variable to assign each item to in the expression
+ # expression - a Liquid comparison expression passed in as a string
+ #
+ # Returns the filtered array of objects
+ def where_exp(input, variable, expression)
+ return input unless input.respond_to?(:select)
+
+ input = input.values if input.is_a?(Hash) # FIXME
+
+ condition = parse_condition(expression)
+ @context.stack do
+ input.select do |object|
+ @context[variable] = object
+ condition.evaluate(@context)
+ end
+ end || []
+ end
+
+ # Search an array of objects and returns the first object that has the queried attribute
+ # with the given value or returns nil otherwise.
+ #
+ # input - the object array.
+ # property - the property within each object to search by.
+ # value - the desired value.
+ # Cannot be an instance of Array nor Hash since calling #to_s on them returns
+ # their `#inspect` string object.
+ #
+ # Returns the found object or nil
+ #
+ # rubocop:disable Metrics/CyclomaticComplexity
+ def find(input, property, value)
+ return input if !property || value.is_a?(Array) || value.is_a?(Hash)
+ return input unless input.respond_to?(:find)
+
+ input = input.values if input.is_a?(Hash)
+ input_id = input.hash
+
+ # implement a hash based on method parameters to cache the end-result for given parameters.
+ @find_filter_cache ||= {}
+ @find_filter_cache[input_id] ||= {}
+ @find_filter_cache[input_id][property] ||= {}
+
+ # stash or retrieve results to return
+ # Since `enum.find` can return nil or false, we use a placeholder string "<__NO MATCH__>"
+ # to validate caching.
+ result = @find_filter_cache[input_id][property][value] ||= input.find do |object|
+ compare_property_vs_target(item_property(object, property), value)
+ end || "<__NO MATCH__>"
+
+ return nil if result == "<__NO MATCH__>"
+
+ result
+ end
+ # rubocop:enable Metrics/CyclomaticComplexity
+
+ # Searches an array of objects against an expression and returns the first object for which
+ # the expression evaluates to true, or returns nil otherwise.
+ #
+ # input - the object array
+ # variable - the variable to assign each item to in the expression
+ # expression - a Liquid comparison expression passed in as a string
+ #
+ # Returns the found object or nil
+ def find_exp(input, variable, expression)
+ return input unless input.respond_to?(:find)
+
+ input = input.values if input.is_a?(Hash)
+
+ condition = parse_condition(expression)
+ @context.stack do
+ input.find do |object|
+ @context[variable] = object
+ condition.evaluate(@context)
+ end
+ end
+ end
+
+ # Convert the input into integer
+ #
+ # input - the object string
+ #
+ # Returns the integer value
+ def to_integer(input)
+ return 1 if input == true
+ return 0 if input == false
+
+ input.to_i
+ end
+
+ # Sort an array of objects
+ #
+ # input - the object array
+ # property - property within each object to filter by
+ # nils ('first' | 'last') - nils appear before or after non-nil values
+ #
+ # Returns the filtered array of objects
+ def sort(input, property = nil, nils = "first")
+ raise ArgumentError, "Cannot sort a null object." if input.nil?
+
+ if property.nil?
+ input.sort
+ else
+ case nils
+ when "first"
+ order = - 1
+ when "last"
+ order = + 1
+ else
+ raise ArgumentError, "Invalid nils order: " \
+ "'#{nils}' is not a valid nils order. It must be 'first' or 'last'."
+ end
+
+ sort_input(input, property, order)
+ end
+ end
+
+ def pop(array, num = 1)
+ return array unless array.is_a?(Array)
+
+ num = Liquid::Utils.to_integer(num)
+ new_ary = array.dup
+ new_ary.pop(num)
+ new_ary
+ end
+
+ def push(array, input)
+ return array unless array.is_a?(Array)
+
+ new_ary = array.dup
+ new_ary.push(input)
+ new_ary
+ end
+
+ def shift(array, num = 1)
+ return array unless array.is_a?(Array)
+
+ num = Liquid::Utils.to_integer(num)
+ new_ary = array.dup
+ new_ary.shift(num)
+ new_ary
+ end
+
+ def unshift(array, input)
+ return array unless array.is_a?(Array)
+
+ new_ary = array.dup
+ new_ary.unshift(input)
+ new_ary
+ end
+
+ def sample(input, num = 1)
+ return input unless input.respond_to?(:sample)
+
+ num = Liquid::Utils.to_integer(num) rescue 1
+ if num == 1
+ input.sample
+ else
+ input.sample(num)
+ end
+ end
+
+ # Convert an object into its String representation for debugging
+ #
+ # input - The Object to be converted
+ #
+ # Returns a String representation of the object.
+ def inspect(input)
+ xml_escape(input.inspect)
+ end
+
+ private
+
+ # Sort the input Enumerable by the given property.
+ # If the property doesn't exist, return the sort order respective of
+ # which item doesn't have the property.
+ # We also utilize the Schwartzian transform to make this more efficient.
+ def sort_input(input, property, order)
+ input.map { |item| [item_property(item, property), item] }
+ .sort! do |a_info, b_info|
+ a_property = a_info.first
+ b_property = b_info.first
+
+ if !a_property.nil? && b_property.nil?
+ - order
+ elsif a_property.nil? && !b_property.nil?
+ + order
+ else
+ a_property <=> b_property || a_property.to_s <=> b_property.to_s
+ end
+ end
+ .map!(&:last)
+ end
+
+ # `where` filter helper
+ #
+ def compare_property_vs_target(property, target)
+ case target
+ when NilClass
+ return true if property.nil?
+ when Liquid::Expression::MethodLiteral # `empty` or `blank`
+ target = target.to_s
+ return true if property == target || Array(property).join == target
+ else
+ target = target.to_s
+ if property.is_a? String
+ return true if property == target
+ else
+ Array(property).each do |prop|
+ return true if prop.to_s == target
+ end
+ end
+ end
+
+ false
+ end
+
+ def item_property(item, property)
+ @item_property_cache ||= @context.registers[:site].filter_cache[:item_property] ||= {}
+ @item_property_cache[property] ||= {}
+ @item_property_cache[property][item] ||= begin
+ property = property.to_s
+ property = if item.respond_to?(:to_liquid)
+ read_liquid_attribute(item.to_liquid, property)
+ elsif item.respond_to?(:data)
+ item.data[property]
+ else
+ item[property]
+ end
+
+ parse_sort_input(property)
+ end
+ end
+
+ def read_liquid_attribute(liquid_data, property)
+ return liquid_data[property] unless property.include?(".")
+
+ property.split(".").reduce(liquid_data) do |data, key|
+ data.respond_to?(:[]) && data[key]
+ end
+ rescue TypeError => e
+ msg = if liquid_data.is_a?(Array)
+ "Error accessing object (#{liquid_data.to_s[0...20]}) with given key. Expected an " \
+ "integer but got #{property.inspect} instead."
+ else
+ e.message
+ end
+ raise e, msg
+ end
+
+ FLOAT_LIKE = %r!\A\s*-?(?:\d+\.?\d*|\.\d+)\s*\Z!.freeze
+ INTEGER_LIKE = %r!\A\s*-?\d+\s*\Z!.freeze
+ private_constant :FLOAT_LIKE, :INTEGER_LIKE
+
+ # return numeric values as numbers for proper sorting
+ def parse_sort_input(property)
+ stringified = property.to_s
+ return property.to_i if INTEGER_LIKE.match?(stringified)
+ return property.to_f if FLOAT_LIKE.match?(stringified)
+
+ property
+ end
+
+ def as_liquid(item)
+ case item
+ when Hash
+ item.each_with_object({}) { |(k, v), result| result[as_liquid(k)] = as_liquid(v) }
+ when Array
+ item.map { |i| as_liquid(i) }
+ else
+ if item.respond_to?(:to_liquid)
+ liquidated = item.to_liquid
+ # prevent infinite recursion for simple types (which return `self`)
+ if liquidated == item
+ item
+ else
+ as_liquid(liquidated)
+ end
+ else
+ item
+ end
+ end
+ end
+
+ # ----------- The following set of code was *adapted* from Liquid::If
+ # ----------- ref: https://github.com/Shopify/liquid/blob/ffb0ace30315bbcf3548a0383fab531452060ae8/lib/liquid/tags/if.rb#L84-L107
+
+ # Parse a string to a Liquid Condition
+ def parse_condition(exp)
+ parser = Liquid::Parser.new(exp)
+ condition = parse_binary_comparison(parser)
+
+ parser.consume(:end_of_string)
+ condition
+ end
+
+ # Generate a Liquid::Condition object from a Liquid::Parser object additionally processing
+ # the parsed expression based on whether the expression consists of binary operations with
+ # Liquid operators `and` or `or`
+ #
+ # - parser: an instance of Liquid::Parser
+ #
+ # Returns an instance of Liquid::Condition
+ def parse_binary_comparison(parser)
+ condition = parse_comparison(parser)
+ first_condition = condition
+ while (binary_operator = parser.id?("and") || parser.id?("or"))
+ child_condition = parse_comparison(parser)
+ condition.send(binary_operator, child_condition)
+ condition = child_condition
+ end
+ first_condition
+ end
+
+ # Generates a Liquid::Condition object from a Liquid::Parser object based on whether the parsed
+ # expression involves a "comparison" operator (e.g. <, ==, >, !=, etc)
+ #
+ # - parser: an instance of Liquid::Parser
+ #
+ # Returns an instance of Liquid::Condition
+ def parse_comparison(parser)
+ left_operand = Liquid::Expression.parse(parser.expression)
+ operator = parser.consume?(:comparison)
+
+ # No comparison-operator detected. Initialize a Liquid::Condition using only left operand
+ return Liquid::Condition.new(left_operand) unless operator
+
+ # Parse what remained after extracting the left operand and the `:comparison` operator
+ # and initialize a Liquid::Condition object using the operands and the comparison-operator
+ Liquid::Condition.new(left_operand, operator, Liquid::Expression.parse(parser.expression))
+ end
+ end
+end
+
+Liquid::Template.register_filter(
+ Jekyll::Filters
+)
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters/date_filters.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters/date_filters.rb
new file mode 100644
index 0000000..966b49b
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters/date_filters.rb
@@ -0,0 +1,110 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Filters
+ module DateFilters
+ # Format a date in short format e.g. "27 Jan 2011".
+ # Ordinal format is also supported, in both the UK
+ # (e.g. "27th Jan 2011") and US ("e.g. Jan 27th, 2011") formats.
+ # UK format is the default.
+ #
+ # date - the Time to format.
+ # type - if "ordinal" the returned String will be in ordinal format
+ # style - if "US" the returned String will be in US format.
+ # Otherwise it will be in UK format.
+ #
+ # Returns the formatting String.
+ def date_to_string(date, type = nil, style = nil)
+ stringify_date(date, "%b", type, style)
+ end
+
+ # Format a date in long format e.g. "27 January 2011".
+ # Ordinal format is also supported, in both the UK
+ # (e.g. "27th January 2011") and US ("e.g. January 27th, 2011") formats.
+ # UK format is the default.
+ #
+ # date - the Time to format.
+ # type - if "ordinal" the returned String will be in ordinal format
+ # style - if "US" the returned String will be in US format.
+ # Otherwise it will be in UK format.
+ #
+ # Returns the formatted String.
+ def date_to_long_string(date, type = nil, style = nil)
+ stringify_date(date, "%B", type, style)
+ end
+
+ # Format a date for use in XML.
+ #
+ # date - The Time to format.
+ #
+ # Examples
+ #
+ # date_to_xmlschema(Time.now)
+ # # => "2011-04-24T20:34:46+08:00"
+ #
+ # Returns the formatted String.
+ def date_to_xmlschema(date)
+ return date if date.to_s.empty?
+
+ time(date).xmlschema
+ end
+
+ # Format a date according to RFC-822
+ #
+ # date - The Time to format.
+ #
+ # Examples
+ #
+ # date_to_rfc822(Time.now)
+ # # => "Sun, 24 Apr 2011 12:34:46 +0000"
+ #
+ # Returns the formatted String.
+ def date_to_rfc822(date)
+ return date if date.to_s.empty?
+
+ time(date).rfc822
+ end
+
+ private
+
+ # month_type: Notations that evaluate to 'Month' via `Time#strftime` ("%b", "%B")
+ # type: nil (default) or "ordinal"
+ # style: nil (default) or "US"
+ #
+ # Returns a stringified date or the empty input.
+ def stringify_date(date, month_type, type = nil, style = nil)
+ return date if date.to_s.empty?
+
+ time = time(date)
+ if type == "ordinal"
+ day = time.day
+ ordinal_day = "#{day}#{ordinal(day)}"
+ return time.strftime("#{month_type} #{ordinal_day}, %Y") if style == "US"
+
+ return time.strftime("#{ordinal_day} #{month_type} %Y")
+ end
+ time.strftime("%d #{month_type} %Y")
+ end
+
+ def ordinal(number)
+ return "th" if (11..13).cover?(number)
+
+ case number % 10
+ when 1 then "st"
+ when 2 then "nd"
+ when 3 then "rd"
+ else "th"
+ end
+ end
+
+ def time(input)
+ date = Liquid::Utils.to_date(input)
+ unless date.respond_to?(:to_time)
+ raise Errors::InvalidDateError,
+ "Invalid Date: '#{input.inspect}' is not a valid datetime."
+ end
+ date.to_time.dup.localtime
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters/grouping_filters.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters/grouping_filters.rb
new file mode 100644
index 0000000..c9cdc65
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters/grouping_filters.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Filters
+ module GroupingFilters
+ # Group an array of items by a property
+ #
+ # input - the inputted Enumerable
+ # property - the property
+ #
+ # Returns an array of Hashes, each looking something like this:
+ # {"name" => "larry"
+ # "items" => [...] } # all the items where `property` == "larry"
+ def group_by(input, property)
+ if groupable?(input)
+ groups = input.group_by { |item| item_property(item, property).to_s }
+ grouped_array(groups)
+ else
+ input
+ end
+ end
+
+ # Group an array of items by an expression
+ #
+ # input - the object array
+ # variable - the variable to assign each item to in the expression
+ # expression -a Liquid comparison expression passed in as a string
+ #
+ # Returns the filtered array of objects
+ def group_by_exp(input, variable, expression)
+ return input unless groupable?(input)
+
+ parsed_expr = parse_expression(expression)
+ @context.stack do
+ groups = input.group_by do |item|
+ @context[variable] = item
+ parsed_expr.render(@context)
+ end
+ grouped_array(groups)
+ end
+ end
+
+ private
+
+ def parse_expression(str)
+ Liquid::Variable.new(str, Liquid::ParseContext.new)
+ end
+
+ def groupable?(element)
+ element.respond_to?(:group_by)
+ end
+
+ def grouped_array(groups)
+ groups.each_with_object([]) do |item, array|
+ array << {
+ "name" => item.first,
+ "items" => item.last,
+ "size" => item.last.size,
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters/url_filters.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters/url_filters.rb
new file mode 100644
index 0000000..aa28c5a
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/filters/url_filters.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Filters
+ module URLFilters
+ # Produces an absolute URL based on site.url and site.baseurl.
+ #
+ # input - the URL to make absolute.
+ #
+ # Returns the absolute URL as a String.
+ def absolute_url(input)
+ return if input.nil?
+
+ cache = if input.is_a?(String)
+ (@context.registers[:site].filter_cache[:absolute_url] ||= {})
+ else
+ (@context.registers[:cached_absolute_url] ||= {})
+ end
+ cache[input] ||= compute_absolute_url(input)
+
+ # Duplicate cached string so that the cached value is never mutated by
+ # a subsequent filter.
+ cache[input].dup
+ end
+
+ # Produces a URL relative to the domain root based on site.baseurl
+ # unless it is already an absolute url with an authority (host).
+ #
+ # input - the URL to make relative to the domain root
+ #
+ # Returns a URL relative to the domain root as a String.
+ def relative_url(input)
+ return if input.nil?
+
+ cache = if input.is_a?(String)
+ (@context.registers[:site].filter_cache[:relative_url] ||= {})
+ else
+ (@context.registers[:cached_relative_url] ||= {})
+ end
+ cache[input] ||= compute_relative_url(input)
+
+ # Duplicate cached string so that the cached value is never mutated by
+ # a subsequent filter.
+ cache[input].dup
+ end
+
+ # Strips trailing `/index.html` from URLs to create pretty permalinks
+ #
+ # input - the URL with a possible `/index.html`
+ #
+ # Returns a URL with the trailing `/index.html` removed
+ def strip_index(input)
+ return if input.nil? || input.to_s.empty?
+
+ input.sub(%r!/index\.html?$!, "/")
+ end
+
+ private
+
+ def compute_absolute_url(input)
+ input = input.url if input.respond_to?(:url)
+ return input if Addressable::URI.parse(input.to_s).absolute?
+
+ site = @context.registers[:site]
+ site_url = site.config["url"]
+ return relative_url(input) if site_url.nil? || site_url == ""
+
+ Addressable::URI.parse(
+ site_url.to_s + relative_url(input)
+ ).normalize.to_s
+ end
+
+ def compute_relative_url(input)
+ input = input.url if input.respond_to?(:url)
+ return input if Addressable::URI.parse(input.to_s).absolute?
+
+ parts = [sanitized_baseurl, input]
+ Addressable::URI.parse(
+ parts.map! { |part| ensure_leading_slash(part.to_s) }.join
+ ).normalize.to_s
+ end
+
+ def sanitized_baseurl
+ site = @context.registers[:site]
+ baseurl = site.config["baseurl"]
+ return "" if baseurl.nil?
+
+ baseurl.to_s.chomp("/")
+ end
+
+ def ensure_leading_slash(input)
+ return input if input.nil? || input.empty? || input.start_with?("/")
+
+ "/#{input}"
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/frontmatter_defaults.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/frontmatter_defaults.rb
new file mode 100644
index 0000000..5ad896b
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/frontmatter_defaults.rb
@@ -0,0 +1,238 @@
+# frozen_string_literal: true
+
+module Jekyll
+ # This class handles custom defaults for YAML frontmatter settings.
+ # These are set in _config.yml and apply both to internal use (e.g. layout)
+ # and the data available to liquid.
+ #
+ # It is exposed via the frontmatter_defaults method on the site class.
+ class FrontmatterDefaults
+ # Initializes a new instance.
+ def initialize(site)
+ @site = site
+ end
+
+ def reset
+ @glob_cache = {} if @glob_cache
+ end
+
+ def update_deprecated_types(set)
+ return set unless set.key?("scope") && set["scope"].key?("type")
+
+ set["scope"]["type"] =
+ case set["scope"]["type"]
+ when "page"
+ Deprecator.defaults_deprecate_type("page", "pages")
+ "pages"
+ when "post"
+ Deprecator.defaults_deprecate_type("post", "posts")
+ "posts"
+ when "draft"
+ Deprecator.defaults_deprecate_type("draft", "drafts")
+ "drafts"
+ else
+ set["scope"]["type"]
+ end
+
+ set
+ end
+
+ def ensure_time!(set)
+ return set unless set.key?("values") && set["values"].key?("date")
+ return set if set["values"]["date"].is_a?(Time)
+
+ set["values"]["date"] = Utils.parse_date(
+ set["values"]["date"],
+ "An invalid date format was found in a front-matter default set: #{set}"
+ )
+ set
+ end
+
+ # Finds a default value for a given setting, filtered by path and type
+ #
+ # path - the path (relative to the source) of the page,
+ # post or :draft the default is used in
+ # type - a symbol indicating whether a :page,
+ # a :post or a :draft calls this method
+ #
+ # Returns the default value or nil if none was found
+ def find(path, type, setting)
+ value = nil
+ old_scope = nil
+
+ matching_sets(path, type).each do |set|
+ if set["values"].key?(setting) && has_precedence?(old_scope, set["scope"])
+ value = set["values"][setting]
+ old_scope = set["scope"]
+ end
+ end
+ value
+ end
+
+ # Collects a hash with all default values for a page or post
+ #
+ # path - the relative path of the page or post
+ # type - a symbol indicating the type (:post, :page or :draft)
+ #
+ # Returns a hash with all default values (an empty hash if there are none)
+ def all(path, type)
+ defaults = {}
+ old_scope = nil
+ matching_sets(path, type).each do |set|
+ if has_precedence?(old_scope, set["scope"])
+ defaults = Utils.deep_merge_hashes(defaults, set["values"])
+ old_scope = set["scope"]
+ else
+ defaults = Utils.deep_merge_hashes(set["values"], defaults)
+ end
+ end
+ defaults
+ end
+
+ private
+
+ # Checks if a given default setting scope matches the given path and type
+ #
+ # scope - the hash indicating the scope, as defined in _config.yml
+ # path - the path to check for
+ # type - the type (:post, :page or :draft) to check for
+ #
+ # Returns true if the scope applies to the given type and path
+ def applies?(scope, path, type)
+ applies_type?(scope, type) && applies_path?(scope, path)
+ end
+
+ def applies_path?(scope, path)
+ rel_scope_path = scope["path"]
+ return true if !rel_scope_path.is_a?(String) || rel_scope_path.empty?
+
+ sanitized_path = sanitize_path(path)
+
+ if rel_scope_path.include?("*")
+ glob_scope(sanitized_path, rel_scope_path)
+ else
+ path_is_subpath?(sanitized_path, strip_collections_dir(rel_scope_path))
+ end
+ end
+
+ def glob_scope(sanitized_path, rel_scope_path)
+ site_source = Pathname.new(@site.source)
+ abs_scope_path = site_source.join(rel_scope_path).to_s
+
+ glob_cache(abs_scope_path).each do |scope_path|
+ scope_path = Pathname.new(scope_path).relative_path_from(site_source).to_s
+ scope_path = strip_collections_dir(scope_path)
+ Jekyll.logger.debug "Globbed Scope Path:", scope_path
+ return true if path_is_subpath?(sanitized_path, scope_path)
+ end
+ false
+ end
+
+ def glob_cache(path)
+ @glob_cache ||= {}
+ @glob_cache[path] ||= Dir.glob(path)
+ end
+
+ def path_is_subpath?(path, parent_path)
+ path.start_with?(parent_path)
+ end
+
+ def strip_collections_dir(path)
+ collections_dir = @site.config["collections_dir"]
+ slashed_coll_dir = collections_dir.empty? ? "/" : "#{collections_dir}/"
+ return path if collections_dir.empty? || !path.to_s.start_with?(slashed_coll_dir)
+
+ path.sub(slashed_coll_dir, "")
+ end
+
+ # Determines whether the scope applies to type.
+ # The scope applies to the type if:
+ # 1. no 'type' is specified
+ # 2. the 'type' in the scope is the same as the type asked about
+ #
+ # scope - the Hash defaults set being asked about application
+ # type - the type of the document being processed / asked about
+ # its defaults.
+ #
+ # Returns true if either of the above conditions are satisfied,
+ # otherwise returns false
+ def applies_type?(scope, type)
+ !scope.key?("type") || type&.to_sym.eql?(scope["type"].to_sym)
+ end
+
+ # Checks if a given set of default values is valid
+ #
+ # set - the default value hash, as defined in _config.yml
+ #
+ # Returns true if the set is valid and can be used in this class
+ def valid?(set)
+ set.is_a?(Hash) && set["values"].is_a?(Hash)
+ end
+
+ # Determines if a new scope has precedence over an old one
+ #
+ # old_scope - the old scope hash, or nil if there's none
+ # new_scope - the new scope hash
+ #
+ # Returns true if the new scope has precedence over the older
+ # rubocop: disable Naming/PredicateName
+ def has_precedence?(old_scope, new_scope)
+ return true if old_scope.nil?
+
+ new_path = sanitize_path(new_scope["path"])
+ old_path = sanitize_path(old_scope["path"])
+
+ if new_path.length != old_path.length
+ new_path.length >= old_path.length
+ elsif new_scope.key?("type")
+ true
+ else
+ !old_scope.key? "type"
+ end
+ end
+ # rubocop: enable Naming/PredicateName
+
+ # Collects a list of sets that match the given path and type
+ #
+ # Returns an array of hashes
+ def matching_sets(path, type)
+ @matched_set_cache ||= {}
+ @matched_set_cache[path] ||= {}
+ @matched_set_cache[path][type] ||= valid_sets.select do |set|
+ !set.key?("scope") || applies?(set["scope"], path, type)
+ end
+ end
+
+ # Returns a list of valid sets
+ #
+ # This is not cached to allow plugins to modify the configuration
+ # and have their changes take effect
+ #
+ # Returns an array of hashes
+ def valid_sets
+ sets = @site.config["defaults"]
+ return [] unless sets.is_a?(Array)
+
+ sets.map do |set|
+ if valid?(set)
+ ensure_time!(update_deprecated_types(set))
+ else
+ Jekyll.logger.warn "Defaults:", "An invalid front-matter default set was found:"
+ Jekyll.logger.warn set.to_s
+ nil
+ end
+ end.tap(&:compact!)
+ end
+
+ # Sanitizes the given path by removing a leading slash
+ def sanitize_path(path)
+ if path.nil? || path.empty?
+ ""
+ elsif path.start_with?("/")
+ path.gsub(%r!\A/|(?<=[^/])\z!, "")
+ else
+ path
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/generator.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/generator.rb
new file mode 100644
index 0000000..649715f
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/generator.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+module Jekyll
+ Generator = Class.new(Plugin)
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/hooks.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/hooks.rb
new file mode 100644
index 0000000..482d802
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/hooks.rb
@@ -0,0 +1,107 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Hooks
+ DEFAULT_PRIORITY = 20
+
+ # compatibility layer for octopress-hooks users
+ PRIORITY_MAP = {
+ :low => 10,
+ :normal => 20,
+ :high => 30,
+ }.freeze
+
+ # initial empty hooks
+ @registry = {
+ :site => {
+ :after_init => [],
+ :after_reset => [],
+ :post_read => [],
+ :pre_render => [],
+ :post_render => [],
+ :post_write => [],
+ },
+ :pages => {
+ :post_init => [],
+ :pre_render => [],
+ :post_convert => [],
+ :post_render => [],
+ :post_write => [],
+ },
+ :posts => {
+ :post_init => [],
+ :pre_render => [],
+ :post_convert => [],
+ :post_render => [],
+ :post_write => [],
+ },
+ :documents => {
+ :post_init => [],
+ :pre_render => [],
+ :post_convert => [],
+ :post_render => [],
+ :post_write => [],
+ },
+ :clean => {
+ :on_obsolete => [],
+ },
+ }
+
+ # map of all hooks and their priorities
+ @hook_priority = {}
+
+ NotAvailable = Class.new(RuntimeError)
+ Uncallable = Class.new(RuntimeError)
+
+ # register hook(s) to be called later, public API
+ def self.register(owners, event, priority: DEFAULT_PRIORITY, &block)
+ Array(owners).each do |owner|
+ register_one(owner, event, priority_value(priority), &block)
+ end
+ end
+
+ # Ensure the priority is a Fixnum
+ def self.priority_value(priority)
+ return priority if priority.is_a?(Integer)
+
+ PRIORITY_MAP[priority] || DEFAULT_PRIORITY
+ end
+
+ # register a single hook to be called later, internal API
+ def self.register_one(owner, event, priority, &block)
+ @registry[owner] ||= {
+ :post_init => [],
+ :pre_render => [],
+ :post_convert => [],
+ :post_render => [],
+ :post_write => [],
+ }
+
+ unless @registry[owner][event]
+ raise NotAvailable, "Invalid hook. #{owner} supports only the following hooks " \
+ "#{@registry[owner].keys.inspect}"
+ end
+
+ raise Uncallable, "Hooks must respond to :call" unless block.respond_to? :call
+
+ insert_hook owner, event, priority, &block
+ end
+
+ def self.insert_hook(owner, event, priority, &block)
+ @hook_priority[block] = [-priority, @hook_priority.size]
+ @registry[owner][event] << block
+ end
+
+ # interface for Jekyll core components to trigger hooks
+ def self.trigger(owner, event, *args)
+ # proceed only if there are hooks to call
+ hooks = @registry.dig(owner, event)
+ return if hooks.nil? || hooks.empty?
+
+ # sort and call hooks according to priority and load order
+ hooks.sort_by { |h| @hook_priority[h] }.each do |hook|
+ hook.call(*args)
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/inclusion.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/inclusion.rb
new file mode 100644
index 0000000..179ddb0
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/inclusion.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Inclusion
+ attr_reader :site, :name, :path
+ private :site
+
+ def initialize(site, base, name)
+ @site = site
+ @name = name
+ @path = PathManager.join(base, name)
+ end
+
+ def render(context)
+ @template ||= site.liquid_renderer.file(path).parse(content)
+ @template.render!(context)
+ rescue Liquid::Error => e
+ e.template_name = path
+ e.markup_context = "included " if e.markup_context.nil?
+ raise e
+ end
+
+ def content
+ @content ||= File.read(path, **site.file_read_opts)
+ end
+
+ def inspect
+ "#{self.class} #{path.inspect}"
+ end
+ alias_method :to_s, :inspect
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/layout.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/layout.rb
new file mode 100644
index 0000000..af3ea71
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/layout.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Layout
+ include Convertible
+
+ attr_accessor :content, # content of layout
+ :data, # the Hash that holds the metadata for this layout
+ :ext # extension of layout
+
+ attr_reader :name, # name of layout
+ :path, # path to layout
+ :site, # the Site object
+ :relative_path # path to layout relative to its base
+
+ # Initialize a new Layout.
+ #
+ # site - The Site.
+ # base - The String path to the source.
+ # name - The String filename of the post file.
+ def initialize(site, base, name)
+ @site = site
+ @base = base
+ @name = name
+
+ if site.theme && site.theme.layouts_path.eql?(base)
+ @base_dir = site.theme.root
+ @path = site.in_theme_dir(base, name)
+ else
+ @base_dir = site.source
+ @path = site.in_source_dir(base, name)
+ end
+ @relative_path = @path.sub(@base_dir, "")
+
+ self.data = {}
+
+ process(name)
+ read_yaml(base, name)
+ end
+
+ # Extract information from the layout filename.
+ #
+ # name - The String filename of the layout file.
+ #
+ # Returns nothing.
+ def process(name)
+ self.ext = File.extname(name)
+ end
+
+ # Returns the object as a debug String.
+ def inspect
+ "#<#{self.class} @path=#{@path.inspect}>"
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_extensions.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_extensions.rb
new file mode 100644
index 0000000..87e06ef
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_extensions.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module LiquidExtensions
+ # Lookup a Liquid variable in the given context.
+ #
+ # context - the Liquid context in question.
+ # variable - the variable name, as a string.
+ #
+ # Returns the value of the variable in the context
+ # or the variable name if not found.
+ def lookup_variable(context, variable)
+ lookup = context
+
+ variable.split(".").each do |value|
+ lookup = lookup[value]
+ end
+
+ lookup || variable
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_renderer.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_renderer.rb
new file mode 100644
index 0000000..7655e04
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_renderer.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require_relative "liquid_renderer/file"
+require_relative "liquid_renderer/table"
+
+module Jekyll
+ class LiquidRenderer
+ def initialize(site)
+ @site = site
+ Liquid::Template.error_mode = @site.config["liquid"]["error_mode"].to_sym
+ reset
+ end
+
+ def reset
+ @stats = {}
+ @cache = {}
+ end
+
+ def file(filename)
+ filename = normalize_path(filename)
+ LiquidRenderer::File.new(self, filename).tap do
+ @stats[filename] ||= new_profile_hash
+ end
+ end
+
+ def increment_bytes(filename, bytes)
+ @stats[filename][:bytes] += bytes
+ end
+
+ def increment_time(filename, time)
+ @stats[filename][:time] += time
+ end
+
+ def increment_count(filename)
+ @stats[filename][:count] += 1
+ end
+
+ def stats_table(num_of_rows = 50)
+ LiquidRenderer::Table.new(@stats).to_s(num_of_rows)
+ end
+
+ def self.format_error(error, path)
+ "#{error.message} in #{path}"
+ end
+
+ # A persistent cache to store and retrieve parsed templates based on the filename
+ # via `LiquidRenderer::File#parse`
+ #
+ # It is emptied when `self.reset` is called.
+ def cache
+ @cache ||= {}
+ end
+
+ private
+
+ def normalize_path(filename)
+ @normalize_path ||= {}
+ @normalize_path[filename] ||= begin
+ theme_dir = @site.theme&.root
+ case filename
+ when %r!\A(#{Regexp.escape(@site.source)}/)(?<rest>.*)!io
+ Regexp.last_match(:rest)
+ when %r!(/gems/.*)*/gems/(?<dirname>[^/]+)(?<rest>.*)!,
+ %r!(?<dirname>[^/]+/lib)(?<rest>.*)!
+ "#{Regexp.last_match(:dirname)}#{Regexp.last_match(:rest)}"
+ when theme_dir && %r!\A#{Regexp.escape(theme_dir)}/(?<rest>.*)!io
+ PathManager.join(@site.theme.basename, Regexp.last_match(:rest))
+ when %r!\A/(.*)!
+ Regexp.last_match(1)
+ else
+ filename
+ end
+ end
+ end
+
+ def new_profile_hash
+ Hash.new { |hash, key| hash[key] = 0 }
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_renderer/file.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_renderer/file.rb
new file mode 100644
index 0000000..146c416
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_renderer/file.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class LiquidRenderer
+ class File
+ def initialize(renderer, filename)
+ @renderer = renderer
+ @filename = filename
+ end
+
+ def parse(content)
+ measure_time do
+ @renderer.cache[@filename] ||= Liquid::Template.parse(content, :line_numbers => true)
+ end
+ @template = @renderer.cache[@filename]
+
+ self
+ end
+
+ def render(*args)
+ reset_template_assigns
+
+ measure_time do
+ measure_bytes do
+ measure_counts do
+ @template.render(*args)
+ end
+ end
+ end
+ end
+
+ # This method simply 'rethrows any error' before attempting to render the template.
+ def render!(*args)
+ reset_template_assigns
+
+ measure_time do
+ measure_bytes do
+ measure_counts do
+ @template.render!(*args)
+ end
+ end
+ end
+ end
+
+ def warnings
+ @template.warnings
+ end
+
+ private
+
+ # clear assigns to `Liquid::Template` instance prior to rendering since
+ # `Liquid::Template` instances are cached in Jekyll 4.
+ def reset_template_assigns
+ @template.instance_assigns.clear
+ end
+
+ def measure_counts
+ @renderer.increment_count(@filename)
+ yield
+ end
+
+ def measure_bytes
+ yield.tap do |str|
+ @renderer.increment_bytes(@filename, str.bytesize)
+ end
+ end
+
+ def measure_time
+ before = Time.now
+ yield
+ ensure
+ after = Time.now
+ @renderer.increment_time(@filename, after - before)
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_renderer/table.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_renderer/table.rb
new file mode 100644
index 0000000..2d06a26
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/liquid_renderer/table.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class LiquidRenderer
+ class Table
+ GAUGES = [:count, :bytes, :time].freeze
+
+ def initialize(stats)
+ @stats = stats
+ end
+
+ def to_s(num_of_rows = 50)
+ Jekyll::Profiler.tabulate(data_for_table(num_of_rows))
+ end
+
+ private
+
+ def data_for_table(num_of_rows)
+ sorted = @stats.sort_by { |_, file_stats| -file_stats[:time] }
+ sorted = sorted.slice(0, num_of_rows)
+
+ table = [header_labels]
+ sorted.each do |filename, file_stats|
+ row = []
+ row << filename
+ row << file_stats[:count].to_s
+ row << format_bytes(file_stats[:bytes])
+ row << format("%.3f", file_stats[:time])
+ table << row
+ end
+
+ table
+ end
+
+ def header_labels
+ GAUGES.map { |gauge| gauge.to_s.capitalize }.unshift("Filename")
+ end
+
+ def format_bytes(bytes)
+ bytes /= 1024.0
+ format("%.2fK", bytes)
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/log_adapter.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/log_adapter.rb
new file mode 100644
index 0000000..6ddfa4a
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/log_adapter.rb
@@ -0,0 +1,151 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class LogAdapter
+ attr_reader :writer, :messages, :level
+
+ LOG_LEVELS = {
+ :debug => ::Logger::DEBUG,
+ :info => ::Logger::INFO,
+ :warn => ::Logger::WARN,
+ :error => ::Logger::ERROR,
+ }.freeze
+
+ # Public: Create a new instance of a log writer
+ #
+ # writer - Logger compatible instance
+ # log_level - (optional, symbol) the log level
+ #
+ # Returns nothing
+ def initialize(writer, level = :info)
+ @messages = []
+ @writer = writer
+ self.log_level = level
+ end
+
+ # Public: Set the log level on the writer
+ #
+ # level - (symbol) the log level
+ #
+ # Returns nothing
+ def log_level=(level)
+ writer.level = level if level.is_a?(Integer) && level.between?(0, 3)
+ writer.level = LOG_LEVELS[level] ||
+ raise(ArgumentError, "unknown log level")
+ @level = level
+ end
+
+ def adjust_verbosity(options = {})
+ # Quiet always wins.
+ if options[:quiet]
+ self.log_level = :error
+ elsif options[:verbose]
+ self.log_level = :debug
+ end
+ debug "Logging at level:", LOG_LEVELS.key(writer.level).to_s
+ debug "Jekyll Version:", Jekyll::VERSION
+ end
+
+ # Public: Print a debug message
+ #
+ # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
+ # message - the message detail
+ #
+ # Returns nothing
+ def debug(topic, message = nil, &block)
+ write(:debug, topic, message, &block)
+ end
+
+ # Public: Print a message
+ #
+ # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
+ # message - the message detail
+ #
+ # Returns nothing
+ def info(topic, message = nil, &block)
+ write(:info, topic, message, &block)
+ end
+
+ # Public: Print a message
+ #
+ # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
+ # message - the message detail
+ #
+ # Returns nothing
+ def warn(topic, message = nil, &block)
+ write(:warn, topic, message, &block)
+ end
+
+ # Public: Print an error message
+ #
+ # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
+ # message - the message detail
+ #
+ # Returns nothing
+ def error(topic, message = nil, &block)
+ write(:error, topic, message, &block)
+ end
+
+ # Public: Print an error message and immediately abort the process
+ #
+ # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
+ # message - the message detail (can be omitted)
+ #
+ # Returns nothing
+ def abort_with(topic, message = nil, &block)
+ error(topic, message, &block)
+ abort
+ end
+
+ # Internal: Build a topic method
+ #
+ # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
+ # message - the message detail
+ #
+ # Returns the formatted message
+ def message(topic, message = nil)
+ raise ArgumentError, "block or message, not both" if block_given? && message
+
+ message = yield if block_given?
+ message = message.to_s.gsub(%r!\s+!, " ")
+ topic = formatted_topic(topic, block_given?)
+ out = topic + message
+ messages << out
+ out
+ end
+
+ # Internal: Format the topic
+ #
+ # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
+ # colon -
+ #
+ # Returns the formatted topic statement
+ def formatted_topic(topic, colon = false)
+ "#{topic}#{colon ? ": " : " "}".rjust(20)
+ end
+
+ # Internal: Check if the message should be written given the log level.
+ #
+ # level_of_message - the Symbol level of message, one of :debug, :info, :warn, :error
+ #
+ # Returns whether the message should be written.
+ def write_message?(level_of_message)
+ LOG_LEVELS.fetch(level) <= LOG_LEVELS.fetch(level_of_message)
+ end
+
+ # Internal: Log a message.
+ #
+ # level_of_message - the Symbol level of message, one of :debug, :info, :warn, :error
+ # topic - the String topic or full message
+ # message - the String message (optional)
+ # block - a block containing the message (optional)
+ #
+ # Returns false if the message was not written, otherwise returns the value of calling
+ # the appropriate writer method, e.g. writer.info.
+ def write(level_of_message, topic, message = nil, &block)
+ return false unless write_message?(level_of_message)
+
+ writer.public_send(level_of_message, message(topic, message, &block))
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/mime.types b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/mime.types
new file mode 100644
index 0000000..10f713c
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/mime.types
@@ -0,0 +1,940 @@
+# Woah there. Do not edit this file directly.
+# This file is generated automatically by script/vendor-mimes.
+
+application/andrew-inset ez
+application/applixware aw
+application/atom+xml atom
+application/atomcat+xml atomcat
+application/atomdeleted+xml atomdeleted
+application/atomsvc+xml atomsvc
+application/atsc-dwd+xml dwd
+application/atsc-held+xml held
+application/atsc-rsat+xml rsat
+application/bdoc bdoc
+application/calendar+xml xcs
+application/ccxml+xml ccxml
+application/cdfx+xml cdfx
+application/cdmi-capability cdmia
+application/cdmi-container cdmic
+application/cdmi-domain cdmid
+application/cdmi-object cdmio
+application/cdmi-queue cdmiq
+application/cpl+xml cpl
+application/cu-seeme cu
+application/dash+xml mpd
+application/dash-patch+xml mpp
+application/davmount+xml davmount
+application/docbook+xml dbk
+application/dssc+der dssc
+application/dssc+xml xdssc
+application/ecmascript ecma es
+application/emma+xml emma
+application/emotionml+xml emotionml
+application/epub+zip epub
+application/exi exi
+application/express exp
+application/fdt+xml fdt
+application/font-tdpfr pfr
+application/geo+json geojson
+application/gml+xml gml
+application/gpx+xml gpx
+application/gxf gxf
+application/gzip gz
+application/hjson hjson
+application/hyperstudio stk
+application/inkml+xml ink inkml
+application/ipfix ipfix
+application/its+xml its
+application/java-archive ear jar war
+application/java-serialized-object ser
+application/java-vm class
+application/javascript js mjs
+application/json json map
+application/json5 json5
+application/jsonml+json jsonml
+application/ld+json jsonld
+application/lgr+xml lgr
+application/lost+xml lostxml
+application/mac-binhex40 hqx
+application/mac-compactpro cpt
+application/mads+xml mads
+application/manifest+json webmanifest
+application/marc mrc
+application/marcxml+xml mrcx
+application/mathematica ma mb nb
+application/mathml+xml mathml
+application/mbox mbox
+application/media-policy-dataset+xml mpf
+application/mediaservercontrol+xml mscml
+application/metalink+xml metalink
+application/metalink4+xml meta4
+application/mets+xml mets
+application/mmt-aei+xml maei
+application/mmt-usd+xml musd
+application/mods+xml mods
+application/mp21 m21 mp21
+application/mp4 m4p mp4s
+application/msword doc dot
+application/mxf mxf
+application/n-quads nq
+application/n-triples nt
+application/node cjs
+application/octet-stream bin bpk buffer deb deploy dist distz dll dmg dms dump elc exe img iso lrf mar msi msm msp pkg so
+application/oda oda
+application/oebps-package+xml opf
+application/ogg ogx
+application/omdoc+xml omdoc
+application/onenote onepkg onetmp onetoc onetoc2
+application/oxps oxps
+application/p2p-overlay+xml relo
+application/patch-ops-error+xml xer
+application/pdf pdf
+application/pgp-encrypted pgp
+application/pgp-keys asc
+application/pgp-signature sig
+application/pics-rules prf
+application/pkcs10 p10
+application/pkcs7-mime p7c p7m
+application/pkcs7-signature p7s
+application/pkcs8 p8
+application/pkix-attr-cert ac
+application/pkix-cert cer
+application/pkix-crl crl
+application/pkix-pkipath pkipath
+application/pkixcmp pki
+application/pls+xml pls
+application/postscript ai eps ps
+application/provenance+xml provx
+application/prs.cww cww
+application/pskc+xml pskcxml
+application/raml+yaml raml
+application/rdf+xml owl rdf
+application/reginfo+xml rif
+application/relax-ng-compact-syntax rnc
+application/resource-lists+xml rl
+application/resource-lists-diff+xml rld
+application/rls-services+xml rs
+application/route-apd+xml rapd
+application/route-s-tsid+xml sls
+application/route-usd+xml rusd
+application/rpki-ghostbusters gbr
+application/rpki-manifest mft
+application/rpki-roa roa
+application/rsd+xml rsd
+application/rss+xml rss
+application/rtf rtf
+application/sbml+xml sbml
+application/scvp-cv-request scq
+application/scvp-cv-response scs
+application/scvp-vp-request spq
+application/scvp-vp-response spp
+application/sdp sdp
+application/senml+xml senmlx
+application/sensml+xml sensmlx
+application/set-payment-initiation setpay
+application/set-registration-initiation setreg
+application/shf+xml shf
+application/sieve sieve siv
+application/smil+xml smi smil
+application/sparql-query rq
+application/sparql-results+xml srx
+application/srgs gram
+application/srgs+xml grxml
+application/sru+xml sru
+application/ssdl+xml ssdl
+application/ssml+xml ssml
+application/swid+xml swidtag
+application/tei+xml tei teicorpus
+application/thraud+xml tfi
+application/timestamped-data tsd
+application/toml toml
+application/trig trig
+application/ttml+xml ttml
+application/ubjson ubj
+application/urc-ressheet+xml rsheet
+application/urc-targetdesc+xml td
+application/vnd.1000minds.decision-model+xml 1km
+application/vnd.3gpp.pic-bw-large plb
+application/vnd.3gpp.pic-bw-small psb
+application/vnd.3gpp.pic-bw-var pvb
+application/vnd.3gpp2.tcap tcap
+application/vnd.3m.post-it-notes pwn
+application/vnd.accpac.simply.aso aso
+application/vnd.accpac.simply.imp imp
+application/vnd.acucobol acu
+application/vnd.acucorp acutc atc
+application/vnd.adobe.air-application-installer-package+zip air
+application/vnd.adobe.formscentral.fcdt fcdt
+application/vnd.adobe.fxp fxp fxpl
+application/vnd.adobe.xdp+xml xdp
+application/vnd.adobe.xfdf xfdf
+application/vnd.age age
+application/vnd.ahead.space ahead
+application/vnd.airzip.filesecure.azf azf
+application/vnd.airzip.filesecure.azs azs
+application/vnd.amazon.ebook azw
+application/vnd.americandynamics.acc acc
+application/vnd.amiga.ami ami
+application/vnd.android.package-archive apk
+application/vnd.anser-web-certificate-issue-initiation cii
+application/vnd.anser-web-funds-transfer-initiation fti
+application/vnd.antix.game-component atx
+application/vnd.apple.installer+xml mpkg
+application/vnd.apple.keynote key
+application/vnd.apple.mpegurl m3u8
+application/vnd.apple.numbers numbers
+application/vnd.apple.pages pages
+application/vnd.apple.pkpass pkpass
+application/vnd.aristanetworks.swi swi
+application/vnd.astraea-software.iota iota
+application/vnd.audiograph aep
+application/vnd.balsamiq.bmml+xml bmml
+application/vnd.blueice.multipass mpm
+application/vnd.bmi bmi
+application/vnd.businessobjects rep
+application/vnd.chemdraw+xml cdxml
+application/vnd.chipnuts.karaoke-mmd mmd
+application/vnd.cinderella cdy
+application/vnd.citationstyles.style+xml csl
+application/vnd.claymore cla
+application/vnd.cloanto.rp9 rp9
+application/vnd.clonk.c4group c4d c4f c4g c4p c4u
+application/vnd.cluetrust.cartomobile-config c11amc
+application/vnd.cluetrust.cartomobile-config-pkg c11amz
+application/vnd.commonspace csp
+application/vnd.contact.cmsg cdbcmsg
+application/vnd.cosmocaller cmc
+application/vnd.crick.clicker clkx
+application/vnd.crick.clicker.keyboard clkk
+application/vnd.crick.clicker.palette clkp
+application/vnd.crick.clicker.template clkt
+application/vnd.crick.clicker.wordbank clkw
+application/vnd.criticaltools.wbs+xml wbs
+application/vnd.ctc-posml pml
+application/vnd.cups-ppd ppd
+application/vnd.curl.car car
+application/vnd.curl.pcurl pcurl
+application/vnd.dart dart
+application/vnd.data-vision.rdz rdz
+application/vnd.dbf dbf
+application/vnd.dece.data uvd uvf uvvd uvvf
+application/vnd.dece.ttml+xml uvt uvvt
+application/vnd.dece.unspecified uvvx uvx
+application/vnd.dece.zip uvvz uvz
+application/vnd.denovo.fcselayout-link fe_launch
+application/vnd.dna dna
+application/vnd.dolby.mlp mlp
+application/vnd.dpgraph dpg
+application/vnd.dreamfactory dfac
+application/vnd.ds-keypoint kpxx
+application/vnd.dvb.ait ait
+application/vnd.dvb.service svc
+application/vnd.dynageo geo
+application/vnd.ecowin.chart mag
+application/vnd.enliven nml
+application/vnd.epson.esf esf
+application/vnd.epson.msf msf
+application/vnd.epson.quickanime qam
+application/vnd.epson.salt slt
+application/vnd.epson.ssf ssf
+application/vnd.eszigno3+xml es3 et3
+application/vnd.ezpix-album ez2
+application/vnd.ezpix-package ez3
+application/vnd.fdf fdf
+application/vnd.fdsn.mseed mseed
+application/vnd.fdsn.seed dataless seed
+application/vnd.flographit gph
+application/vnd.fluxtime.clip ftc
+application/vnd.framemaker book fm frame maker
+application/vnd.frogans.fnc fnc
+application/vnd.frogans.ltf ltf
+application/vnd.fsc.weblaunch fsc
+application/vnd.fujitsu.oasys oas
+application/vnd.fujitsu.oasys2 oa2
+application/vnd.fujitsu.oasys3 oa3
+application/vnd.fujitsu.oasysgp fg5
+application/vnd.fujitsu.oasysprs bh2
+application/vnd.fujixerox.ddd ddd
+application/vnd.fujixerox.docuworks xdw
+application/vnd.fujixerox.docuworks.binder xbd
+application/vnd.fuzzysheet fzs
+application/vnd.genomatix.tuxedo txd
+application/vnd.geogebra.file ggb
+application/vnd.geogebra.tool ggt
+application/vnd.geometry-explorer gex gre
+application/vnd.geonext gxt
+application/vnd.geoplan g2w
+application/vnd.geospace g3w
+application/vnd.gmx gmx
+application/vnd.google-apps.document gdoc
+application/vnd.google-apps.presentation gslides
+application/vnd.google-apps.spreadsheet gsheet
+application/vnd.google-earth.kml+xml kml
+application/vnd.google-earth.kmz kmz
+application/vnd.grafeq gqf gqs
+application/vnd.groove-account gac
+application/vnd.groove-help ghf
+application/vnd.groove-identity-message gim
+application/vnd.groove-injector grv
+application/vnd.groove-tool-message gtm
+application/vnd.groove-tool-template tpl
+application/vnd.groove-vcard vcg
+application/vnd.hal+xml hal
+application/vnd.handheld-entertainment+xml zmm
+application/vnd.hbci hbci
+application/vnd.hhe.lesson-player les
+application/vnd.hp-hpgl hpgl
+application/vnd.hp-hpid hpid
+application/vnd.hp-hps hps
+application/vnd.hp-jlyt jlt
+application/vnd.hp-pcl pcl
+application/vnd.hp-pclxl pclxl
+application/vnd.hydrostatix.sof-data sfd-hdstx
+application/vnd.ibm.minipay mpy
+application/vnd.ibm.modcap afp list3820 listafp
+application/vnd.ibm.rights-management irm
+application/vnd.ibm.secure-container sc
+application/vnd.iccprofile icc icm
+application/vnd.igloader igl
+application/vnd.immervision-ivp ivp
+application/vnd.immervision-ivu ivu
+application/vnd.insors.igm igm
+application/vnd.intercon.formnet xpw xpx
+application/vnd.intergeo i2g
+application/vnd.intu.qbo qbo
+application/vnd.intu.qfx qfx
+application/vnd.ipunplugged.rcprofile rcprofile
+application/vnd.irepository.package+xml irp
+application/vnd.is-xpr xpr
+application/vnd.isac.fcs fcs
+application/vnd.jam jam
+application/vnd.jcp.javame.midlet-rms rms
+application/vnd.jisp jisp
+application/vnd.joost.joda-archive joda
+application/vnd.kahootz ktr ktz
+application/vnd.kde.karbon karbon
+application/vnd.kde.kchart chrt
+application/vnd.kde.kformula kfo
+application/vnd.kde.kivio flw
+application/vnd.kde.kontour kon
+application/vnd.kde.kpresenter kpr kpt
+application/vnd.kde.kspread ksp
+application/vnd.kde.kword kwd kwt
+application/vnd.kenameaapp htke
+application/vnd.kidspiration kia
+application/vnd.kinar kne knp
+application/vnd.koan skd skm skp skt
+application/vnd.kodak-descriptor sse
+application/vnd.las.las+xml lasxml
+application/vnd.llamagraphics.life-balance.desktop lbd
+application/vnd.llamagraphics.life-balance.exchange+xml lbe
+application/vnd.lotus-1-2-3 123
+application/vnd.lotus-approach apr
+application/vnd.lotus-freelance pre
+application/vnd.lotus-notes nsf
+application/vnd.lotus-organizer org
+application/vnd.lotus-screencam scm
+application/vnd.lotus-wordpro lwp
+application/vnd.macports.portpkg portpkg
+application/vnd.mapbox-vector-tile mvt
+application/vnd.mcd mcd
+application/vnd.medcalcdata mc1
+application/vnd.mediastation.cdkey cdkey
+application/vnd.mfer mwf
+application/vnd.mfmp mfm
+application/vnd.micrografx.flo flo
+application/vnd.micrografx.igx igx
+application/vnd.mif mif
+application/vnd.mobius.daf daf
+application/vnd.mobius.dis dis
+application/vnd.mobius.mbk mbk
+application/vnd.mobius.mqy mqy
+application/vnd.mobius.msl msl
+application/vnd.mobius.plc plc
+application/vnd.mobius.txf txf
+application/vnd.mophun.application mpn
+application/vnd.mophun.certificate mpc
+application/vnd.mozilla.xul+xml xul
+application/vnd.ms-artgalry cil
+application/vnd.ms-cab-compressed cab
+application/vnd.ms-excel xla xlc xlm xls xlt xlw
+application/vnd.ms-excel.addin.macroenabled.12 xlam
+application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb
+application/vnd.ms-excel.sheet.macroenabled.12 xlsm
+application/vnd.ms-excel.template.macroenabled.12 xltm
+application/vnd.ms-fontobject eot
+application/vnd.ms-htmlhelp chm
+application/vnd.ms-ims ims
+application/vnd.ms-lrm lrm
+application/vnd.ms-officetheme thmx
+application/vnd.ms-outlook msg
+application/vnd.ms-pki.seccat cat
+application/vnd.ms-pki.stl stl
+application/vnd.ms-powerpoint pot pps ppt
+application/vnd.ms-powerpoint.addin.macroenabled.12 ppam
+application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm
+application/vnd.ms-powerpoint.slide.macroenabled.12 sldm
+application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm
+application/vnd.ms-powerpoint.template.macroenabled.12 potm
+application/vnd.ms-project mpt
+application/vnd.ms-word.document.macroenabled.12 docm
+application/vnd.ms-word.template.macroenabled.12 dotm
+application/vnd.ms-works wcm wdb wks wps
+application/vnd.ms-wpl wpl
+application/vnd.ms-xpsdocument xps
+application/vnd.mseq mseq
+application/vnd.musician mus
+application/vnd.muvee.style msty
+application/vnd.mynfc taglet
+application/vnd.neurolanguage.nlu nlu
+application/vnd.nitf nitf ntf
+application/vnd.noblenet-directory nnd
+application/vnd.noblenet-sealer nns
+application/vnd.noblenet-web nnw
+application/vnd.nokia.n-gage.data ngdat
+application/vnd.nokia.n-gage.symbian.install n-gage
+application/vnd.nokia.radio-preset rpst
+application/vnd.nokia.radio-presets rpss
+application/vnd.novadigm.edm edm
+application/vnd.novadigm.edx edx
+application/vnd.novadigm.ext ext
+application/vnd.oasis.opendocument.chart odc
+application/vnd.oasis.opendocument.chart-template otc
+application/vnd.oasis.opendocument.database odb
+application/vnd.oasis.opendocument.formula odf
+application/vnd.oasis.opendocument.formula-template odft
+application/vnd.oasis.opendocument.graphics odg
+application/vnd.oasis.opendocument.graphics-template otg
+application/vnd.oasis.opendocument.image odi
+application/vnd.oasis.opendocument.image-template oti
+application/vnd.oasis.opendocument.presentation odp
+application/vnd.oasis.opendocument.presentation-template otp
+application/vnd.oasis.opendocument.spreadsheet ods
+application/vnd.oasis.opendocument.spreadsheet-template ots
+application/vnd.oasis.opendocument.text odt
+application/vnd.oasis.opendocument.text-master odm
+application/vnd.oasis.opendocument.text-template ott
+application/vnd.oasis.opendocument.text-web oth
+application/vnd.olpc-sugar xo
+application/vnd.oma.dd2+xml dd2
+application/vnd.openblox.game+xml obgx
+application/vnd.openofficeorg.extension oxt
+application/vnd.openstreetmap.data+xml osm
+application/vnd.openxmlformats-officedocument.presentationml.presentation pptx
+application/vnd.openxmlformats-officedocument.presentationml.slide sldx
+application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx
+application/vnd.openxmlformats-officedocument.presentationml.template potx
+application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx
+application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx
+application/vnd.openxmlformats-officedocument.wordprocessingml.document docx
+application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx
+application/vnd.osgeo.mapguide.package mgp
+application/vnd.osgi.dp dp
+application/vnd.osgi.subsystem esa
+application/vnd.palm oprc pdb pqa
+application/vnd.pawaafile paw
+application/vnd.pg.format str
+application/vnd.pg.osasli ei6
+application/vnd.picsel efif
+application/vnd.pmi.widget wg
+application/vnd.pocketlearn plf
+application/vnd.powerbuilder6 pbd
+application/vnd.previewsystems.box box
+application/vnd.proteus.magazine mgz
+application/vnd.publishare-delta-tree qps
+application/vnd.pvi.ptid1 ptid
+application/vnd.quark.quarkxpress qwd qwt qxb qxd qxl qxt
+application/vnd.rar rar
+application/vnd.realvnc.bed bed
+application/vnd.recordare.musicxml mxl
+application/vnd.recordare.musicxml+xml musicxml
+application/vnd.rig.cryptonote cryptonote
+application/vnd.rim.cod cod
+application/vnd.rn-realmedia rm
+application/vnd.rn-realmedia-vbr rmvb
+application/vnd.route66.link66+xml link66
+application/vnd.sailingtracker.track st
+application/vnd.seemail see
+application/vnd.sema sema
+application/vnd.semd semd
+application/vnd.semf semf
+application/vnd.shana.informed.formdata ifm
+application/vnd.shana.informed.formtemplate itp
+application/vnd.shana.informed.interchange iif
+application/vnd.shana.informed.package ipk
+application/vnd.simtech-mindmapper twd twds
+application/vnd.smaf mmf
+application/vnd.smart.teacher teacher
+application/vnd.software602.filler.form+xml fo
+application/vnd.solent.sdkm+xml sdkd sdkm
+application/vnd.spotfire.dxp dxp
+application/vnd.spotfire.sfs sfs
+application/vnd.stardivision.calc sdc
+application/vnd.stardivision.draw sda
+application/vnd.stardivision.impress sdd
+application/vnd.stardivision.math smf
+application/vnd.stardivision.writer sdw vor
+application/vnd.stardivision.writer-global sgl
+application/vnd.stepmania.package smzip
+application/vnd.stepmania.stepchart sm
+application/vnd.sun.wadl+xml wadl
+application/vnd.sun.xml.calc sxc
+application/vnd.sun.xml.calc.template stc
+application/vnd.sun.xml.draw sxd
+application/vnd.sun.xml.draw.template std
+application/vnd.sun.xml.impress sxi
+application/vnd.sun.xml.impress.template sti
+application/vnd.sun.xml.math sxm
+application/vnd.sun.xml.writer sxw
+application/vnd.sun.xml.writer.global sxg
+application/vnd.sun.xml.writer.template stw
+application/vnd.sus-calendar sus susp
+application/vnd.svd svd
+application/vnd.symbian.install sis sisx
+application/vnd.syncml+xml xsm
+application/vnd.syncml.dm+wbxml bdm
+application/vnd.syncml.dm+xml xdm
+application/vnd.syncml.dmddf+xml ddf
+application/vnd.tao.intent-module-archive tao
+application/vnd.tcpdump.pcap cap dmp pcap
+application/vnd.tmobile-livetv tmo
+application/vnd.trid.tpt tpt
+application/vnd.triscape.mxs mxs
+application/vnd.trueapp tra
+application/vnd.ufdl ufd ufdl
+application/vnd.uiq.theme utz
+application/vnd.umajin umj
+application/vnd.unity unityweb
+application/vnd.uoml+xml uoml
+application/vnd.vcx vcx
+application/vnd.visio vsd vss vst vsw
+application/vnd.visionary vis
+application/vnd.vsf vsf
+application/vnd.wap.wbxml wbxml
+application/vnd.wap.wmlc wmlc
+application/vnd.wap.wmlscriptc wmlsc
+application/vnd.webturbo wtb
+application/vnd.wolfram.player nbp
+application/vnd.wordperfect wpd
+application/vnd.wqd wqd
+application/vnd.wt.stf stf
+application/vnd.xara xar
+application/vnd.xfdl xfdl
+application/vnd.yamaha.hv-dic hvd
+application/vnd.yamaha.hv-script hvs
+application/vnd.yamaha.hv-voice hvp
+application/vnd.yamaha.openscoreformat osf
+application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg
+application/vnd.yamaha.smaf-audio saf
+application/vnd.yamaha.smaf-phrase spf
+application/vnd.yellowriver-custom-menu cmp
+application/vnd.zul zir zirz
+application/vnd.zzazz.deck+xml zaz
+application/voicexml+xml vxml
+application/wasm wasm
+application/watcherinfo+xml wif
+application/widget wgt
+application/winhlp hlp
+application/wsdl+xml wsdl
+application/wspolicy+xml wspolicy
+application/x-7z-compressed 7z
+application/x-abiword abw
+application/x-ace-compressed ace
+application/x-arj arj
+application/x-authorware-bin aab u32 vox x32
+application/x-authorware-map aam
+application/x-authorware-seg aas
+application/x-bcpio bcpio
+application/x-bittorrent torrent
+application/x-blorb blb blorb
+application/x-bzip bz
+application/x-bzip2 boz bz2
+application/x-cbr cb7 cba cbr cbt cbz
+application/x-cdlink vcd
+application/x-cfs-compressed cfs
+application/x-chat chat
+application/x-chess-pgn pgn
+application/x-chrome-extension crx
+application/x-cocoa cco
+application/x-conference nsc
+application/x-cpio cpio
+application/x-csh csh
+application/x-debian-package udeb
+application/x-dgc-compressed dgc
+application/x-director cct cst cxt dcr dir dxr fgd swa w3d
+application/x-doom wad
+application/x-dtbncx+xml ncx
+application/x-dtbook+xml dtb
+application/x-dtbresource+xml res
+application/x-dvi dvi
+application/x-envoy evy
+application/x-eva eva
+application/x-font-bdf bdf
+application/x-font-ghostscript gsf
+application/x-font-linux-psf psf
+application/x-font-pcf pcf
+application/x-font-snf snf
+application/x-font-type1 afm pfa pfb pfm
+application/x-freearc arc
+application/x-futuresplash spl
+application/x-gca-compressed gca
+application/x-glulx ulx
+application/x-gnumeric gnumeric
+application/x-gramps-xml gramps
+application/x-gtar gtar
+application/x-hdf hdf
+application/x-httpd-php php
+application/x-install-instructions install
+application/x-java-archive-diff jardiff
+application/x-java-jnlp-file jnlp
+application/x-keepass2 kdbx
+application/x-latex latex
+application/x-lua-bytecode luac
+application/x-lzh-compressed lha lzh
+application/x-makeself run
+application/x-mie mie
+application/x-mobipocket-ebook mobi prc
+application/x-ms-application application
+application/x-ms-shortcut lnk
+application/x-ms-wmd wmd
+application/x-ms-wmz wmz
+application/x-ms-xbap xbap
+application/x-msaccess mdb
+application/x-msbinder obd
+application/x-mscardfile crd
+application/x-msclip clp
+application/x-msdownload bat com
+application/x-msmediaview m13 m14 mvb
+application/x-msmetafile emf emz wmf
+application/x-msmoney mny
+application/x-mspublisher pub
+application/x-msschedule scd
+application/x-msterminal trm
+application/x-mswrite wri
+application/x-netcdf cdf nc
+application/x-ns-proxy-autoconfig pac
+application/x-nzb nzb
+application/x-perl pl pm
+application/x-pkcs12 p12 pfx
+application/x-pkcs7-certificates p7b spc
+application/x-pkcs7-certreqresp p7r
+application/x-redhat-package-manager rpm
+application/x-research-info-systems ris
+application/x-sea sea
+application/x-sh sh
+application/x-shar shar
+application/x-shockwave-flash swf
+application/x-silverlight-app xap
+application/x-sql sql
+application/x-stuffit sit
+application/x-stuffitx sitx
+application/x-subrip srt
+application/x-sv4cpio sv4cpio
+application/x-sv4crc sv4crc
+application/x-t3vm-image t3
+application/x-tads gam
+application/x-tar tar
+application/x-tcl tcl tk
+application/x-tex tex
+application/x-tex-tfm tfm
+application/x-texinfo texi texinfo
+application/x-tgif obj
+application/x-ustar ustar
+application/x-virtualbox-hdd hdd
+application/x-virtualbox-ova ova
+application/x-virtualbox-ovf ovf
+application/x-virtualbox-vbox vbox
+application/x-virtualbox-vbox-extpack vbox-extpack
+application/x-virtualbox-vdi vdi
+application/x-virtualbox-vhd vhd
+application/x-virtualbox-vmdk vmdk
+application/x-wais-source src
+application/x-web-app-manifest+json webapp
+application/x-x509-ca-cert crt der pem
+application/x-xfig fig
+application/x-xliff+xml xlf
+application/x-xpinstall xpi
+application/x-xz xz
+application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8
+application/xaml+xml xaml
+application/xcap-att+xml xav
+application/xcap-caps+xml xca
+application/xcap-diff+xml xdf
+application/xcap-el+xml xel
+application/xcap-ns+xml xns
+application/xenc+xml xenc
+application/xhtml+xml xht xhtml
+application/xml rng xml xsd xsl
+application/xml-dtd dtd
+application/xop+xml xop
+application/xproc+xml xpl
+application/xslt+xml xslt
+application/xspf+xml xspf
+application/xv+xml mxml xhvml xvm xvml
+application/yang yang
+application/yin+xml yin
+application/zip zip
+audio/3gpp 3gpp
+audio/adpcm adp
+audio/amr amr
+audio/basic au snd
+audio/midi kar mid midi rmi
+audio/mobile-xmf mxmf
+audio/mp3 mp3
+audio/mp4 m4a mp4a
+audio/mpeg m2a m3a mp2 mp2a mpga
+audio/ogg oga ogg opus spx
+audio/s3m s3m
+audio/silk sil
+audio/vnd.dece.audio uva uvva
+audio/vnd.digital-winds eol
+audio/vnd.dra dra
+audio/vnd.dts dts
+audio/vnd.dts.hd dtshd
+audio/vnd.lucent.voice lvp
+audio/vnd.ms-playready.media.pya pya
+audio/vnd.nuera.ecelp4800 ecelp4800
+audio/vnd.nuera.ecelp7470 ecelp7470
+audio/vnd.nuera.ecelp9600 ecelp9600
+audio/vnd.rip rip
+audio/wav wav
+audio/webm weba
+audio/x-aac aac
+audio/x-aiff aif aifc aiff
+audio/x-caf caf
+audio/x-flac flac
+audio/x-matroska mka
+audio/x-mpegurl m3u
+audio/x-ms-wax wax
+audio/x-ms-wma wma
+audio/x-pn-realaudio ra ram
+audio/x-pn-realaudio-plugin rmp
+audio/xm xm
+chemical/x-cdx cdx
+chemical/x-cif cif
+chemical/x-cmdf cmdf
+chemical/x-cml cml
+chemical/x-csml csml
+chemical/x-xyz xyz
+font/collection ttc
+font/otf otf
+font/ttf ttf
+font/woff woff
+font/woff2 woff2
+image/aces exr
+image/apng apng
+image/avci avci
+image/avcs avcs
+image/avif avif
+image/bmp bmp
+image/cgm cgm
+image/dicom-rle drle
+image/fits fits
+image/g3fax g3
+image/gif gif
+image/heic heic
+image/heic-sequence heics
+image/heif heif
+image/heif-sequence heifs
+image/hej2k hej2
+image/hsj2 hsj2
+image/ief ief
+image/jls jls
+image/jp2 jp2 jpg2
+image/jpeg jpe jpeg jpg
+image/jph jph
+image/jphc jhc
+image/jpm jpm
+image/jpx jpf jpx
+image/jxr jxr
+image/jxra jxra
+image/jxrs jxrs
+image/jxs jxs
+image/jxsc jxsc
+image/jxsi jxsi
+image/jxss jxss
+image/ktx ktx
+image/ktx2 ktx2
+image/png png
+image/prs.btif btif
+image/prs.pti pti
+image/sgi sgi
+image/svg+xml svg svgz
+image/t38 t38
+image/tiff tif tiff
+image/tiff-fx tfx
+image/vnd.adobe.photoshop psd
+image/vnd.airzip.accelerator.azv azv
+image/vnd.dece.graphic uvg uvi uvvg uvvi
+image/vnd.djvu djv djvu
+image/vnd.dvb.subtitle sub
+image/vnd.dwg dwg
+image/vnd.dxf dxf
+image/vnd.fastbidsheet fbs
+image/vnd.fpx fpx
+image/vnd.fst fst
+image/vnd.fujixerox.edmics-mmr mmr
+image/vnd.fujixerox.edmics-rlc rlc
+image/vnd.microsoft.icon ico
+image/vnd.ms-dds dds
+image/vnd.ms-modi mdi
+image/vnd.ms-photo wdp
+image/vnd.net-fpx npx
+image/vnd.pco.b16 b16
+image/vnd.tencent.tap tap
+image/vnd.valve.source.texture vtf
+image/vnd.wap.wbmp wbmp
+image/vnd.xiff xif
+image/vnd.zbrush.pcx pcx
+image/webp webp
+image/x-3ds 3ds
+image/x-cmu-raster ras
+image/x-cmx cmx
+image/x-freehand fh fh4 fh5 fh7 fhc
+image/x-jng jng
+image/x-mrsid-image sid
+image/x-pict pct pic
+image/x-portable-anymap pnm
+image/x-portable-bitmap pbm
+image/x-portable-graymap pgm
+image/x-portable-pixmap ppm
+image/x-rgb rgb
+image/x-tga tga
+image/x-xbitmap xbm
+image/x-xpixmap xpm
+image/x-xwindowdump xwd
+message/disposition-notification disposition-notification
+message/global u8msg
+message/global-delivery-status u8dsn
+message/global-disposition-notification u8mdn
+message/global-headers u8hdr
+message/rfc822 eml mime
+message/vnd.wfa.wsc wsc
+model/3mf 3mf
+model/gltf+json gltf
+model/gltf-binary glb
+model/iges iges igs
+model/mesh mesh msh silo
+model/mtl mtl
+model/step+xml stpx
+model/step+zip stpz
+model/step-xml+zip stpxz
+model/vnd.collada+xml dae
+model/vnd.dwf dwf
+model/vnd.gdl gdl
+model/vnd.gtw gtw
+model/vnd.mts mts
+model/vnd.opengex ogex
+model/vnd.parasolid.transmit.binary x_b
+model/vnd.parasolid.transmit.text x_t
+model/vnd.sap.vds vds
+model/vnd.usdz+zip usdz
+model/vnd.valve.source.compiled-map bsp
+model/vnd.vtu vtu
+model/vrml vrml wrl
+model/x3d+binary x3db x3dbz
+model/x3d+vrml x3dv x3dvz
+model/x3d+xml x3d x3dz
+text/cache-manifest appcache manifest
+text/calendar ics ifb
+text/coffeescript coffee litcoffee
+text/css css
+text/csv csv
+text/html htm html shtml
+text/jade jade
+text/jsx jsx
+text/less less
+text/markdown markdown md
+text/mathml mml
+text/mdx mdx
+text/n3 n3
+text/plain conf def in ini list log text txt
+text/prs.lines.tag dsc
+text/richtext rtx
+text/sgml sgm sgml
+text/shex shex
+text/slim slim slm
+text/spdx spdx
+text/stylus styl stylus
+text/tab-separated-values tsv
+text/troff man me ms roff t tr
+text/turtle ttl
+text/uri-list uri uris urls
+text/vcard vcard
+text/vnd.curl curl
+text/vnd.curl.dcurl dcurl
+text/vnd.curl.mcurl mcurl
+text/vnd.curl.scurl scurl
+text/vnd.familysearch.gedcom ged
+text/vnd.fly fly
+text/vnd.fmi.flexstor flx
+text/vnd.graphviz gv
+text/vnd.in3d.3dml 3dml
+text/vnd.in3d.spot spot
+text/vnd.sun.j2me.app-descriptor jad
+text/vnd.wap.wml wml
+text/vnd.wap.wmlscript wmls
+text/vtt vtt
+text/x-asm asm s
+text/x-c c cc cpp cxx dic h hh
+text/x-component htc
+text/x-fortran f f77 f90 for
+text/x-handlebars-template hbs
+text/x-java-source java
+text/x-lua lua
+text/x-markdown mkd
+text/x-nfo nfo
+text/x-opml opml
+text/x-pascal p pas
+text/x-processing pde
+text/x-sass sass
+text/x-scss scss
+text/x-setext etx
+text/x-sfv sfv
+text/x-suse-ymp ymp
+text/x-uuencode uu
+text/x-vcalendar vcs
+text/x-vcard vcf
+text/yaml yaml yml
+video/3gpp 3gp
+video/3gpp2 3g2
+video/h261 h261
+video/h263 h263
+video/h264 h264
+video/iso.segment m4s
+video/jpeg jpgv
+video/jpm jpgm
+video/mj2 mj2 mjp2
+video/mp2t ts
+video/mp4 mp4 mp4v mpg4
+video/mpeg m1v m2v mpe mpeg mpg
+video/ogg ogv
+video/quicktime mov qt
+video/vnd.dece.hd uvh uvvh
+video/vnd.dece.mobile uvm uvvm
+video/vnd.dece.pd uvp uvvp
+video/vnd.dece.sd uvs uvvs
+video/vnd.dece.video uvv uvvv
+video/vnd.dvb.file dvb
+video/vnd.fvt fvt
+video/vnd.mpegurl m4u mxu
+video/vnd.ms-playready.media.pyv pyv
+video/vnd.uvvu.mp4 uvu uvvu
+video/vnd.vivo viv
+video/webm webm
+video/x-f4v f4v
+video/x-fli fli
+video/x-flv flv
+video/x-m4v m4v
+video/x-matroska mk3d mks mkv
+video/x-mng mng
+video/x-ms-asf asf asx
+video/x-ms-vob vob
+video/x-ms-wm wm
+video/x-ms-wmv wmv
+video/x-ms-wmx wmx
+video/x-ms-wvx wvx
+video/x-msvideo avi
+video/x-sgi-movie movie
+video/x-smv smv
+x-conference/x-cooltalk ice \ No newline at end of file
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/page.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/page.rb
new file mode 100644
index 0000000..64821a8
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/page.rb
@@ -0,0 +1,215 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Page
+ include Convertible
+
+ attr_writer :dir
+ attr_accessor :basename, :content, :data, :ext, :name, :output, :pager, :site
+
+ alias_method :extname, :ext
+
+ # Attributes for Liquid templates
+ ATTRIBUTES_FOR_LIQUID = %w(
+ content
+ dir
+ excerpt
+ name
+ path
+ url
+ ).freeze
+
+ # A set of extensions that are considered HTML or HTML-like so we
+ # should not alter them, this includes .xhtml through XHTM5.
+
+ HTML_EXTENSIONS = %w(
+ .html
+ .xhtml
+ .htm
+ ).freeze
+
+ # Initialize a new Page.
+ #
+ # site - The Site object.
+ # base - The String path to the source.
+ # dir - The String path between the source and the file.
+ # name - The String filename of the file.
+ def initialize(site, base, dir, name)
+ @site = site
+ @base = base
+ @dir = dir
+ @name = name
+ @path = if site.in_theme_dir(base) == base # we're in a theme
+ site.in_theme_dir(base, dir, name)
+ else
+ site.in_source_dir(base, dir, name)
+ end
+
+ process(name)
+ read_yaml(PathManager.join(base, dir), name)
+ generate_excerpt if site.config["page_excerpts"]
+
+ data.default_proc = proc do |_, key|
+ site.frontmatter_defaults.find(relative_path, type, key)
+ end
+
+ Jekyll::Hooks.trigger :pages, :post_init, self
+ end
+
+ # The generated directory into which the page will be placed
+ # upon generation. This is derived from the permalink or, if
+ # permalink is absent, will be '/'
+ #
+ # Returns the String destination directory.
+ def dir
+ url.end_with?("/") ? url : url_dir
+ end
+
+ # The full path and filename of the post. Defined in the YAML of the post
+ # body.
+ #
+ # Returns the String permalink or nil if none has been set.
+ def permalink
+ data.nil? ? nil : data["permalink"]
+ end
+
+ # The template of the permalink.
+ #
+ # Returns the template String.
+ def template
+ if !html?
+ "/:path/:basename:output_ext"
+ elsif index?
+ "/:path/"
+ else
+ Utils.add_permalink_suffix("/:path/:basename", site.permalink_style)
+ end
+ end
+
+ # The generated relative url of this page. e.g. /about.html.
+ #
+ # Returns the String url.
+ def url
+ @url ||= URL.new(
+ :template => template,
+ :placeholders => url_placeholders,
+ :permalink => permalink
+ ).to_s
+ end
+
+ # Returns a hash of URL placeholder names (as symbols) mapping to the
+ # desired placeholder replacements. For details see "url.rb"
+ def url_placeholders
+ {
+ :path => @dir,
+ :basename => basename,
+ :output_ext => output_ext,
+ }
+ end
+
+ # Extract information from the page filename.
+ #
+ # name - The String filename of the page file.
+ #
+ # NOTE: `String#gsub` removes all trailing periods (in comparison to `String#chomp`)
+ # Returns nothing.
+ def process(name)
+ return unless name
+
+ self.ext = File.extname(name)
+ self.basename = name[0..-ext.length - 1].gsub(%r!\.*\z!, "")
+ end
+
+ # Add any necessary layouts to this post
+ #
+ # layouts - The Hash of {"name" => "layout"}.
+ # site_payload - The site payload Hash.
+ #
+ # Returns String rendered page.
+ def render(layouts, site_payload)
+ site_payload["page"] = to_liquid
+ site_payload["paginator"] = pager.to_liquid
+
+ do_layout(site_payload, layouts)
+ end
+
+ # The path to the source file
+ #
+ # Returns the path to the source file
+ def path
+ data.fetch("path") { relative_path }
+ end
+
+ # The path to the page source file, relative to the site source
+ def relative_path
+ @relative_path ||= PathManager.join(@dir, @name).delete_prefix("/")
+ end
+
+ # Obtain destination path.
+ #
+ # dest - The String path to the destination dir.
+ #
+ # Returns the destination file path String.
+ def destination(dest)
+ @destination ||= {}
+ @destination[dest] ||= begin
+ path = site.in_dest_dir(dest, URL.unescape_path(url))
+ path = File.join(path, "index") if url.end_with?("/")
+ path << output_ext unless path.end_with? output_ext
+ path
+ end
+ end
+
+ # Returns the object as a debug String.
+ def inspect
+ "#<#{self.class} @relative_path=#{relative_path.inspect}>"
+ end
+
+ # Returns the Boolean of whether this Page is HTML or not.
+ def html?
+ HTML_EXTENSIONS.include?(output_ext)
+ end
+
+ # Returns the Boolean of whether this Page is an index file or not.
+ def index?
+ basename == "index"
+ end
+
+ def trigger_hooks(hook_name, *args)
+ Jekyll::Hooks.trigger :pages, hook_name, self, *args
+ end
+
+ def write?
+ true
+ end
+
+ def excerpt_separator
+ @excerpt_separator ||= (data["excerpt_separator"] || site.config["excerpt_separator"]).to_s
+ end
+
+ def excerpt
+ return @excerpt if defined?(@excerpt)
+
+ @excerpt = data["excerpt"] ? data["excerpt"].to_s : nil
+ end
+
+ def generate_excerpt?
+ !excerpt_separator.empty? && instance_of?(Jekyll::Page) && html?
+ end
+
+ private
+
+ def generate_excerpt
+ return unless generate_excerpt?
+
+ data["excerpt"] ||= Jekyll::PageExcerpt.new(self)
+ end
+
+ def url_dir
+ @url_dir ||= begin
+ value = File.dirname(url)
+ value.end_with?("/") ? value : "#{value}/"
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/page_excerpt.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/page_excerpt.rb
new file mode 100644
index 0000000..dd79fca
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/page_excerpt.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class PageExcerpt < Excerpt
+ attr_reader :doc
+ alias_method :id, :relative_path
+
+ EXCERPT_ATTRIBUTES = (Page::ATTRIBUTES_FOR_LIQUID - %w(excerpt)).freeze
+ private_constant :EXCERPT_ATTRIBUTES
+
+ def to_liquid
+ @to_liquid ||= doc.to_liquid(EXCERPT_ATTRIBUTES)
+ end
+
+ def render_with_liquid?
+ return false if data["render_with_liquid"] == false
+
+ Jekyll::Utils.has_liquid_construct?(content)
+ end
+
+ def inspect
+ "#<#{self.class} id=#{id.inspect}>"
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/page_without_a_file.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/page_without_a_file.rb
new file mode 100644
index 0000000..e314f97
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/page_without_a_file.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Jekyll
+ # A Jekyll::Page subclass to handle processing files without reading it to
+ # determine the page-data and page-content based on Front Matter delimiters.
+ #
+ # The class instance is basically just a bare-bones entity with just
+ # attributes "dir", "name", "path", "url" defined on it.
+ class PageWithoutAFile < Page
+ def read_yaml(*)
+ @data ||= {}
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/path_manager.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/path_manager.rb
new file mode 100644
index 0000000..5d97522
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/path_manager.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+module Jekyll
+ # A singleton class that caches frozen instances of path strings returned from its methods.
+ #
+ # NOTE:
+ # This class exists because `File.join` allocates an Array and returns a new String on every
+ # call using **the same arguments**. Caching the result means reduced memory usage.
+ # However, the caches are never flushed so that they can be used even when a site is
+ # regenerating. The results are frozen to deter mutation of the cached string.
+ #
+ # Therefore, employ this class only for situations where caching the result is necessary
+ # for performance reasons.
+ #
+ class PathManager
+ # This class cannot be initialized from outside
+ private_class_method :new
+
+ class << self
+ # Wraps `File.join` to cache the frozen result.
+ # Reassigns `nil`, empty strings and empty arrays to a frozen empty string beforehand.
+ #
+ # Returns a frozen string.
+ def join(base, item)
+ base = "" if base.nil? || base.empty?
+ item = "" if item.nil? || item.empty?
+ @join ||= {}
+ @join[base] ||= {}
+ @join[base][item] ||= File.join(base, item).freeze
+ end
+
+ # Ensures the questionable path is prefixed with the base directory
+ # and prepends the questionable path with the base directory if false.
+ #
+ # Returns a frozen string.
+ def sanitized_path(base_directory, questionable_path)
+ @sanitized_path ||= {}
+ @sanitized_path[base_directory] ||= {}
+ @sanitized_path[base_directory][questionable_path] ||= if questionable_path.nil?
+ base_directory.freeze
+ else
+ sanitize_and_join(
+ base_directory, questionable_path
+ ).freeze
+ end
+ end
+
+ private
+
+ def sanitize_and_join(base_directory, questionable_path)
+ clean_path = if questionable_path.start_with?("~")
+ questionable_path.dup.insert(0, "/")
+ else
+ questionable_path
+ end
+ clean_path = File.expand_path(clean_path, "/")
+ return clean_path if clean_path.eql?(base_directory)
+
+ # remove any remaining extra leading slashes not stripped away by calling
+ # `File.expand_path` above.
+ clean_path.squeeze!("/")
+ return clean_path if clean_path.start_with?(slashed_dir_cache(base_directory))
+
+ clean_path.sub!(%r!\A\w:/!, "/")
+ join(base_directory, clean_path)
+ end
+
+ def slashed_dir_cache(base_directory)
+ @slashed_dir_cache ||= {}
+ @slashed_dir_cache[base_directory] ||= base_directory.sub(%r!\z!, "/")
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/plugin.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/plugin.rb
new file mode 100644
index 0000000..1157e12
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/plugin.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Plugin
+ PRIORITIES = {
+ :low => -10,
+ :highest => 100,
+ :lowest => -100,
+ :normal => 0,
+ :high => 10,
+ }.freeze
+
+ #
+
+ def self.inherited(const)
+ catch_inheritance(const) do |const_|
+ catch_inheritance(const_)
+ end
+ end
+
+ #
+
+ def self.catch_inheritance(const)
+ const.define_singleton_method :inherited do |const_|
+ (@children ||= Set.new).add const_
+ yield const_ if block_given?
+ end
+ end
+
+ #
+
+ def self.descendants
+ @children ||= Set.new
+ out = @children.map(&:descendants)
+ out << self unless superclass == Plugin
+ Set.new(out).flatten
+ end
+
+ # Get or set the priority of this plugin. When called without an
+ # argument it returns the priority. When an argument is given, it will
+ # set the priority.
+ #
+ # priority - The Symbol priority (default: nil). Valid options are:
+ # :lowest, :low, :normal, :high, :highest
+ #
+ # Returns the Symbol priority.
+ def self.priority(priority = nil)
+ @priority ||= nil
+ @priority = priority if priority && PRIORITIES.key?(priority)
+ @priority || :normal
+ end
+
+ # Get or set the safety of this plugin. When called without an argument
+ # it returns the safety. When an argument is given, it will set the
+ # safety.
+ #
+ # safe - The Boolean safety (default: nil).
+ #
+ # Returns the safety Boolean.
+ def self.safe(safe = nil)
+ @safe = safe unless defined?(@safe) && safe.nil?
+ @safe || false
+ end
+
+ # Spaceship is priority [higher -> lower]
+ #
+ # other - The class to be compared.
+ #
+ # Returns -1, 0, 1.
+ def self.<=>(other)
+ PRIORITIES[other.priority] <=> PRIORITIES[priority]
+ end
+
+ # Spaceship is priority [higher -> lower]
+ #
+ # other - The class to be compared.
+ #
+ # Returns -1, 0, 1.
+ def <=>(other)
+ self.class <=> other.class
+ end
+
+ # Initialize a new plugin. This should be overridden by the subclass.
+ #
+ # config - The Hash of configuration options.
+ #
+ # Returns a new instance.
+ def initialize(config = {})
+ # no-op for default
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/plugin_manager.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/plugin_manager.rb
new file mode 100644
index 0000000..810a2fa
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/plugin_manager.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class PluginManager
+ attr_reader :site
+
+ # Create an instance of this class.
+ #
+ # site - the instance of Jekyll::Site we're concerned with
+ #
+ # Returns nothing
+ def initialize(site)
+ @site = site
+ end
+
+ # Require all the plugins which are allowed.
+ #
+ # Returns nothing
+ def conscientious_require
+ require_theme_deps if site.theme
+ require_plugin_files
+ require_gems
+ deprecation_checks
+ end
+
+ # Require each of the gem plugins specified.
+ #
+ # Returns nothing.
+ def require_gems
+ Jekyll::External.require_with_graceful_fail(
+ site.gems.select { |plugin| plugin_allowed?(plugin) }
+ )
+ end
+
+ # Require each of the runtime_dependencies specified by the theme's gemspec.
+ #
+ # Returns false only if no dependencies have been specified, otherwise nothing.
+ def require_theme_deps
+ return false unless site.theme.runtime_dependencies
+
+ site.theme.runtime_dependencies.each do |dep|
+ next if dep.name == "jekyll"
+
+ External.require_with_graceful_fail(dep.name) if plugin_allowed?(dep.name)
+ end
+ end
+
+ def self.require_from_bundler
+ if !ENV["JEKYLL_NO_BUNDLER_REQUIRE"] && gemfile_exists?
+ require "bundler"
+
+ Bundler.setup
+ required_gems = Bundler.require(:jekyll_plugins)
+ message = "Required #{required_gems.map(&:name).join(", ")}"
+ Jekyll.logger.debug("PluginManager:", message)
+ ENV["JEKYLL_NO_BUNDLER_REQUIRE"] = "true"
+
+ true
+ else
+ false
+ end
+ end
+
+ # Check for the existence of a Gemfile.
+ #
+ # Returns true if a Gemfile exists in the places bundler will look
+ def self.gemfile_exists?
+ File.file?("Gemfile") || (ENV["BUNDLE_GEMFILE"] && File.file?(ENV["BUNDLE_GEMFILE"]))
+ end
+
+ # Check whether a gem plugin is allowed to be used during this build.
+ #
+ # plugin_name - the name of the plugin
+ #
+ # Returns true if the plugin name is in the whitelist or if the site is not
+ # in safe mode.
+ def plugin_allowed?(plugin_name)
+ !site.safe || whitelist.include?(plugin_name)
+ end
+
+ # Build an array of allowed plugin gem names.
+ #
+ # Returns an array of strings, each string being the name of a gem name
+ # that is allowed to be used.
+ def whitelist
+ @whitelist ||= [site.config["whitelist"]].flatten
+ end
+
+ # Require all .rb files if safe mode is off
+ #
+ # Returns nothing.
+ def require_plugin_files
+ unless site.safe
+ plugins_path.each do |plugin_search_path|
+ plugin_files = Utils.safe_glob(plugin_search_path, File.join("**", "*.rb"))
+ Jekyll::External.require_with_graceful_fail(plugin_files)
+ end
+ end
+ end
+
+ # Public: Setup the plugin search path
+ #
+ # Returns an Array of plugin search paths
+ def plugins_path
+ if site.config["plugins_dir"].eql? Jekyll::Configuration::DEFAULTS["plugins_dir"]
+ [site.in_source_dir(site.config["plugins_dir"])]
+ else
+ Array(site.config["plugins_dir"]).map { |d| File.expand_path(d) }
+ end
+ end
+
+ def deprecation_checks
+ pagination_included = (site.config["plugins"] || []).include?("jekyll-paginate") ||
+ defined?(Jekyll::Paginate)
+ if site.config["paginate"] && !pagination_included
+ Jekyll::Deprecator.deprecation_message <<~MSG
+ You appear to have pagination turned on, but you haven't included the `jekyll-paginate`
+ gem. Ensure you have `plugins: [jekyll-paginate]` in your configuration file.
+ MSG
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/profiler.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/profiler.rb
new file mode 100644
index 0000000..f5dbfb1
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/profiler.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Profiler
+ TERMINAL_TABLE_STYLES = {
+ :alignment => :right,
+ :border_top => false,
+ :border_bottom => false,
+ }.freeze
+ private_constant :TERMINAL_TABLE_STYLES
+
+ def self.tabulate(table_rows)
+ require "terminal-table"
+
+ rows = table_rows.dup
+ header = rows.shift
+ output = +"\n"
+
+ table = Terminal::Table.new do |t|
+ t << header
+ t << :separator
+ rows.each { |row| t << row }
+ t.style = TERMINAL_TABLE_STYLES
+ t.align_column(0, :left)
+ end
+
+ output << table.to_s << "\n"
+ end
+
+ def initialize(site)
+ @site = site
+ end
+
+ def profile_process
+ profile_data = { "PHASE" => "TIME" }
+
+ [:reset, :read, :generate, :render, :cleanup, :write].each do |method|
+ start_time = Time.now
+ @site.send(method)
+ end_time = (Time.now - start_time).round(4)
+ profile_data[method.to_s.upcase] = format("%.4f", end_time)
+ end
+
+ Jekyll.logger.info "\nBuild Process Summary:"
+ Jekyll.logger.info Profiler.tabulate(Array(profile_data))
+
+ Jekyll.logger.info "\nSite Render Stats:"
+ @site.print_stats
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/publisher.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/publisher.rb
new file mode 100644
index 0000000..26fe4a3
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/publisher.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Publisher
+ def initialize(site)
+ @site = site
+ end
+
+ def publish?(thing)
+ can_be_published?(thing) && !hidden_in_the_future?(thing)
+ end
+
+ def hidden_in_the_future?(thing)
+ thing.respond_to?(:date) && !@site.future && thing.date.to_i > @site.time.to_i
+ end
+
+ private
+
+ def can_be_published?(thing)
+ thing.data.fetch("published", true) || @site.unpublished
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/reader.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/reader.rb
new file mode 100644
index 0000000..5d15177
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/reader.rb
@@ -0,0 +1,209 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Reader
+ attr_reader :site
+
+ def initialize(site)
+ @site = site
+ end
+
+ # Read Site data from disk and load it into internal data structures.
+ #
+ # Returns nothing.
+ def read
+ @site.layouts = LayoutReader.new(site).read
+ read_directories
+ read_included_excludes
+ sort_files!
+ CollectionReader.new(site).read
+ ThemeAssetsReader.new(site).read
+ read_data
+ end
+
+ # Read and merge the data files.
+ # If a theme is specified and it contains data, it will be read.
+ # Site data will overwrite theme data with the same key using the
+ # semantics of Utils.deep_merge_hashes.
+ #
+ # Returns nothing.
+ def read_data
+ @site.data = DataReader.new(site).read(site.config["data_dir"])
+ return unless site.theme&.data_path
+
+ theme_data = DataReader.new(
+ site,
+ :in_source_dir => site.method(:in_theme_dir)
+ ).read(site.theme.data_path)
+ @site.data = Jekyll::Utils.deep_merge_hashes(theme_data, @site.data)
+ end
+
+ # Sorts posts, pages, and static files.
+ def sort_files!
+ site.collections.each_value { |c| c.docs.sort! }
+ site.pages.sort_by!(&:name)
+ site.static_files.sort_by!(&:relative_path)
+ end
+
+ # Recursively traverse directories to find pages and static files
+ # that will become part of the site according to the rules in
+ # filter_entries.
+ #
+ # dir - The String relative path of the directory to read. Default: ''.
+ #
+ # Returns nothing.
+ def read_directories(dir = "")
+ base = site.in_source_dir(dir)
+
+ return unless File.directory?(base)
+
+ dot_dirs = []
+ dot_pages = []
+ dot_static_files = []
+
+ dot = Dir.chdir(base) { filter_entries(Dir.entries("."), base) }
+ dot.each do |entry|
+ file_path = @site.in_source_dir(base, entry)
+ if File.directory?(file_path)
+ dot_dirs << entry
+ elsif Utils.has_yaml_header?(file_path)
+ dot_pages << entry
+ else
+ dot_static_files << entry
+ end
+ end
+
+ retrieve_posts(dir)
+ retrieve_dirs(base, dir, dot_dirs)
+ retrieve_pages(dir, dot_pages)
+ retrieve_static_files(dir, dot_static_files)
+ end
+
+ # Retrieves all the posts(posts/drafts) from the given directory
+ # and add them to the site and sort them.
+ #
+ # dir - The String representing the directory to retrieve the posts from.
+ #
+ # Returns nothing.
+ def retrieve_posts(dir)
+ return if outside_configured_directory?(dir)
+
+ site.posts.docs.concat(post_reader.read_posts(dir))
+ site.posts.docs.concat(post_reader.read_drafts(dir)) if site.show_drafts
+ end
+
+ # Recursively traverse directories with the read_directories function.
+ #
+ # base - The String representing the site's base directory.
+ # dir - The String representing the directory to traverse down.
+ # dot_dirs - The Array of subdirectories in the dir.
+ #
+ # Returns nothing.
+ def retrieve_dirs(_base, dir, dot_dirs)
+ dot_dirs.each do |file|
+ dir_path = site.in_source_dir(dir, file)
+ rel_path = PathManager.join(dir, file)
+ @site.reader.read_directories(rel_path) unless @site.dest.chomp("/") == dir_path
+ end
+ end
+
+ # Retrieve all the pages from the current directory,
+ # add them to the site and sort them.
+ #
+ # dir - The String representing the directory retrieve the pages from.
+ # dot_pages - The Array of pages in the dir.
+ #
+ # Returns nothing.
+ def retrieve_pages(dir, dot_pages)
+ site.pages.concat(PageReader.new(site, dir).read(dot_pages))
+ end
+
+ # Retrieve all the static files from the current directory,
+ # add them to the site and sort them.
+ #
+ # dir - The directory retrieve the static files from.
+ # dot_static_files - The static files in the dir.
+ #
+ # Returns nothing.
+ def retrieve_static_files(dir, dot_static_files)
+ site.static_files.concat(StaticFileReader.new(site, dir).read(dot_static_files))
+ end
+
+ # Filter out any files/directories that are hidden or backup files (start
+ # with "." or "#" or end with "~"), or contain site content (start with "_"),
+ # or are excluded in the site configuration, unless they are web server
+ # files such as '.htaccess'.
+ #
+ # entries - The Array of String file/directory entries to filter.
+ # base_directory - The string representing the optional base directory.
+ #
+ # Returns the Array of filtered entries.
+ def filter_entries(entries, base_directory = nil)
+ EntryFilter.new(site, base_directory).filter(entries)
+ end
+
+ # Read the entries from a particular directory for processing
+ #
+ # dir - The String representing the relative path of the directory to read.
+ # subfolder - The String representing the directory to read.
+ #
+ # Returns the list of entries to process
+ def get_entries(dir, subfolder)
+ base = site.in_source_dir(dir, subfolder)
+ return [] unless File.exist?(base)
+
+ entries = Dir.chdir(base) { filter_entries(Dir["**/*"], base) }
+ entries.delete_if { |e| File.directory?(site.in_source_dir(base, e)) }
+ end
+
+ private
+
+ # Internal
+ #
+ # Determine if the directory is supposed to contain posts and drafts.
+ # If the user has defined a custom collections_dir, then attempt to read
+ # posts and drafts only from within that directory.
+ #
+ # Returns true if a custom collections_dir has been set but current directory lies
+ # outside that directory.
+ def outside_configured_directory?(dir)
+ collections_dir = site.config["collections_dir"]
+ !collections_dir.empty? && !dir.start_with?("/#{collections_dir}")
+ end
+
+ # Create a single PostReader instance to retrieve drafts and posts from all valid
+ # directories in current site.
+ def post_reader
+ @post_reader ||= PostReader.new(site)
+ end
+
+ def read_included_excludes
+ entry_filter = EntryFilter.new(site)
+
+ site.include.each do |entry|
+ entry_path = site.in_source_dir(entry)
+ next if File.directory?(entry_path)
+ next if entry_filter.symlink?(entry_path)
+
+ read_included_file(entry_path) if File.file?(entry_path)
+ end
+ end
+
+ def read_included_file(entry_path)
+ if Utils.has_yaml_header?(entry_path)
+ conditionally_generate_entry(entry_path, site.pages, PageReader)
+ else
+ conditionally_generate_entry(entry_path, site.static_files, StaticFileReader)
+ end
+ end
+
+ def conditionally_generate_entry(entry_path, container, reader)
+ return if container.find { |item| site.in_source_dir(item.relative_path) == entry_path }
+
+ dir, files = File.split(entry_path)
+ dir.sub!(site.source, "")
+ files = Array(files)
+ container.concat(reader.new(site, dir).read(files))
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/collection_reader.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/collection_reader.rb
new file mode 100644
index 0000000..6d18275
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/collection_reader.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class CollectionReader
+ SPECIAL_COLLECTIONS = %w(posts data).freeze
+
+ attr_reader :site, :content
+
+ def initialize(site)
+ @site = site
+ @content = {}
+ end
+
+ # Read in all collections specified in the configuration
+ #
+ # Returns nothing.
+ def read
+ site.collections.each_value do |collection|
+ collection.read unless SPECIAL_COLLECTIONS.include?(collection.label)
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/data_reader.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/data_reader.rb
new file mode 100644
index 0000000..80b57bd
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/data_reader.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class DataReader
+ attr_reader :site, :content
+
+ def initialize(site, in_source_dir: nil)
+ @site = site
+ @content = {}
+ @entry_filter = EntryFilter.new(site)
+ @in_source_dir = in_source_dir || @site.method(:in_source_dir)
+ @source_dir = @in_source_dir.call("/")
+ end
+
+ # Read all the files in <dir> and adds them to @content
+ #
+ # dir - The String relative path of the directory to read.
+ #
+ # Returns @content, a Hash of the .yaml, .yml,
+ # .json, and .csv files in the base directory
+ def read(dir)
+ base = @in_source_dir.call(dir)
+ read_data_to(base, @content)
+ @content
+ end
+
+ # Read and parse all .yaml, .yml, .json, .csv and .tsv
+ # files under <dir> and add them to the <data> variable.
+ #
+ # dir - The string absolute path of the directory to read.
+ # data - The variable to which data will be added.
+ #
+ # Returns nothing
+ def read_data_to(dir, data)
+ return unless File.directory?(dir) && !@entry_filter.symlink?(dir)
+
+ entries = Dir.chdir(dir) do
+ Dir["*.{yaml,yml,json,csv,tsv}"] + Dir["*"].select { |fn| File.directory?(fn) }
+ end
+
+ entries.each do |entry|
+ path = @in_source_dir.call(dir, entry)
+ next if @entry_filter.symlink?(path)
+
+ if File.directory?(path)
+ read_data_to(path, data[sanitize_filename(entry)] = {})
+ else
+ key = sanitize_filename(File.basename(entry, ".*"))
+ data[key] = read_data_file(path)
+ end
+ end
+ end
+
+ # Determines how to read a data file.
+ #
+ # Returns the contents of the data file.
+ def read_data_file(path)
+ Jekyll.logger.debug "Reading:", path.sub(@source_dir, "")
+
+ case File.extname(path).downcase
+ when ".csv"
+ CSV.read(path, **csv_config).map { |row| convert_row(row) }
+ when ".tsv"
+ CSV.read(path, **tsv_config).map { |row| convert_row(row) }
+ else
+ SafeYAML.load_file(path)
+ end
+ end
+
+ def sanitize_filename(name)
+ name.gsub(%r![^\w\s-]+|(?<=^|\b\s)\s+(?=$|\s?\b)!, "")
+ .gsub(%r!\s+!, "_")
+ end
+
+ private
+
+ # @return [Hash]
+ def csv_config
+ @csv_config ||= read_config("csv_reader")
+ end
+
+ # @return [Hash]
+ def tsv_config
+ @tsv_config ||= read_config("tsv_reader", { :col_sep => "\t" })
+ end
+
+ # @param config_key [String]
+ # @param overrides [Hash]
+ # @return [Hash]
+ # @see https://ruby-doc.org/stdlib-2.5.0/libdoc/csv/rdoc/CSV.html#Converters
+ def read_config(config_key, overrides = {})
+ reader_config = config[config_key] || {}
+
+ defaults = {
+ :converters => reader_config.fetch("csv_converters", []).map(&:to_sym),
+ :headers => reader_config.fetch("headers", true),
+ :encoding => reader_config.fetch("encoding", config["encoding"]),
+ }
+
+ defaults.merge(overrides)
+ end
+
+ def config
+ @config ||= site.config
+ end
+
+ # @param row [Array, CSV::Row]
+ # @return [Array, Hash]
+ def convert_row(row)
+ row.instance_of?(CSV::Row) ? row.to_hash : row
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/layout_reader.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/layout_reader.rb
new file mode 100644
index 0000000..981867b
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/layout_reader.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class LayoutReader
+ attr_reader :site
+
+ def initialize(site)
+ @site = site
+ @layouts = {}
+ end
+
+ def read
+ layout_entries.each do |layout_file|
+ @layouts[layout_name(layout_file)] = \
+ Layout.new(site, layout_directory, layout_file)
+ end
+
+ theme_layout_entries.each do |layout_file|
+ @layouts[layout_name(layout_file)] ||= \
+ Layout.new(site, theme_layout_directory, layout_file)
+ end
+
+ @layouts
+ end
+
+ def layout_directory
+ @layout_directory ||= site.in_source_dir(site.config["layouts_dir"])
+ end
+
+ def theme_layout_directory
+ @theme_layout_directory ||= site.theme.layouts_path if site.theme
+ end
+
+ private
+
+ def layout_entries
+ entries_in layout_directory
+ end
+
+ def theme_layout_entries
+ theme_layout_directory ? entries_in(theme_layout_directory) : []
+ end
+
+ def entries_in(dir)
+ entries = []
+ within(dir) do
+ entries = EntryFilter.new(site).filter(Dir["**/*.*"])
+ end
+ entries
+ end
+
+ def layout_name(file)
+ file.split(".")[0..-2].join(".")
+ end
+
+ def within(directory)
+ return unless File.exist?(directory)
+
+ Dir.chdir(directory) { yield }
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/page_reader.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/page_reader.rb
new file mode 100644
index 0000000..e72f767
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/page_reader.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class PageReader
+ attr_reader :site, :dir, :unfiltered_content
+
+ def initialize(site, dir)
+ @site = site
+ @dir = dir
+ @unfiltered_content = []
+ end
+
+ # Create a new `Jekyll::Page` object for each entry in a given array.
+ #
+ # files - An array of file names inside `@dir`
+ #
+ # Returns an array of publishable `Jekyll::Page` objects.
+ def read(files)
+ files.each do |page|
+ @unfiltered_content << Page.new(@site, @site.source, @dir, page)
+ end
+ @unfiltered_content.select { |page| site.publisher.publish?(page) }
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/post_reader.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/post_reader.rb
new file mode 100644
index 0000000..25c5f98
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/post_reader.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class PostReader
+ attr_reader :site, :unfiltered_content
+
+ def initialize(site)
+ @site = site
+ end
+
+ # Read all the files in <source>/<dir>/_drafts and create a new
+ # Document object with each one.
+ #
+ # dir - The String relative path of the directory to read.
+ #
+ # Returns nothing.
+ def read_drafts(dir)
+ read_publishable(dir, "_drafts", Document::DATELESS_FILENAME_MATCHER)
+ end
+
+ # Read all the files in <source>/<dir>/_posts and create a new Document
+ # object with each one.
+ #
+ # dir - The String relative path of the directory to read.
+ #
+ # Returns nothing.
+ def read_posts(dir)
+ read_publishable(dir, "_posts", Document::DATE_FILENAME_MATCHER)
+ end
+
+ # Read all the files in <source>/<dir>/<magic_dir> and create a new
+ # Document object with each one insofar as it matches the regexp matcher.
+ #
+ # dir - The String relative path of the directory to read.
+ #
+ # Returns nothing.
+ def read_publishable(dir, magic_dir, matcher)
+ read_content(dir, magic_dir, matcher)
+ .tap { |docs| docs.each(&:read) }
+ .select { |doc| processable?(doc) }
+ end
+
+ # Read all the content files from <source>/<dir>/magic_dir
+ # and return them with the type klass.
+ #
+ # dir - The String relative path of the directory to read.
+ # magic_dir - The String relative directory to <dir>,
+ # looks for content here.
+ # klass - The return type of the content.
+ #
+ # Returns klass type of content files
+ def read_content(dir, magic_dir, matcher)
+ @site.reader.get_entries(dir, magic_dir).map do |entry|
+ next unless matcher.match?(entry)
+
+ path = @site.in_source_dir(File.join(dir, magic_dir, entry))
+ Document.new(path,
+ :site => @site,
+ :collection => @site.posts)
+ end.tap(&:compact!)
+ end
+
+ private
+
+ def processable?(doc)
+ if doc.content.nil?
+ Jekyll.logger.debug "Skipping:", "Content in #{doc.relative_path} is nil"
+ false
+ elsif !doc.content.valid_encoding?
+ Jekyll.logger.debug "Skipping:", "#{doc.relative_path} is not valid UTF-8"
+ false
+ else
+ publishable?(doc)
+ end
+ end
+
+ def publishable?(doc)
+ site.publisher.publish?(doc).tap do |will_publish|
+ if !will_publish && site.publisher.hidden_in_the_future?(doc)
+ Jekyll.logger.warn "Skipping:", "#{doc.relative_path} has a future date"
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/static_file_reader.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/static_file_reader.rb
new file mode 100644
index 0000000..5c8a677
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/static_file_reader.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class StaticFileReader
+ attr_reader :site, :dir, :unfiltered_content
+
+ def initialize(site, dir)
+ @site = site
+ @dir = dir
+ @unfiltered_content = []
+ end
+
+ # Create a new StaticFile object for every entry in a given list of basenames.
+ #
+ # files - an array of file basenames.
+ #
+ # Returns an array of static files.
+ def read(files)
+ files.each do |file|
+ @unfiltered_content << StaticFile.new(@site, @site.source, @dir, file)
+ end
+ @unfiltered_content
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/theme_assets_reader.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/theme_assets_reader.rb
new file mode 100644
index 0000000..b20a3a0
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/readers/theme_assets_reader.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class ThemeAssetsReader
+ attr_reader :site
+
+ def initialize(site)
+ @site = site
+ end
+
+ def read
+ return unless site.theme&.assets_path
+
+ Find.find(site.theme.assets_path) do |path|
+ next if File.directory?(path)
+
+ if File.symlink?(path)
+ Jekyll.logger.warn "Theme reader:", "Ignored symlinked asset: #{path}"
+ else
+ read_theme_asset(path)
+ end
+ end
+ end
+
+ private
+
+ def read_theme_asset(path)
+ base = site.theme.root
+ dir = File.dirname(path.sub("#{site.theme.root}/", ""))
+ name = File.basename(path)
+
+ if Utils.has_yaml_header?(path)
+ append_unless_exists site.pages,
+ Jekyll::Page.new(site, base, dir, name)
+ else
+ append_unless_exists site.static_files,
+ Jekyll::StaticFile.new(site, base, "/#{dir}", name)
+ end
+ end
+
+ def append_unless_exists(haystack, new_item)
+ if haystack.any? { |file| file.relative_path == new_item.relative_path }
+ Jekyll.logger.debug "Theme:",
+ "Ignoring #{new_item.relative_path} in theme due to existing file " \
+ "with that path in site."
+ return
+ end
+
+ haystack << new_item
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/regenerator.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/regenerator.rb
new file mode 100644
index 0000000..88c6a81
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/regenerator.rb
@@ -0,0 +1,195 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Regenerator
+ attr_reader :site, :metadata, :cache
+ attr_accessor :disabled
+ private :disabled, :disabled=
+
+ def initialize(site)
+ @site = site
+
+ # Read metadata from file
+ read_metadata
+
+ # Initialize cache to an empty hash
+ clear_cache
+ end
+
+ # Checks if a renderable object needs to be regenerated
+ #
+ # Returns a boolean.
+ def regenerate?(document)
+ return true if disabled
+
+ case document
+ when Page
+ regenerate_page?(document)
+ when Document
+ regenerate_document?(document)
+ else
+ source_path = document.respond_to?(:path) ? document.path : nil
+ dest_path = document.destination(@site.dest) if document.respond_to?(:destination)
+ source_modified_or_dest_missing?(source_path, dest_path)
+ end
+ end
+
+ # Add a path to the metadata
+ #
+ # Returns true, also on failure.
+ def add(path)
+ return true unless File.exist?(path)
+
+ metadata[path] = {
+ "mtime" => File.mtime(path),
+ "deps" => [],
+ }
+ cache[path] = true
+ end
+
+ # Force a path to regenerate
+ #
+ # Returns true.
+ def force(path)
+ cache[path] = true
+ end
+
+ # Clear the metadata and cache
+ #
+ # Returns nothing
+ def clear
+ @metadata = {}
+ clear_cache
+ end
+
+ # Clear just the cache
+ #
+ # Returns nothing
+ def clear_cache
+ @cache = {}
+ end
+
+ # Checks if the source has been modified or the
+ # destination is missing
+ #
+ # returns a boolean
+ def source_modified_or_dest_missing?(source_path, dest_path)
+ modified?(source_path) || (dest_path && !File.exist?(dest_path))
+ end
+
+ # Checks if a path's (or one of its dependencies)
+ # mtime has changed
+ #
+ # Returns a boolean.
+ def modified?(path)
+ return true if disabled?
+
+ # objects that don't have a path are always regenerated
+ return true if path.nil?
+
+ # Check for path in cache
+ return cache[path] if cache.key? path
+
+ if metadata[path]
+ # If we have seen this file before,
+ # check if it or one of its dependencies has been modified
+ existing_file_modified?(path)
+ else
+ # If we have not seen this file before, add it to the metadata and regenerate it
+ add(path)
+ end
+ end
+
+ # Add a dependency of a path
+ #
+ # Returns nothing.
+ def add_dependency(path, dependency)
+ return if metadata[path].nil? || disabled
+
+ unless metadata[path]["deps"].include? dependency
+ metadata[path]["deps"] << dependency
+ add(dependency) unless metadata.include?(dependency)
+ end
+ regenerate? dependency
+ end
+
+ # Write the metadata to disk
+ #
+ # Returns nothing.
+ def write_metadata
+ unless disabled?
+ Jekyll.logger.debug "Writing Metadata:", ".jekyll-metadata"
+ File.binwrite(metadata_file, Marshal.dump(metadata))
+ end
+ end
+
+ # Produce the absolute path of the metadata file
+ #
+ # Returns the String path of the file.
+ def metadata_file
+ @metadata_file ||= site.in_source_dir(".jekyll-metadata")
+ end
+
+ # Check if metadata has been disabled
+ #
+ # Returns a Boolean (true for disabled, false for enabled).
+ def disabled?
+ self.disabled = !site.incremental? if disabled.nil?
+ disabled
+ end
+
+ private
+
+ # Read metadata from the metadata file, if no file is found,
+ # initialize with an empty hash
+ #
+ # Returns the read metadata.
+ def read_metadata
+ @metadata =
+ if !disabled? && File.file?(metadata_file)
+ content = File.binread(metadata_file)
+
+ begin
+ Marshal.load(content)
+ rescue TypeError
+ SafeYAML.load(content)
+ rescue ArgumentError => e
+ Jekyll.logger.warn("Failed to load #{metadata_file}: #{e}")
+ {}
+ end
+ else
+ {}
+ end
+ end
+
+ def regenerate_page?(document)
+ document.asset_file? || document.data["regenerate"] ||
+ source_modified_or_dest_missing?(
+ site.in_source_dir(document.relative_path), document.destination(@site.dest)
+ )
+ end
+
+ def regenerate_document?(document)
+ !document.write? || document.data["regenerate"] ||
+ source_modified_or_dest_missing?(
+ document.path, document.destination(@site.dest)
+ )
+ end
+
+ def existing_file_modified?(path)
+ # If one of this file dependencies have been modified,
+ # set the regeneration bit for both the dependency and the file to true
+ metadata[path]["deps"].each do |dependency|
+ return cache[dependency] = cache[path] = true if modified?(dependency)
+ end
+
+ if File.exist?(path) && metadata[path]["mtime"].eql?(File.mtime(path))
+ # If this file has not been modified, set the regeneration bit to false
+ cache[path] = false
+ else
+ # If it has been modified, set it to true
+ add(path)
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/related_posts.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/related_posts.rb
new file mode 100644
index 0000000..98fc488
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/related_posts.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class RelatedPosts
+ class << self
+ attr_accessor :lsi
+ end
+
+ attr_reader :post, :site
+
+ def initialize(post)
+ @post = post
+ @site = post.site
+ Jekyll::External.require_with_graceful_fail("classifier-reborn") if site.lsi
+ end
+
+ def build
+ return [] unless site.posts.docs.size > 1
+
+ if site.lsi
+ build_index
+ lsi_related_posts
+ else
+ most_recent_posts
+ end
+ end
+
+ def build_index
+ self.class.lsi ||= begin
+ lsi = ClassifierReborn::LSI.new(:auto_rebuild => false)
+ Jekyll.logger.info("Populating LSI...")
+
+ site.posts.docs.each do |x|
+ lsi.add_item(x)
+ end
+
+ Jekyll.logger.info("Rebuilding index...")
+ lsi.build_index
+ Jekyll.logger.info("")
+ lsi
+ end
+ end
+
+ def lsi_related_posts
+ self.class.lsi.find_related(post, 11)
+ end
+
+ def most_recent_posts
+ @most_recent_posts ||= (site.posts.docs.last(11).reverse! - [post]).first(10)
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/renderer.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/renderer.rb
new file mode 100644
index 0000000..c365a0d
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/renderer.rb
@@ -0,0 +1,263 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Renderer
+ attr_reader :document, :site
+ attr_writer :layouts, :payload
+
+ def initialize(site, document, site_payload = nil)
+ @site = site
+ @document = document
+ @payload = site_payload
+ @layouts = nil
+ end
+
+ # Fetches the payload used in Liquid rendering.
+ # It can be written with #payload=(new_payload)
+ # Falls back to site.site_payload if no payload is set.
+ #
+ # Returns a Jekyll::Drops::UnifiedPayloadDrop
+ def payload
+ @payload ||= site.site_payload
+ end
+
+ # The list of layouts registered for this Renderer.
+ # It can be written with #layouts=(new_layouts)
+ # Falls back to site.layouts if no layouts are registered.
+ #
+ # Returns a Hash of String => Jekyll::Layout identified
+ # as basename without the extension name.
+ def layouts
+ @layouts || site.layouts
+ end
+
+ # Determine which converters to use based on this document's
+ # extension.
+ #
+ # Returns Array of Converter instances.
+ def converters
+ @converters ||= site.converters.select { |c| c.matches(document.extname) }.tap(&:sort!)
+ end
+
+ # Determine the extname the outputted file should have
+ #
+ # Returns String the output extname including the leading period.
+ def output_ext
+ @output_ext ||= (permalink_ext || converter_output_ext)
+ end
+
+ # Prepare payload and render the document
+ #
+ # Returns String rendered document output
+ def run
+ Jekyll.logger.debug "Rendering:", document.relative_path
+
+ assign_pages!
+ assign_current_document!
+ assign_highlighter_options!
+ assign_layout_data!
+
+ Jekyll.logger.debug "Pre-Render Hooks:", document.relative_path
+ document.trigger_hooks(:pre_render, payload)
+
+ render_document
+ end
+
+ # Render the document.
+ #
+ # Returns String rendered document output
+ # rubocop: disable Metrics/AbcSize, Metrics/MethodLength
+ def render_document
+ info = {
+ :registers => { :site => site, :page => payload["page"] },
+ :strict_filters => liquid_options["strict_filters"],
+ :strict_variables => liquid_options["strict_variables"],
+ }
+
+ output = document.content
+ if document.render_with_liquid?
+ Jekyll.logger.debug "Rendering Liquid:", document.relative_path
+ output = render_liquid(output, payload, info, document.path)
+ end
+
+ Jekyll.logger.debug "Rendering Markup:", document.relative_path
+ output = convert(output.to_s)
+ document.content = output
+
+ Jekyll.logger.debug "Post-Convert Hooks:", document.relative_path
+ document.trigger_hooks(:post_convert)
+ output = document.content
+
+ if document.place_in_layout?
+ Jekyll.logger.debug "Rendering Layout:", document.relative_path
+ output = place_in_layouts(output, payload, info)
+ end
+
+ output
+ end
+ # rubocop: enable Metrics/AbcSize, Metrics/MethodLength
+
+ # Convert the document using the converters which match this renderer's document.
+ #
+ # Returns String the converted content.
+ def convert(content)
+ converters.reduce(content) do |output, converter|
+ converter.convert output
+ rescue StandardError => e
+ Jekyll.logger.error "Conversion error:",
+ "#{converter.class} encountered an error while " \
+ "converting '#{document.relative_path}':"
+ Jekyll.logger.error("", e.to_s)
+ raise e
+ end
+ end
+
+ # Render the given content with the payload and info
+ #
+ # content -
+ # payload -
+ # info -
+ # path - (optional) the path to the file, for use in ex
+ #
+ # Returns String the content, rendered by Liquid.
+ def render_liquid(content, payload, info, path = nil)
+ template = site.liquid_renderer.file(path).parse(content)
+ template.warnings.each do |e|
+ Jekyll.logger.warn "Liquid Warning:",
+ LiquidRenderer.format_error(e, path || document.relative_path)
+ end
+ template.render!(payload, info)
+ # rubocop: disable Lint/RescueException
+ rescue Exception => e
+ Jekyll.logger.error "Liquid Exception:",
+ LiquidRenderer.format_error(e, path || document.relative_path)
+ raise e
+ end
+ # rubocop: enable Lint/RescueException
+
+ # Checks if the layout specified in the document actually exists
+ #
+ # layout - the layout to check
+ #
+ # Returns Boolean true if the layout is invalid, false if otherwise
+ def invalid_layout?(layout)
+ !document.data["layout"].nil? && layout.nil? && !(document.is_a? Jekyll::Excerpt)
+ end
+
+ # Render layouts and place document content inside.
+ #
+ # Returns String rendered content
+ def place_in_layouts(content, payload, info)
+ output = content.dup
+ layout = layouts[document.data["layout"].to_s]
+ validate_layout(layout)
+
+ used = Set.new([layout])
+
+ # Reset the payload layout data to ensure it starts fresh for each page.
+ payload["layout"] = nil
+
+ while layout
+ output = render_layout(output, layout, info)
+ add_regenerator_dependencies(layout)
+
+ next unless (layout = site.layouts[layout.data["layout"]])
+ break if used.include?(layout)
+
+ used << layout
+ end
+ output
+ end
+
+ private
+
+ # Checks if the layout specified in the document actually exists
+ #
+ # layout - the layout to check
+ # Returns nothing
+ def validate_layout(layout)
+ return unless invalid_layout?(layout)
+
+ Jekyll.logger.warn "Build Warning:", "Layout '#{document.data["layout"]}' requested " \
+ "in #{document.relative_path} does not exist."
+ end
+
+ # Render layout content into document.output
+ #
+ # Returns String rendered content
+ def render_layout(output, layout, info)
+ payload["content"] = output
+ payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {})
+
+ render_liquid(
+ layout.content,
+ payload,
+ info,
+ layout.path
+ )
+ end
+
+ def add_regenerator_dependencies(layout)
+ return unless document.write?
+
+ site.regenerator.add_dependency(
+ site.in_source_dir(document.path),
+ layout.path
+ )
+ end
+
+ # Set page content to payload and assign pager if document has one.
+ #
+ # Returns nothing
+ def assign_pages!
+ payload["page"] = document.to_liquid
+ payload["paginator"] = (document.pager.to_liquid if document.respond_to?(:pager))
+ end
+
+ # Set related posts to payload if document is a post.
+ #
+ # Returns nothing
+ def assign_current_document!
+ payload["site"].current_document = document
+ end
+
+ # Set highlighter prefix and suffix
+ #
+ # Returns nothing
+ def assign_highlighter_options!
+ payload["highlighter_prefix"] = converters.first.highlighter_prefix
+ payload["highlighter_suffix"] = converters.first.highlighter_suffix
+ end
+
+ def assign_layout_data!
+ layout = layouts[document.data["layout"]]
+ payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {}) if layout
+ end
+
+ def permalink_ext
+ document_permalink = document.permalink
+ if document_permalink && !document_permalink.end_with?("/")
+ permalink_ext = File.extname(document_permalink)
+ permalink_ext unless permalink_ext.empty?
+ end
+ end
+
+ def converter_output_ext
+ if output_exts.size == 1
+ output_exts.last
+ else
+ output_exts[-2]
+ end
+ end
+
+ def output_exts
+ @output_exts ||= converters.map do |c|
+ c.output_ext(document.extname)
+ end.tap(&:compact!)
+ end
+
+ def liquid_options
+ @liquid_options ||= site.config["liquid"]
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/site.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/site.rb
new file mode 100644
index 0000000..adec4cc
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/site.rb
@@ -0,0 +1,576 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Site
+ attr_accessor :baseurl, :converters, :data, :drafts, :exclude,
+ :file_read_opts, :future, :gems, :generators, :highlighter,
+ :include, :inclusions, :keep_files, :layouts, :limit_posts,
+ :lsi, :pages, :permalink_style, :plugin_manager, :plugins,
+ :reader, :safe, :show_drafts, :static_files, :theme, :time,
+ :unpublished
+
+ attr_reader :cache_dir, :config, :dest, :filter_cache, :includes_load_paths,
+ :liquid_renderer, :profiler, :regenerator, :source
+
+ # Public: Initialize a new Site.
+ #
+ # config - A Hash containing site configuration details.
+ def initialize(config)
+ # Source and destination may not be changed after the site has been created.
+ @source = File.expand_path(config["source"]).freeze
+ @dest = File.expand_path(config["destination"]).freeze
+
+ self.config = config
+
+ @cache_dir = in_source_dir(config["cache_dir"])
+ @filter_cache = {}
+
+ @reader = Reader.new(self)
+ @profiler = Profiler.new(self)
+ @regenerator = Regenerator.new(self)
+ @liquid_renderer = LiquidRenderer.new(self)
+
+ Jekyll.sites << self
+
+ reset
+ setup
+
+ Jekyll::Hooks.trigger :site, :after_init, self
+ end
+
+ # Public: Set the site's configuration. This handles side-effects caused by
+ # changing values in the configuration.
+ #
+ # config - a Jekyll::Configuration, containing the new configuration.
+ #
+ # Returns the new configuration.
+ def config=(config)
+ @config = config.clone
+
+ %w(safe lsi highlighter baseurl exclude include future unpublished
+ show_drafts limit_posts keep_files).each do |opt|
+ send(:"#{opt}=", config[opt])
+ end
+
+ # keep using `gems` to avoid breaking change
+ self.gems = config["plugins"]
+
+ configure_cache
+ configure_plugins
+ configure_theme
+ configure_include_paths
+ configure_file_read_opts
+
+ self.permalink_style = config["permalink"].to_sym
+
+ # Read in a _config.yml from the current theme-gem at the very end.
+ @config = load_theme_configuration(config) if theme
+ @config
+ end
+
+ # Public: Read, process, and write this Site to output.
+ #
+ # Returns nothing.
+ def process
+ return profiler.profile_process if config["profile"]
+
+ reset
+ read
+ generate
+ render
+ cleanup
+ write
+ end
+
+ def print_stats
+ Jekyll.logger.info @liquid_renderer.stats_table
+ end
+
+ # rubocop:disable Metrics/AbcSize
+ # rubocop:disable Metrics/MethodLength
+ #
+ # Reset Site details.
+ #
+ # Returns nothing
+ def reset
+ self.time = if config["time"]
+ Utils.parse_date(config["time"].to_s, "Invalid time in _config.yml.")
+ else
+ Time.now
+ end
+ self.layouts = {}
+ self.inclusions = {}
+ self.pages = []
+ self.static_files = []
+ self.data = {}
+ @post_attr_hash = {}
+ @site_data = nil
+ @collections = nil
+ @documents = nil
+ @docs_to_write = nil
+ @regenerator.clear_cache
+ @liquid_renderer.reset
+ @site_cleaner = nil
+ frontmatter_defaults.reset
+
+ raise ArgumentError, "limit_posts must be a non-negative number" if limit_posts.negative?
+
+ Jekyll::Cache.clear_if_config_changed config
+ Jekyll::Hooks.trigger :site, :after_reset, self
+ nil
+ end
+ # rubocop:enable Metrics/MethodLength
+ # rubocop:enable Metrics/AbcSize
+
+ # Load necessary libraries, plugins, converters, and generators.
+ #
+ # Returns nothing.
+ def setup
+ ensure_not_in_dest
+
+ plugin_manager.conscientious_require
+
+ self.converters = instantiate_subclasses(Jekyll::Converter)
+ self.generators = instantiate_subclasses(Jekyll::Generator)
+ end
+
+ # Check that the destination dir isn't the source dir or a directory
+ # parent to the source dir.
+ def ensure_not_in_dest
+ dest_pathname = Pathname.new(dest)
+ Pathname.new(source).ascend do |path|
+ if path == dest_pathname
+ raise Errors::FatalException,
+ "Destination directory cannot be or contain the Source directory."
+ end
+ end
+ end
+
+ # The list of collections and their corresponding Jekyll::Collection instances.
+ # If config['collections'] is set, a new instance is created
+ # for each item in the collection, a new hash is returned otherwise.
+ #
+ # Returns a Hash containing collection name-to-instance pairs.
+ def collections
+ @collections ||= collection_names.each_with_object({}) do |name, hsh|
+ hsh[name] = Jekyll::Collection.new(self, name)
+ end
+ end
+
+ # The list of collection names.
+ #
+ # Returns an array of collection names from the configuration,
+ # or an empty array if the `collections` key is not set.
+ def collection_names
+ case config["collections"]
+ when Hash
+ config["collections"].keys
+ when Array
+ config["collections"]
+ when nil
+ []
+ else
+ raise ArgumentError, "Your `collections` key must be a hash or an array."
+ end
+ end
+
+ # Read Site data from disk and load it into internal data structures.
+ #
+ # Returns nothing.
+ def read
+ reader.read
+ limit_posts!
+ Jekyll::Hooks.trigger :site, :post_read, self
+ nil
+ end
+
+ # Run each of the Generators.
+ #
+ # Returns nothing.
+ def generate
+ generators.each do |generator|
+ start = Time.now
+ generator.generate(self)
+ Jekyll.logger.debug "Generating:",
+ "#{generator.class} finished in #{Time.now - start} seconds."
+ end
+ nil
+ end
+
+ # Render the site to the destination.
+ #
+ # Returns nothing.
+ def render
+ relative_permalinks_are_deprecated
+
+ payload = site_payload
+
+ Jekyll::Hooks.trigger :site, :pre_render, self, payload
+
+ render_docs(payload)
+ render_pages(payload)
+
+ Jekyll::Hooks.trigger :site, :post_render, self, payload
+ nil
+ end
+
+ # Remove orphaned files and empty directories in destination.
+ #
+ # Returns nothing.
+ def cleanup
+ site_cleaner.cleanup!
+ nil
+ end
+
+ # Write static files, pages, and posts.
+ #
+ # Returns nothing.
+ def write
+ Jekyll::Commands::Doctor.conflicting_urls(self)
+ each_site_file do |item|
+ item.write(dest) if regenerator.regenerate?(item)
+ end
+ regenerator.write_metadata
+ Jekyll::Hooks.trigger :site, :post_write, self
+ nil
+ end
+
+ def posts
+ collections["posts"] ||= Collection.new(self, "posts")
+ end
+
+ # Construct a Hash of Posts indexed by the specified Post attribute.
+ #
+ # post_attr - The String name of the Post attribute.
+ #
+ # Examples
+ #
+ # post_attr_hash('categories')
+ # # => { 'tech' => [<Post A>, <Post B>],
+ # # 'ruby' => [<Post B>] }
+ #
+ # Returns the Hash: { attr => posts } where
+ # attr - One of the values for the requested attribute.
+ # posts - The Array of Posts with the given attr value.
+ def post_attr_hash(post_attr)
+ # Build a hash map based on the specified post attribute ( post attr =>
+ # array of posts ) then sort each array in reverse order.
+ @post_attr_hash[post_attr] ||= begin
+ hash = Hash.new { |h, key| h[key] = [] }
+ posts.docs.each do |p|
+ p.data[post_attr]&.each { |t| hash[t] << p }
+ end
+ hash.each_value { |posts| posts.sort!.reverse! }
+ hash
+ end
+ end
+
+ def tags
+ post_attr_hash("tags")
+ end
+
+ def categories
+ post_attr_hash("categories")
+ end
+
+ # Prepare site data for site payload. The method maintains backward compatibility
+ # if the key 'data' is already used in _config.yml.
+ #
+ # Returns the Hash to be hooked to site.data.
+ def site_data
+ @site_data ||= (config["data"] || data)
+ end
+
+ # The Hash payload containing site-wide data.
+ #
+ # Returns the Hash: { "site" => data } where data is a Hash with keys:
+ # "time" - The Time as specified in the configuration or the
+ # current time if none was specified.
+ # "posts" - The Array of Posts, sorted chronologically by post date
+ # and then title.
+ # "pages" - The Array of all Pages.
+ # "html_pages" - The Array of HTML Pages.
+ # "categories" - The Hash of category values and Posts.
+ # See Site#post_attr_hash for type info.
+ # "tags" - The Hash of tag values and Posts.
+ # See Site#post_attr_hash for type info.
+ def site_payload
+ Drops::UnifiedPayloadDrop.new self
+ end
+ alias_method :to_liquid, :site_payload
+
+ # Get the implementation class for the given Converter.
+ # Returns the Converter instance implementing the given Converter.
+ # klass - The Class of the Converter to fetch.
+ def find_converter_instance(klass)
+ @find_converter_instance ||= {}
+ @find_converter_instance[klass] ||= converters.find do |converter|
+ converter.instance_of?(klass)
+ end || \
+ raise("No Converters found for #{klass}")
+ end
+
+ # klass - class or module containing the subclasses.
+ # Returns array of instances of subclasses of parameter.
+ # Create array of instances of the subclasses of the class or module
+ # passed in as argument.
+
+ def instantiate_subclasses(klass)
+ klass.descendants.select { |c| !safe || c.safe }.tap do |result|
+ result.sort!
+ result.map! { |c| c.new(config) }
+ end
+ end
+
+ # Warns the user if permanent links are relative to the parent
+ # directory. As this is a deprecated function of Jekyll.
+ #
+ # Returns
+ def relative_permalinks_are_deprecated
+ if config["relative_permalinks"]
+ Jekyll.logger.abort_with "Since v3.0, permalinks for pages " \
+ "in subfolders must be relative to the " \
+ "site source directory, not the parent " \
+ "directory. Check https://jekyllrb.com/docs/upgrading/ " \
+ "for more info."
+ end
+ end
+
+ # Get the to be written documents
+ #
+ # Returns an Array of Documents which should be written
+ def docs_to_write
+ documents.select(&:write?)
+ end
+
+ # Get the to be written static files
+ #
+ # Returns an Array of StaticFiles which should be written
+ def static_files_to_write
+ static_files.select(&:write?)
+ end
+
+ # Get all the documents
+ #
+ # Returns an Array of all Documents
+ def documents
+ collections.each_with_object(Set.new) do |(_, collection), set|
+ set.merge(collection.docs).merge(collection.files)
+ end.to_a
+ end
+
+ def each_site_file
+ pages.each { |page| yield page }
+ static_files.each { |file| yield(file) if file.write? }
+ collections.each_value { |coll| coll.docs.each { |doc| yield(doc) if doc.write? } }
+ end
+
+ # Returns the FrontmatterDefaults or creates a new FrontmatterDefaults
+ # if it doesn't already exist.
+ #
+ # Returns The FrontmatterDefaults
+ def frontmatter_defaults
+ @frontmatter_defaults ||= FrontmatterDefaults.new(self)
+ end
+
+ # Whether to perform a full rebuild without incremental regeneration
+ #
+ # Returns a Boolean: true for a full rebuild, false for normal build
+ def incremental?(override = {})
+ override["incremental"] || config["incremental"]
+ end
+
+ # Returns the publisher or creates a new publisher if it doesn't
+ # already exist.
+ #
+ # Returns The Publisher
+ def publisher
+ @publisher ||= Publisher.new(self)
+ end
+
+ # Public: Prefix a given path with the source directory.
+ #
+ # paths - (optional) path elements to a file or directory within the
+ # source directory
+ #
+ # Returns a path which is prefixed with the source directory.
+ def in_source_dir(*paths)
+ paths.reduce(source) do |base, path|
+ Jekyll.sanitized_path(base, path)
+ end
+ end
+
+ # Public: Prefix a given path with the theme directory.
+ #
+ # paths - (optional) path elements to a file or directory within the
+ # theme directory
+ #
+ # Returns a path which is prefixed with the theme root directory.
+ def in_theme_dir(*paths)
+ return nil unless theme
+
+ paths.reduce(theme.root) do |base, path|
+ Jekyll.sanitized_path(base, path)
+ end
+ end
+
+ # Public: Prefix a given path with the destination directory.
+ #
+ # paths - (optional) path elements to a file or directory within the
+ # destination directory
+ #
+ # Returns a path which is prefixed with the destination directory.
+ def in_dest_dir(*paths)
+ paths.reduce(dest) do |base, path|
+ Jekyll.sanitized_path(base, path)
+ end
+ end
+
+ # Public: Prefix a given path with the cache directory.
+ #
+ # paths - (optional) path elements to a file or directory within the
+ # cache directory
+ #
+ # Returns a path which is prefixed with the cache directory.
+ def in_cache_dir(*paths)
+ paths.reduce(cache_dir) do |base, path|
+ Jekyll.sanitized_path(base, path)
+ end
+ end
+
+ # Public: The full path to the directory that houses all the collections registered
+ # with the current site.
+ #
+ # Returns the source directory or the absolute path to the custom collections_dir
+ def collections_path
+ dir_str = config["collections_dir"]
+ @collections_path ||= dir_str.empty? ? source : in_source_dir(dir_str)
+ end
+
+ # Public
+ #
+ # Returns the object as a debug String.
+ def inspect
+ "#<#{self.class} @source=#{@source}>"
+ end
+
+ private
+
+ def load_theme_configuration(config)
+ return config if config["ignore_theme_config"] == true
+
+ theme_config_file = in_theme_dir("_config.yml")
+ return config unless File.exist?(theme_config_file)
+
+ # Bail out if the theme_config_file is a symlink file irrespective of safe mode
+ return config if File.symlink?(theme_config_file)
+
+ theme_config = SafeYAML.load_file(theme_config_file)
+ return config unless theme_config.is_a?(Hash)
+
+ Jekyll.logger.info "Theme Config file:", theme_config_file
+
+ # theme_config should not be overriding Jekyll's defaults
+ theme_config.delete_if { |key, _| Configuration::DEFAULTS.key?(key) }
+
+ # Override theme_config with existing config and return the result.
+ # Additionally ensure we return a `Jekyll::Configuration` instance instead of a Hash.
+ Utils.deep_merge_hashes(theme_config, config)
+ .each_with_object(Jekyll::Configuration.new) do |(key, value), conf|
+ conf[key] = value
+ end
+ end
+
+ # Limits the current posts; removes the posts which exceed the limit_posts
+ #
+ # Returns nothing
+ def limit_posts!
+ if limit_posts.positive?
+ limit = [posts.docs.length, limit_posts].min
+ posts.docs = posts.docs[-limit, limit]
+ end
+ end
+
+ # Returns the Cleaner or creates a new Cleaner if it doesn't
+ # already exist.
+ #
+ # Returns The Cleaner
+ def site_cleaner
+ @site_cleaner ||= Cleaner.new(self)
+ end
+
+ def hide_cache_dir_from_git
+ @cache_gitignore_path ||= in_source_dir(config["cache_dir"], ".gitignore")
+ return if File.exist?(@cache_gitignore_path)
+
+ cache_dir_path = in_source_dir(config["cache_dir"])
+ FileUtils.mkdir_p(cache_dir_path) unless File.directory?(cache_dir_path)
+
+ File.open(@cache_gitignore_path, "wb") do |file|
+ file.puts("# ignore everything in this directory\n*")
+ end
+ end
+
+ # Disable Marshaling cache to disk in Safe Mode
+ def configure_cache
+ Jekyll::Cache.cache_dir = in_source_dir(config["cache_dir"], "Jekyll/Cache")
+ if safe || config["disable_disk_cache"]
+ Jekyll::Cache.disable_disk_cache!
+ else
+ hide_cache_dir_from_git
+ end
+ end
+
+ def configure_plugins
+ self.plugin_manager = Jekyll::PluginManager.new(self)
+ self.plugins = plugin_manager.plugins_path
+ end
+
+ def configure_theme
+ self.theme = nil
+ return if config["theme"].nil?
+
+ self.theme =
+ if config["theme"].is_a?(String)
+ Jekyll::Theme.new(config["theme"])
+ else
+ Jekyll.logger.warn "Theme:", "value of 'theme' in config should be String to use " \
+ "gem-based themes, but got #{config["theme"].class}"
+ nil
+ end
+ end
+
+ def configure_include_paths
+ @includes_load_paths = Array(in_source_dir(config["includes_dir"].to_s))
+ @includes_load_paths << theme.includes_path if theme&.includes_path
+ end
+
+ def configure_file_read_opts
+ self.file_read_opts = {}
+ file_read_opts[:encoding] = config["encoding"] if config["encoding"]
+ self.file_read_opts = Jekyll::Utils.merged_file_read_opts(self, {})
+ end
+
+ def render_docs(payload)
+ collections.each_value do |collection|
+ collection.docs.each do |document|
+ render_regenerated(document, payload)
+ end
+ end
+ end
+
+ def render_pages(payload)
+ pages.each do |page|
+ render_regenerated(page, payload)
+ end
+ end
+
+ def render_regenerated(document, payload)
+ return unless regenerator.regenerate?(document)
+
+ document.renderer.payload = payload
+ document.output = document.renderer.run
+ document.trigger_hooks(:post_render)
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/static_file.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/static_file.rb
new file mode 100644
index 0000000..13479b0
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/static_file.rb
@@ -0,0 +1,203 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class StaticFile
+ extend Forwardable
+
+ attr_reader :relative_path, :extname,
+ :type, # Returns the type of the collection if present, nil otherwise.
+ :name
+
+ def_delegator :to_liquid, :to_json, :to_json
+
+ class << self
+ # The cache of last modification times [path] -> mtime.
+ def mtimes
+ @mtimes ||= {}
+ end
+
+ def reset_cache
+ @mtimes = nil
+ end
+ end
+
+ # Initialize a new StaticFile.
+ #
+ # site - The Site.
+ # base - The String path to the <source>.
+ # dir - The String path between <source> and the file.
+ # name - The String filename of the file.
+ # rubocop: disable Metrics/ParameterLists
+ def initialize(site, base, dir, name, collection = nil)
+ @site = site
+ @base = base
+ @dir = dir
+ @name = name
+ @collection = collection
+ @relative_path = File.join(*[@dir, @name].compact)
+ @extname = File.extname(@name)
+ @type = @collection&.label&.to_sym
+ end
+ # rubocop: enable Metrics/ParameterLists
+
+ # Returns source file path.
+ def path
+ @path ||= if !@collection.nil? && !@site.config["collections_dir"].empty?
+ File.join(*[@base, @site.config["collections_dir"], @dir, @name].compact)
+ else
+ File.join(*[@base, @dir, @name].compact)
+ end
+ end
+
+ # Obtain destination path.
+ #
+ # dest - The String path to the destination dir.
+ #
+ # Returns destination file path.
+ def destination(dest)
+ @destination ||= {}
+ @destination[dest] ||= @site.in_dest_dir(dest, Jekyll::URL.unescape_path(url))
+ end
+
+ def destination_rel_dir
+ if @collection
+ File.dirname(url)
+ else
+ @dir
+ end
+ end
+
+ def modified_time
+ @modified_time ||= File.stat(path).mtime
+ end
+
+ # Returns last modification time for this file.
+ def mtime
+ modified_time.to_i
+ end
+
+ # Is source path modified?
+ #
+ # Returns true if modified since last write.
+ def modified?
+ self.class.mtimes[path] != mtime
+ end
+
+ # Whether to write the file to the filesystem
+ #
+ # Returns true unless the defaults for the destination path from
+ # _config.yml contain `published: false`.
+ def write?
+ publishable = defaults.fetch("published", true)
+ return publishable unless @collection
+
+ publishable && @collection.write?
+ end
+
+ # Write the static file to the destination directory (if modified).
+ #
+ # dest - The String path to the destination dir.
+ #
+ # Returns false if the file was not modified since last time (no-op).
+ def write(dest)
+ dest_path = destination(dest)
+ return false if File.exist?(dest_path) && !modified?
+
+ self.class.mtimes[path] = mtime
+
+ FileUtils.mkdir_p(File.dirname(dest_path))
+ FileUtils.rm(dest_path) if File.exist?(dest_path)
+ copy_file(dest_path)
+
+ true
+ end
+
+ def data
+ @data ||= @site.frontmatter_defaults.all(relative_path, type)
+ end
+
+ def to_liquid
+ @to_liquid ||= Drops::StaticFileDrop.new(self)
+ end
+
+ # Generate "basename without extension" and strip away any trailing periods.
+ # NOTE: `String#gsub` removes all trailing periods (in comparison to `String#chomp`)
+ def basename
+ @basename ||= File.basename(name, extname).gsub(%r!\.*\z!, "")
+ end
+
+ def placeholders
+ {
+ :collection => @collection.label,
+ :path => cleaned_relative_path,
+ :output_ext => "",
+ :name => basename,
+ :title => "",
+ }
+ end
+
+ # Similar to Jekyll::Document#cleaned_relative_path.
+ # Generates a relative path with the collection's directory removed when applicable
+ # and additionally removes any multiple periods in the string.
+ #
+ # NOTE: `String#gsub!` removes all trailing periods (in comparison to `String#chomp!`)
+ #
+ # Examples:
+ # When `relative_path` is "_methods/site/my-cool-avatar...png":
+ # cleaned_relative_path
+ # # => "/site/my-cool-avatar"
+ #
+ # Returns the cleaned relative path of the static file.
+ def cleaned_relative_path
+ @cleaned_relative_path ||= begin
+ cleaned = relative_path[0..-extname.length - 1]
+ cleaned.gsub!(%r!\.*\z!, "")
+ cleaned.sub!(@collection.relative_directory, "") if @collection
+ cleaned
+ end
+ end
+
+ # Applies a similar URL-building technique as Jekyll::Document that takes
+ # the collection's URL template into account. The default URL template can
+ # be overridden in the collection's configuration in _config.yml.
+ def url
+ @url ||= begin
+ base = if @collection.nil?
+ cleaned_relative_path
+ else
+ Jekyll::URL.new(
+ :template => @collection.url_template,
+ :placeholders => placeholders
+ )
+ end.to_s.chomp("/")
+ base << extname
+ end
+ end
+
+ # Returns the front matter defaults defined for the file's URL and/or type
+ # as defined in _config.yml.
+ def defaults
+ @defaults ||= @site.frontmatter_defaults.all url, type
+ end
+
+ # Returns a debug string on inspecting the static file.
+ # Includes only the relative path of the object.
+ def inspect
+ "#<#{self.class} @relative_path=#{relative_path.inspect}>"
+ end
+
+ private
+
+ def copy_file(dest_path)
+ if @site.safe || Jekyll.env == "production"
+ FileUtils.cp(path, dest_path)
+ else
+ FileUtils.copy_entry(path, dest_path)
+ end
+
+ unless File.symlink?(dest_path)
+ File.utime(self.class.mtimes[path], self.class.mtimes[path], dest_path)
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/stevenson.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/stevenson.rb
new file mode 100644
index 0000000..10e5a0b
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/stevenson.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Stevenson < ::Logger
+ def initialize
+ formatter = proc do |_, _, _, msg|
+ msg.to_s
+ end
+ super($stdout, :formatter => formatter)
+ end
+
+ def add(severity, message = nil, progname = nil)
+ severity ||= UNKNOWN
+ @logdev = logdevice(severity)
+
+ return true if @logdev.nil? || severity < @level
+
+ progname ||= @progname
+ if message.nil?
+ if block_given?
+ message = yield
+ else
+ message = progname
+ progname = @progname
+ end
+ end
+ @logdev.puts(
+ format_message(format_severity(severity), Time.now, progname, message)
+ )
+ true
+ end
+
+ # Log a +WARN+ message
+ def warn(progname = nil, &block)
+ add(WARN, nil, progname.yellow, &block)
+ end
+
+ # Log an +ERROR+ message
+ def error(progname = nil, &block)
+ add(ERROR, nil, progname.red, &block)
+ end
+
+ def close
+ # No LogDevice in use
+ end
+
+ private
+
+ def logdevice(severity)
+ if severity > INFO
+ $stderr
+ else
+ $stdout
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/highlight.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/highlight.rb
new file mode 100644
index 0000000..fcea81f
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/highlight.rb
@@ -0,0 +1,129 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Tags
+ class HighlightBlock < Liquid::Block
+ include Liquid::StandardFilters
+
+ # The regular expression syntax checker. Start with the language specifier.
+ # Follow that by zero or more space separated options that take one of three
+ # forms: name, name=value, or name="<quoted list>"
+ #
+ # <quoted list> is a space-separated list of numbers
+ SYNTAX = %r!^([a-zA-Z0-9.+#_-]+)((\s+\w+(=(\w+|"([0-9]+\s)*[0-9]+"))?)*)$!.freeze
+
+ def initialize(tag_name, markup, tokens)
+ super
+ if markup.strip =~ SYNTAX
+ @lang = Regexp.last_match(1).downcase
+ @highlight_options = parse_options(Regexp.last_match(2))
+ else
+ raise SyntaxError, <<~MSG
+ Syntax Error in tag 'highlight' while parsing the following markup:
+
+ #{markup}
+
+ Valid syntax: highlight <lang> [linenos] [mark_lines="3 4 5"]
+
+ See https://jekyllrb.com/docs/liquid/tags/#code-snippet-highlighting for more details.
+ MSG
+ end
+ end
+
+ LEADING_OR_TRAILING_LINE_TERMINATORS = %r!\A(\n|\r)+|(\n|\r)+\z!.freeze
+
+ def render(context)
+ prefix = context["highlighter_prefix"] || ""
+ suffix = context["highlighter_suffix"] || ""
+ code = super.to_s.gsub(LEADING_OR_TRAILING_LINE_TERMINATORS, "")
+
+ output =
+ case context.registers[:site].highlighter
+ when "rouge"
+ render_rouge(code)
+ when "pygments"
+ render_pygments(code, context)
+ else
+ render_codehighlighter(code)
+ end
+
+ rendered_output = add_code_tag(output)
+ prefix + rendered_output + suffix
+ end
+
+ private
+
+ OPTIONS_REGEX = %r!(?:\w="[^"]*"|\w=\w|\w)+!.freeze
+
+ def parse_options(input)
+ options = {}
+ return options if input.empty?
+
+ # Split along 3 possible forms -- key="<quoted list>", key=value, or key
+ input.scan(OPTIONS_REGEX) do |opt|
+ key, value = opt.split("=")
+ # If a quoted list, convert to array
+ if value&.include?('"')
+ value.delete!('"')
+ value = value.split
+ end
+ options[key.to_sym] = value || true
+ end
+
+ options[:linenos] = "inline" if options[:linenos] == true
+ options
+ end
+
+ def render_pygments(code, _context)
+ Jekyll.logger.warn "Warning:", "Highlight Tag no longer supports rendering with Pygments."
+ Jekyll.logger.warn "", "Using the default highlighter, Rouge, instead."
+ render_rouge(code)
+ end
+
+ def render_rouge(code)
+ require "rouge"
+ formatter = Rouge::Formatters::HTML.new
+ formatter = line_highlighter_formatter(formatter) if @highlight_options[:mark_lines]
+ formatter = table_formatter(formatter) if @highlight_options[:linenos]
+
+ lexer = Rouge::Lexer.find_fancy(@lang, code) || Rouge::Lexers::PlainText
+ formatter.format(lexer.lex(code))
+ end
+
+ def line_highlighter_formatter(formatter)
+ Rouge::Formatters::HTMLLineHighlighter.new(
+ formatter,
+ :highlight_lines => mark_lines
+ )
+ end
+
+ def mark_lines
+ value = @highlight_options[:mark_lines]
+ return value.map(&:to_i) if value.is_a?(Array)
+
+ raise SyntaxError, "Syntax Error for mark_lines declaration. Expected a " \
+ "double-quoted list of integers."
+ end
+
+ def table_formatter(formatter)
+ Rouge::Formatters::HTMLTable.new(
+ formatter,
+ :css_class => "highlight",
+ :gutter_class => "gutter",
+ :code_class => "code"
+ )
+ end
+
+ def render_codehighlighter(code)
+ h(code).strip
+ end
+
+ def add_code_tag(code)
+ code_attrs = %(class="language-#{@lang.tr("+", "-")}" data-lang="#{@lang}")
+ %(<figure class="highlight"><pre><code #{code_attrs}>#{code.chomp}</code></pre></figure>)
+ end
+ end
+ end
+end
+
+Liquid::Template.register_tag("highlight", Jekyll::Tags::HighlightBlock)
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/include.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/include.rb
new file mode 100644
index 0000000..6960952
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/include.rb
@@ -0,0 +1,275 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Tags
+ class IncludeTag < Liquid::Tag
+ VALID_SYNTAX = %r!
+ ([\w-]+)\s*=\s*
+ (?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w.-]+))
+ !x.freeze
+ VARIABLE_SYNTAX = %r!
+ (?<variable>[^{]*(\{\{\s*[\w\-.]+\s*(\|.*)?\}\}[^\s{}]*)+)
+ (?<params>.*)
+ !mx.freeze
+
+ FULL_VALID_SYNTAX = %r!\A\s*(?:#{VALID_SYNTAX}(?=\s|\z)\s*)*\z!.freeze
+ VALID_FILENAME_CHARS = %r!^[\w/.\-()+~\#@]+$!.freeze
+ INVALID_SEQUENCES = %r![./]{2,}!.freeze
+
+ def initialize(tag_name, markup, tokens)
+ super
+ markup = markup.strip
+ matched = markup.match(VARIABLE_SYNTAX)
+ if matched
+ @file = matched["variable"].strip
+ @params = matched["params"].strip
+ else
+ @file, @params = markup.split(%r!\s+!, 2)
+ end
+ validate_params if @params
+ @tag_name = tag_name
+ end
+
+ def syntax_example
+ "{% #{@tag_name} file.ext param='value' param2='value' %}"
+ end
+
+ def parse_params(context)
+ params = {}
+ @params.scan(VALID_SYNTAX) do |key, d_quoted, s_quoted, variable|
+ value = if d_quoted
+ d_quoted.include?('\\"') ? d_quoted.gsub('\\"', '"') : d_quoted
+ elsif s_quoted
+ s_quoted.include?("\\'") ? s_quoted.gsub("\\'", "'") : s_quoted
+ elsif variable
+ context[variable]
+ end
+
+ params[key] = value
+ end
+ params
+ end
+
+ def validate_file_name(file)
+ if INVALID_SEQUENCES.match?(file) || !VALID_FILENAME_CHARS.match?(file)
+ raise ArgumentError, <<~MSG
+ Invalid syntax for include tag. File contains invalid characters or sequences:
+
+ #{file}
+
+ Valid syntax:
+
+ #{syntax_example}
+
+ MSG
+ end
+ end
+
+ def validate_params
+ unless FULL_VALID_SYNTAX.match?(@params)
+ raise ArgumentError, <<~MSG
+ Invalid syntax for include tag:
+
+ #{@params}
+
+ Valid syntax:
+
+ #{syntax_example}
+
+ MSG
+ end
+ end
+
+ # Grab file read opts in the context
+ def file_read_opts(context)
+ context.registers[:site].file_read_opts
+ end
+
+ # Render the variable if required
+ def render_variable(context)
+ Liquid::Template.parse(@file).render(context) if VARIABLE_SYNTAX.match?(@file)
+ end
+
+ def tag_includes_dirs(context)
+ context.registers[:site].includes_load_paths.freeze
+ end
+
+ def locate_include_file(context, file, safe)
+ includes_dirs = tag_includes_dirs(context)
+ includes_dirs.each do |dir|
+ path = PathManager.join(dir, file)
+ return path if valid_include_file?(path, dir.to_s, safe)
+ end
+ raise IOError, could_not_locate_message(file, includes_dirs, safe)
+ end
+
+ def render(context)
+ site = context.registers[:site]
+
+ file = render_variable(context) || @file
+ validate_file_name(file)
+
+ path = locate_include_file(context, file, site.safe)
+ return unless path
+
+ add_include_to_dependency(site, path, context)
+
+ partial = load_cached_partial(path, context)
+
+ context.stack do
+ context["include"] = parse_params(context) if @params
+ begin
+ partial.render!(context)
+ rescue Liquid::Error => e
+ e.template_name = path
+ e.markup_context = "included " if e.markup_context.nil?
+ raise e
+ end
+ end
+ end
+
+ def add_include_to_dependency(site, path, context)
+ if context.registers[:page]&.key?("path")
+ site.regenerator.add_dependency(
+ site.in_source_dir(context.registers[:page]["path"]),
+ path
+ )
+ end
+ end
+
+ def load_cached_partial(path, context)
+ context.registers[:cached_partials] ||= {}
+ cached_partial = context.registers[:cached_partials]
+
+ if cached_partial.key?(path)
+ cached_partial[path]
+ else
+ unparsed_file = context.registers[:site]
+ .liquid_renderer
+ .file(path)
+ begin
+ cached_partial[path] = unparsed_file.parse(read_file(path, context))
+ rescue Liquid::Error => e
+ e.template_name = path
+ e.markup_context = "included " if e.markup_context.nil?
+ raise e
+ end
+ end
+ end
+
+ def valid_include_file?(path, dir, safe)
+ !outside_site_source?(path, dir, safe) && File.file?(path)
+ end
+
+ def outside_site_source?(path, dir, safe)
+ safe && !realpath_prefixed_with?(path, dir)
+ end
+
+ def realpath_prefixed_with?(path, dir)
+ File.exist?(path) && File.realpath(path).start_with?(dir)
+ rescue StandardError
+ false
+ end
+
+ # This method allows to modify the file content by inheriting from the class.
+ def read_file(file, context)
+ File.read(file, **file_read_opts(context))
+ end
+
+ private
+
+ def could_not_locate_message(file, includes_dirs, safe)
+ message = "Could not locate the included file '#{file}' in any of #{includes_dirs}. " \
+ "Ensure it exists in one of those directories and"
+ message + if safe
+ " is not a symlink as those are not allowed in safe mode."
+ else
+ ", if it is a symlink, does not point outside your site source."
+ end
+ end
+ end
+
+ # Do not inherit from this class.
+ # TODO: Merge into the `Jekyll::Tags::IncludeTag` in v5.0
+ class OptimizedIncludeTag < IncludeTag
+ def render(context)
+ @site ||= context.registers[:site]
+
+ file = render_variable(context) || @file
+ validate_file_name(file)
+
+ @site.inclusions[file] ||= locate_include_file(file)
+ inclusion = @site.inclusions[file]
+
+ add_include_to_dependency(inclusion, context) if @site.config["incremental"]
+
+ context.stack do
+ context["include"] = parse_params(context) if @params
+ inclusion.render(context)
+ end
+ end
+
+ private
+
+ def locate_include_file(file)
+ @site.includes_load_paths.each do |dir|
+ path = PathManager.join(dir, file)
+ return Inclusion.new(@site, dir, file) if valid_include_file?(path, dir)
+ end
+ raise IOError, could_not_locate_message(file, @site.includes_load_paths, @site.safe)
+ end
+
+ def valid_include_file?(path, dir)
+ File.file?(path) && !outside_scope?(path, dir)
+ end
+
+ def outside_scope?(path, dir)
+ @site.safe && !realpath_prefixed_with?(path, dir)
+ end
+
+ def realpath_prefixed_with?(path, dir)
+ File.realpath(path).start_with?(dir)
+ rescue StandardError
+ false
+ end
+
+ def add_include_to_dependency(inclusion, context)
+ page = context.registers[:page]
+ return unless page&.key?("path")
+
+ absolute_path = \
+ if page["collection"]
+ @site.in_source_dir(@site.config["collections_dir"], page["path"])
+ else
+ @site.in_source_dir(page["path"])
+ end
+
+ @site.regenerator.add_dependency(absolute_path, inclusion.path)
+ end
+ end
+
+ class IncludeRelativeTag < IncludeTag
+ def tag_includes_dirs(context)
+ Array(page_path(context)).freeze
+ end
+
+ def page_path(context)
+ page, site = context.registers.values_at(:page, :site)
+ return site.source unless page
+
+ site.in_source_dir File.dirname(resource_path(page, site))
+ end
+
+ private
+
+ def resource_path(page, site)
+ path = page["path"]
+ path = File.join(site.config["collections_dir"], path) if page["collection"]
+ path.delete_suffix("/#excerpt")
+ end
+ end
+ end
+end
+
+Liquid::Template.register_tag("include", Jekyll::Tags::OptimizedIncludeTag)
+Liquid::Template.register_tag("include_relative", Jekyll::Tags::IncludeRelativeTag)
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/link.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/link.rb
new file mode 100644
index 0000000..c986b5a
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/link.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Tags
+ class Link < Liquid::Tag
+ include Jekyll::Filters::URLFilters
+
+ class << self
+ def tag_name
+ name.split("::").last.downcase
+ end
+ end
+
+ def initialize(tag_name, relative_path, tokens)
+ super
+
+ @relative_path = relative_path.strip
+ end
+
+ def render(context)
+ @context = context
+ site = context.registers[:site]
+ relative_path = Liquid::Template.parse(@relative_path).render(context)
+ relative_path_with_leading_slash = PathManager.join("", relative_path)
+
+ site.each_site_file do |item|
+ return relative_url(item) if item.relative_path == relative_path
+ # This takes care of the case for static files that have a leading /
+ return relative_url(item) if item.relative_path == relative_path_with_leading_slash
+ end
+
+ raise ArgumentError, <<~MSG
+ Could not find document '#{relative_path}' in tag '#{self.class.tag_name}'.
+
+ Make sure the document exists and the path is correct.
+ MSG
+ end
+ end
+ end
+end
+
+Liquid::Template.register_tag(Jekyll::Tags::Link.tag_name, Jekyll::Tags::Link)
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/post_url.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/post_url.rb
new file mode 100644
index 0000000..7774d37
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/tags/post_url.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Tags
+ class PostComparer
+ MATCHER = %r!^(.+/)*(\d+-\d+-\d+)-(.*)$!.freeze
+
+ attr_reader :path, :date, :slug, :name
+
+ def initialize(name)
+ @name = name
+
+ all, @path, @date, @slug = *name.sub(%r!^/!, "").match(MATCHER)
+ unless all
+ raise Jekyll::Errors::InvalidPostNameError,
+ "'#{name}' does not contain valid date and/or title."
+ end
+
+ basename_pattern = "#{date}-#{Regexp.escape(slug)}\\.[^.]+"
+ @name_regex = %r!^_posts/#{path}#{basename_pattern}|^#{path}_posts/?#{basename_pattern}!
+ end
+
+ def post_date
+ @post_date ||= Utils.parse_date(
+ date,
+ "'#{date}' does not contain valid date and/or title."
+ )
+ end
+
+ def ==(other)
+ other.relative_path.match(@name_regex)
+ end
+
+ def deprecated_equality(other)
+ slug == post_slug(other) &&
+ post_date.year == other.date.year &&
+ post_date.month == other.date.month &&
+ post_date.day == other.date.day
+ end
+
+ private
+
+ # Construct the directory-aware post slug for a Jekyll::Post
+ #
+ # other - the Jekyll::Post
+ #
+ # Returns the post slug with the subdirectory (relative to _posts)
+ def post_slug(other)
+ path = other.basename.split("/")[0...-1].join("/")
+ if path.nil? || path == ""
+ other.data["slug"]
+ else
+ "#{path}/#{other.data["slug"]}"
+ end
+ end
+ end
+
+ class PostUrl < Liquid::Tag
+ include Jekyll::Filters::URLFilters
+
+ def initialize(tag_name, post, tokens)
+ super
+ @orig_post = post.strip
+ begin
+ @post = PostComparer.new(@orig_post)
+ rescue StandardError => e
+ raise Jekyll::Errors::PostURLError, <<~MSG
+ Could not parse name of post "#{@orig_post}" in tag 'post_url'.
+ Make sure the post exists and the name is correct.
+ #{e.class}: #{e.message}
+ MSG
+ end
+ end
+
+ def render(context)
+ @context = context
+ site = context.registers[:site]
+
+ site.posts.docs.each do |document|
+ return relative_url(document) if @post == document
+ end
+
+ # New matching method did not match, fall back to old method
+ # with deprecation warning if this matches
+
+ site.posts.docs.each do |document|
+ next unless @post.deprecated_equality document
+
+ Jekyll::Deprecator.deprecation_message(
+ "A call to '{% post_url #{@post.name} %}' did not match a post using the new " \
+ "matching method of checking name (path-date-slug) equality. Please make sure " \
+ "that you change this tag to match the post's name exactly."
+ )
+ return relative_url(document)
+ end
+
+ raise Jekyll::Errors::PostURLError, <<~MSG
+ Could not find post "#{@orig_post}" in tag 'post_url'.
+ Make sure the post exists and the name is correct.
+ MSG
+ end
+ end
+ end
+end
+
+Liquid::Template.register_tag("post_url", Jekyll::Tags::PostUrl)
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/theme.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/theme.rb
new file mode 100644
index 0000000..a3f2a94
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/theme.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class Theme
+ extend Forwardable
+ attr_reader :name
+
+ def_delegator :gemspec, :version, :version
+
+ def initialize(name)
+ @name = name.downcase.strip
+ Jekyll.logger.debug "Theme:", name
+ Jekyll.logger.debug "Theme source:", root
+ end
+
+ def root
+ # Must use File.realpath to resolve symlinks created by rbenv
+ # Otherwise, Jekyll.sanitized path with prepend the unresolved root
+ @root ||= File.realpath(gemspec.full_gem_path)
+ rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP
+ raise "Path #{gemspec.full_gem_path} does not exist, is not accessible or includes " \
+ "a symbolic link loop"
+ end
+
+ # The name of theme directory
+ def basename
+ @basename ||= File.basename(root)
+ end
+
+ def includes_path
+ @includes_path ||= path_for "_includes"
+ end
+
+ def layouts_path
+ @layouts_path ||= path_for "_layouts"
+ end
+
+ def sass_path
+ @sass_path ||= path_for "_sass"
+ end
+
+ def assets_path
+ @assets_path ||= path_for "assets"
+ end
+
+ def data_path
+ @data_path ||= path_for "_data"
+ end
+
+ def runtime_dependencies
+ gemspec.runtime_dependencies
+ end
+
+ private
+
+ def path_for(folder)
+ path = realpath_for(folder)
+ path if path && File.directory?(path)
+ end
+
+ def realpath_for(folder)
+ # This resolves all symlinks for the theme subfolder and then ensures that the directory
+ # remains inside the theme root. This prevents the use of symlinks for theme subfolders to
+ # escape the theme root.
+ # However, symlinks are allowed to point to other directories within the theme.
+ Jekyll.sanitized_path(root, File.realpath(Jekyll.sanitized_path(root, folder.to_s)))
+ rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP => e
+ log_realpath_exception(e, folder)
+ nil
+ end
+
+ def log_realpath_exception(err, folder)
+ return if err.is_a?(Errno::ENOENT)
+
+ case err
+ when Errno::EACCES
+ Jekyll.logger.error "Theme error:", "Directory '#{folder}' is not accessible."
+ when Errno::ELOOP
+ Jekyll.logger.error "Theme error:", "Directory '#{folder}' includes a symbolic link loop."
+ end
+ end
+
+ def gemspec
+ @gemspec ||= Gem::Specification.find_by_name(name)
+ rescue Gem::LoadError
+ raise Jekyll::Errors::MissingDependencyException,
+ "The #{name} theme could not be found."
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/theme_builder.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/theme_builder.rb
new file mode 100644
index 0000000..b03abbf
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/theme_builder.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: true
+
+module Jekyll
+ class ThemeBuilder
+ SCAFFOLD_DIRECTORIES = %w(
+ assets _data _layouts _includes _sass
+ ).freeze
+
+ attr_reader :name, :path, :code_of_conduct
+
+ def initialize(theme_name, opts)
+ @name = theme_name.to_s.tr(" ", "_").squeeze("_")
+ @path = Pathname.new(File.expand_path(name, Dir.pwd))
+ @code_of_conduct = !!opts["code_of_conduct"]
+ end
+
+ def create!
+ create_directories
+ create_starter_files
+ create_gemspec
+ create_accessories
+ initialize_git_repo
+ end
+
+ def user_name
+ @user_name ||= `git config user.name`.chomp
+ end
+
+ def user_email
+ @user_email ||= `git config user.email`.chomp
+ end
+
+ private
+
+ def root
+ @root ||= Pathname.new(File.expand_path("../", __dir__))
+ end
+
+ def template_file(filename)
+ [
+ root.join("theme_template", "#{filename}.erb"),
+ root.join("theme_template", filename.to_s),
+ ].find(&:exist?)
+ end
+
+ def template(filename)
+ erb.render(template_file(filename).read)
+ end
+
+ def erb
+ @erb ||= ERBRenderer.new(self)
+ end
+
+ def mkdir_p(directories)
+ Array(directories).each do |directory|
+ full_path = path.join(directory)
+ Jekyll.logger.info "create", full_path.to_s
+ FileUtils.mkdir_p(full_path)
+ end
+ end
+
+ def write_file(filename, contents)
+ full_path = path.join(filename)
+ Jekyll.logger.info "create", full_path.to_s
+ File.write(full_path, contents)
+ end
+
+ def create_directories
+ mkdir_p(SCAFFOLD_DIRECTORIES)
+ end
+
+ def create_starter_files
+ %w(page post default).each do |layout|
+ write_file("_layouts/#{layout}.html", template("_layouts/#{layout}.html"))
+ end
+ end
+
+ def create_gemspec
+ write_file("Gemfile", template("Gemfile"))
+ write_file("#{name}.gemspec", template("theme.gemspec"))
+ end
+
+ def create_accessories
+ accessories = %w(README.md LICENSE.txt)
+ accessories << "CODE_OF_CONDUCT.md" if code_of_conduct
+ accessories.each do |filename|
+ write_file(filename, template(filename))
+ end
+ end
+
+ def initialize_git_repo
+ Jekyll.logger.info "initialize", path.join(".git").to_s
+ Dir.chdir(path.to_s) { `git init` }
+ write_file(".gitignore", template("gitignore"))
+ end
+
+ class ERBRenderer
+ extend Forwardable
+
+ def_delegator :@theme_builder, :name, :theme_name
+ def_delegator :@theme_builder, :user_name, :user_name
+ def_delegator :@theme_builder, :user_email, :user_email
+
+ def initialize(theme_builder)
+ @theme_builder = theme_builder
+ end
+
+ def jekyll_version_with_minor
+ Jekyll::VERSION.split(".").take(2).join(".")
+ end
+
+ def theme_directories
+ SCAFFOLD_DIRECTORIES
+ end
+
+ def render(contents)
+ ERB.new(contents).result binding
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/url.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/url.rb
new file mode 100644
index 0000000..aeb2ac0
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/url.rb
@@ -0,0 +1,167 @@
+# frozen_string_literal: true
+
+# Public: Methods that generate a URL for a resource such as a Post or a Page.
+#
+# Examples
+#
+# URL.new({
+# :template => /:categories/:title.html",
+# :placeholders => {:categories => "ruby", :title => "something"}
+# }).to_s
+#
+module Jekyll
+ class URL
+ # options - One of :permalink or :template must be supplied.
+ # :template - The String used as template for URL generation,
+ # for example "/:path/:basename:output_ext", where
+ # a placeholder is prefixed with a colon.
+ # :placeholders - A hash containing the placeholders which will be
+ # replaced when used inside the template. E.g.
+ # { "year" => Time.now.strftime("%Y") } would replace
+ # the placeholder ":year" with the current year.
+ # :permalink - If supplied, no URL will be generated from the
+ # template. Instead, the given permalink will be
+ # used as URL.
+ def initialize(options)
+ @template = options[:template]
+ @placeholders = options[:placeholders] || {}
+ @permalink = options[:permalink]
+
+ if (@template || @permalink).nil?
+ raise ArgumentError, "One of :template or :permalink must be supplied."
+ end
+ end
+
+ # The generated relative URL of the resource
+ #
+ # Returns the String URL
+ def to_s
+ sanitize_url(generated_permalink || generated_url)
+ end
+
+ # Generates a URL from the permalink
+ #
+ # Returns the _unsanitized String URL
+ def generated_permalink
+ (@generated_permalink ||= generate_url(@permalink)) if @permalink
+ end
+
+ # Generates a URL from the template
+ #
+ # Returns the unsanitized String URL
+ def generated_url
+ @generated_url ||= generate_url(@template)
+ end
+
+ # Internal: Generate the URL by replacing all placeholders with their
+ # respective values in the given template
+ #
+ # Returns the unsanitized String URL
+ def generate_url(template)
+ if @placeholders.is_a? Drops::UrlDrop
+ generate_url_from_drop(template)
+ else
+ generate_url_from_hash(template)
+ end
+ end
+
+ def generate_url_from_hash(template)
+ @placeholders.inject(template) do |result, token|
+ break result if result.index(":").nil?
+
+ if token.last.nil?
+ # Remove leading "/" to avoid generating urls with `//`
+ result.gsub("/:#{token.first}", "")
+ else
+ result.gsub(":#{token.first}", self.class.escape_path(token.last))
+ end
+ end
+ end
+
+ # We include underscores in keys to allow for 'i_month' and so forth.
+ # This poses a problem for keys which are followed by an underscore
+ # but the underscore is not part of the key, e.g. '/:month_:day'.
+ # That should be :month and :day, but our key extraction regexp isn't
+ # smart enough to know that so we have to make it an explicit
+ # possibility.
+ def possible_keys(key)
+ if key.end_with?("_")
+ [key, key.chomp("_")]
+ else
+ [key]
+ end
+ end
+
+ def generate_url_from_drop(template)
+ template.gsub(%r!:([a-z_]+)!) do |match|
+ name = Regexp.last_match(1)
+ pool = name.end_with?("_") ? [name, name.chomp!("_")] : [name]
+
+ winner = pool.find { |key| @placeholders.key?(key) }
+ if winner.nil?
+ raise NoMethodError,
+ "The URL template doesn't have #{pool.join(" or ")} keys. " \
+ "Check your permalink template!"
+ end
+
+ value = @placeholders[winner]
+ value = "" if value.nil?
+ replacement = self.class.escape_path(value)
+
+ match.sub!(":#{winner}", replacement)
+ end
+ end
+
+ # Returns a sanitized String URL, stripping "../../" and multiples of "/",
+ # as well as the beginning "/" so we can enforce and ensure it.
+ def sanitize_url(str)
+ "/#{str}".gsub("..", "/").tap do |result|
+ result.gsub!("./", "")
+ result.squeeze!("/")
+ end
+ end
+
+ # Escapes a path to be a valid URL path segment
+ #
+ # path - The path to be escaped.
+ #
+ # Examples:
+ #
+ # URL.escape_path("/a b")
+ # # => "/a%20b"
+ #
+ # Returns the escaped path.
+ def self.escape_path(path)
+ return path if path.empty? || %r!^[a-zA-Z0-9./-]+$!.match?(path)
+
+ # Because URI.escape doesn't escape "?", "[" and "]" by default,
+ # specify unsafe string (except unreserved, sub-delims, ":", "@" and "/").
+ #
+ # URI path segment is defined in RFC 3986 as follows:
+ # segment = *pchar
+ # pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
+ # unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ # pct-encoded = "%" HEXDIG HEXDIG
+ # sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ # / "*" / "+" / "," / ";" / "="
+ Addressable::URI.encode(path).encode("utf-8").sub("#", "%23")
+ end
+
+ # Unescapes a URL path segment
+ #
+ # path - The path to be unescaped.
+ #
+ # Examples:
+ #
+ # URL.unescape_path("/a%20b")
+ # # => "/a b"
+ #
+ # Returns the unescaped path.
+ def self.unescape_path(path)
+ path = path.encode("utf-8")
+ return path unless path.include?("%")
+
+ Addressable::URI.unencode(path)
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils.rb
new file mode 100644
index 0000000..2a96527
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils.rb
@@ -0,0 +1,371 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Utils
+ extend self
+ autoload :Ansi, "jekyll/utils/ansi"
+ autoload :Exec, "jekyll/utils/exec"
+ autoload :Internet, "jekyll/utils/internet"
+ autoload :Platforms, "jekyll/utils/platforms"
+ autoload :ThreadEvent, "jekyll/utils/thread_event"
+ autoload :WinTZ, "jekyll/utils/win_tz"
+
+ # Constants for use in #slugify
+ SLUGIFY_MODES = %w(raw default pretty ascii latin).freeze
+ SLUGIFY_RAW_REGEXP = Regexp.new('\\s+').freeze
+ SLUGIFY_DEFAULT_REGEXP = Regexp.new("[^\\p{M}\\p{L}\\p{Nd}]+").freeze
+ SLUGIFY_PRETTY_REGEXP = Regexp.new("[^\\p{M}\\p{L}\\p{Nd}._~!$&'()+,;=@]+").freeze
+ SLUGIFY_ASCII_REGEXP = Regexp.new("[^[A-Za-z0-9]]+").freeze
+
+ # Takes a slug and turns it into a simple title.
+ def titleize_slug(slug)
+ slug.split("-").map!(&:capitalize).join(" ")
+ end
+
+ # Non-destructive version of deep_merge_hashes! See that method.
+ #
+ # Returns the merged hashes.
+ def deep_merge_hashes(master_hash, other_hash)
+ deep_merge_hashes!(master_hash.dup, other_hash)
+ end
+
+ # Merges a master hash with another hash, recursively.
+ #
+ # master_hash - the "parent" hash whose values will be overridden
+ # other_hash - the other hash whose values will be persisted after the merge
+ #
+ # This code was lovingly stolen from some random gem:
+ # http://gemjack.com/gems/tartan-0.1.1/classes/Hash.html
+ #
+ # Thanks to whoever made it.
+ def deep_merge_hashes!(target, overwrite)
+ merge_values(target, overwrite)
+ merge_default_proc(target, overwrite)
+ duplicate_frozen_values(target)
+
+ target
+ end
+
+ def mergable?(value)
+ value.is_a?(Hash) || value.is_a?(Drops::Drop)
+ end
+
+ def duplicable?(obj)
+ case obj
+ when nil, false, true, Symbol, Numeric
+ false
+ else
+ true
+ end
+ end
+
+ # Read array from the supplied hash favouring the singular key
+ # and then the plural key, and handling any nil entries.
+ #
+ # hash - the hash to read from
+ # singular_key - the singular key
+ # plural_key - the plural key
+ #
+ # Returns an array
+ def pluralized_array_from_hash(hash, singular_key, plural_key)
+ array = []
+ value = value_from_singular_key(hash, singular_key)
+ value ||= value_from_plural_key(hash, plural_key)
+
+ array << value
+ array.flatten!
+ array.compact!
+ array
+ end
+
+ def value_from_singular_key(hash, key)
+ hash[key] if hash.key?(key) || (hash.default_proc && hash[key])
+ end
+
+ def value_from_plural_key(hash, key)
+ if hash.key?(key) || (hash.default_proc && hash[key])
+ val = hash[key]
+ case val
+ when String
+ val.split
+ when Array
+ val.compact
+ end
+ end
+ end
+
+ def transform_keys(hash)
+ result = {}
+ hash.each_key do |key|
+ result[yield(key)] = hash[key]
+ end
+ result
+ end
+
+ # Apply #to_sym to all keys in the hash
+ #
+ # hash - the hash to which to apply this transformation
+ #
+ # Returns a new hash with symbolized keys
+ def symbolize_hash_keys(hash)
+ transform_keys(hash) { |key| key.to_sym rescue key }
+ end
+
+ # Apply #to_s to all keys in the Hash
+ #
+ # hash - the hash to which to apply this transformation
+ #
+ # Returns a new hash with stringified keys
+ def stringify_hash_keys(hash)
+ transform_keys(hash) { |key| key.to_s rescue key }
+ end
+
+ # Parse a date/time and throw an error if invalid
+ #
+ # input - the date/time to parse
+ # msg - (optional) the error message to show the user
+ #
+ # Returns the parsed date if successful, throws a FatalException
+ # if not
+ def parse_date(input, msg = "Input could not be parsed.")
+ @parse_date_cache ||= {}
+ @parse_date_cache[input] ||= Time.parse(input).localtime
+ rescue ArgumentError
+ raise Errors::InvalidDateError, "Invalid date '#{input}': #{msg}"
+ end
+
+ # Determines whether a given file has
+ #
+ # Returns true if the YAML front matter is present.
+ # rubocop: disable Naming/PredicateName
+ def has_yaml_header?(file)
+ File.open(file, "rb", &:readline).match? %r!\A---\s*\r?\n!
+ rescue EOFError
+ false
+ end
+
+ # Determine whether the given content string contains Liquid Tags or Variables
+ #
+ # Returns true is the string contains sequences of `{%` or `{{`
+ def has_liquid_construct?(content)
+ return false if content.nil? || content.empty?
+
+ content.include?("{%") || content.include?("{{")
+ end
+ # rubocop: enable Naming/PredicateName
+
+ # Slugify a filename or title.
+ #
+ # string - the filename or title to slugify
+ # mode - how string is slugified
+ # cased - whether to replace all uppercase letters with their
+ # lowercase counterparts
+ #
+ # When mode is "none", return the given string.
+ #
+ # When mode is "raw", return the given string,
+ # with every sequence of spaces characters replaced with a hyphen.
+ #
+ # When mode is "default" or nil, non-alphabetic characters are
+ # replaced with a hyphen too.
+ #
+ # When mode is "pretty", some non-alphabetic characters (._~!$&'()+,;=@)
+ # are not replaced with hyphen.
+ #
+ # When mode is "ascii", some everything else except ASCII characters
+ # a-z (lowercase), A-Z (uppercase) and 0-9 (numbers) are not replaced with hyphen.
+ #
+ # When mode is "latin", the input string is first preprocessed so that
+ # any letters with accents are replaced with the plain letter. Afterwards,
+ # it follows the "default" mode of operation.
+ #
+ # If cased is true, all uppercase letters in the result string are
+ # replaced with their lowercase counterparts.
+ #
+ # Examples:
+ # slugify("The _config.yml file")
+ # # => "the-config-yml-file"
+ #
+ # slugify("The _config.yml file", "pretty")
+ # # => "the-_config.yml-file"
+ #
+ # slugify("The _config.yml file", "pretty", true)
+ # # => "The-_config.yml file"
+ #
+ # slugify("The _config.yml file", "ascii")
+ # # => "the-config-yml-file"
+ #
+ # slugify("The _config.yml file", "latin")
+ # # => "the-config-yml-file"
+ #
+ # Returns the slugified string.
+ def slugify(string, mode: nil, cased: false)
+ mode ||= "default"
+ return nil if string.nil?
+
+ unless SLUGIFY_MODES.include?(mode)
+ return cased ? string : string.downcase
+ end
+
+ # Drop accent marks from latin characters. Everything else turns to ?
+ if mode == "latin"
+ I18n.config.available_locales = :en if I18n.config.available_locales.empty?
+ string = I18n.transliterate(string)
+ end
+
+ slug = replace_character_sequence_with_hyphen(string, :mode => mode)
+
+ # Remove leading/trailing hyphen
+ slug.gsub!(%r!^-|-$!i, "")
+
+ slug.downcase! unless cased
+ Jekyll.logger.warn("Warning:", "Empty `slug` generated for '#{string}'.") if slug.empty?
+ slug
+ end
+
+ # Add an appropriate suffix to template so that it matches the specified
+ # permalink style.
+ #
+ # template - permalink template without trailing slash or file extension
+ # permalink_style - permalink style, either built-in or custom
+ #
+ # The returned permalink template will use the same ending style as
+ # specified in permalink_style. For example, if permalink_style contains a
+ # trailing slash (or is :pretty, which indirectly has a trailing slash),
+ # then so will the returned template. If permalink_style has a trailing
+ # ":output_ext" (or is :none, :date, or :ordinal) then so will the returned
+ # template. Otherwise, template will be returned without modification.
+ #
+ # Examples:
+ # add_permalink_suffix("/:basename", :pretty)
+ # # => "/:basename/"
+ #
+ # add_permalink_suffix("/:basename", :date)
+ # # => "/:basename:output_ext"
+ #
+ # add_permalink_suffix("/:basename", "/:year/:month/:title/")
+ # # => "/:basename/"
+ #
+ # add_permalink_suffix("/:basename", "/:year/:month/:title")
+ # # => "/:basename"
+ #
+ # Returns the updated permalink template
+ def add_permalink_suffix(template, permalink_style)
+ template = template.dup
+
+ case permalink_style
+ when :pretty
+ template << "/"
+ when :date, :ordinal, :none
+ template << ":output_ext"
+ else
+ template << "/" if permalink_style.to_s.end_with?("/")
+ template << ":output_ext" if permalink_style.to_s.end_with?(":output_ext")
+ end
+
+ template
+ end
+
+ # Work the same way as Dir.glob but separating the input into two parts
+ # ('dir' + '/' + 'pattern') to make sure the first part('dir') does not act
+ # as a pattern.
+ #
+ # For example, Dir.glob("path[/*") always returns an empty array,
+ # because the method fails to find the closing pattern to '[' which is ']'
+ #
+ # Examples:
+ # safe_glob("path[", "*")
+ # # => ["path[/file1", "path[/file2"]
+ #
+ # safe_glob("path", "*", File::FNM_DOTMATCH)
+ # # => ["path/.", "path/..", "path/file1"]
+ #
+ # safe_glob("path", ["**", "*"])
+ # # => ["path[/file1", "path[/folder/file2"]
+ #
+ # dir - the dir where glob will be executed under
+ # (the dir will be included to each result)
+ # patterns - the patterns (or the pattern) which will be applied under the dir
+ # flags - the flags which will be applied to the pattern
+ #
+ # Returns matched paths
+ def safe_glob(dir, patterns, flags = 0)
+ return [] unless Dir.exist?(dir)
+
+ pattern = File.join(Array(patterns))
+ return [dir] if pattern.empty?
+
+ Dir.chdir(dir) do
+ Dir.glob(pattern, flags).map { |f| File.join(dir, f) }
+ end
+ end
+
+ # Returns merged option hash for File.read of self.site (if exists)
+ # and a given param
+ def merged_file_read_opts(site, opts)
+ merged = (site ? site.file_read_opts : {}).merge(opts)
+
+ # always use BOM when reading UTF-encoded files
+ if merged[:encoding]&.downcase&.start_with?("utf-")
+ merged[:encoding] = "bom|#{merged[:encoding]}"
+ end
+ if merged["encoding"]&.downcase&.start_with?("utf-")
+ merged["encoding"] = "bom|#{merged["encoding"]}"
+ end
+
+ merged
+ end
+
+ private
+
+ def merge_values(target, overwrite)
+ target.merge!(overwrite) do |_key, old_val, new_val|
+ if new_val.nil?
+ old_val
+ elsif mergable?(old_val) && mergable?(new_val)
+ deep_merge_hashes(old_val, new_val)
+ else
+ new_val
+ end
+ end
+ end
+
+ def merge_default_proc(target, overwrite)
+ if target.is_a?(Hash) && overwrite.is_a?(Hash) && target.default_proc.nil?
+ target.default_proc = overwrite.default_proc
+ end
+ end
+
+ def duplicate_frozen_values(target)
+ target.each do |key, val|
+ target[key] = val.dup if val.frozen? && duplicable?(val)
+ end
+ end
+
+ # Replace each character sequence with a hyphen.
+ #
+ # See Utils#slugify for a description of the character sequence specified
+ # by each mode.
+ def replace_character_sequence_with_hyphen(string, mode: "default")
+ replaceable_char =
+ case mode
+ when "raw"
+ SLUGIFY_RAW_REGEXP
+ when "pretty"
+ # "._~!$&'()+,;=@" is human readable (not URI-escaped) in URL
+ # and is allowed in both extN and NTFS.
+ SLUGIFY_PRETTY_REGEXP
+ when "ascii"
+ # For web servers not being able to handle Unicode, the safe
+ # method is to ditch anything else but latin letters and numeric
+ # digits.
+ SLUGIFY_ASCII_REGEXP
+ else
+ SLUGIFY_DEFAULT_REGEXP
+ end
+
+ # Strip according to the mode
+ string.gsub(replaceable_char, "-")
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/ansi.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/ansi.rb
new file mode 100644
index 0000000..00d1b1d
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/ansi.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Utils
+ module Ansi
+ extend self
+
+ ESCAPE = format("%c", 27)
+ MATCH = %r!#{ESCAPE}\[(?:\d+)(?:;\d+)*(j|k|m|s|u|A|B|G)|\e\(B\e\[m!ix.freeze
+ COLORS = {
+ :red => 31,
+ :green => 32,
+ :black => 30,
+ :magenta => 35,
+ :yellow => 33,
+ :white => 37,
+ :blue => 34,
+ :cyan => 36,
+ }.freeze
+
+ # Strip ANSI from the current string. It also strips cursor stuff,
+ # well some of it, and it also strips some other stuff that a lot of
+ # the other ANSI strippers don't.
+
+ def strip(str)
+ str.gsub MATCH, ""
+ end
+
+ #
+
+ def has?(str)
+ !!(str =~ MATCH)
+ end
+
+ # Reset the color back to the default color so that you do not leak any
+ # colors when you move onto the next line. This is probably normally
+ # used as part of a wrapper so that we don't leak colors.
+
+ def reset(str = "")
+ @ansi_reset ||= format("%c[0m", 27)
+ "#{@ansi_reset}#{str}"
+ end
+
+ # SEE: `self::COLORS` for a list of methods. They are mostly
+ # standard base colors supported by pretty much any xterm-color, we do
+ # not need more than the base colors so we do not include them.
+ # Actually... if I'm honest we don't even need most of the
+ # base colors.
+
+ COLORS.each do |color, num|
+ define_method color do |str|
+ "#{format("%c", 27)}[#{num}m#{str}#{reset}"
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/exec.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/exec.rb
new file mode 100644
index 0000000..5838ecb
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/exec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require "open3"
+
+module Jekyll
+ module Utils
+ module Exec
+ extend self
+
+ # Runs a program in a sub-shell.
+ #
+ # *args - a list of strings containing the program name and arguments
+ #
+ # Returns a Process::Status and a String of output in an array in
+ # that order.
+ def run(*args)
+ stdin, stdout, stderr, process = Open3.popen3(*args)
+ out = stdout.read.strip
+ err = stderr.read.strip
+
+ [stdin, stdout, stderr].each(&:close)
+ [process.value, out + err]
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/internet.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/internet.rb
new file mode 100644
index 0000000..945267f
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/internet.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Utils
+ module Internet
+ # Public: Determine whether the present device has a connection to
+ # the Internet. This allows plugin writers which require the outside
+ # world to have a neat fallback mechanism for offline building.
+ #
+ # Example:
+ # if Internet.connected?
+ # Typhoeus.get("https://pages.github.com/versions.json")
+ # else
+ # Jekyll.logger.warn "Warning:", "Version check has been disabled."
+ # Jekyll.logger.warn "", "Connect to the Internet to enable it."
+ # nil
+ # end
+ #
+ # Returns true if a DNS call can successfully be made, or false if not.
+
+ module_function
+
+ def connected?
+ !dns("example.com").nil?
+ end
+
+ def dns(domain)
+ require "resolv"
+ Resolv::DNS.open do |resolver|
+ resolver.getaddress(domain)
+ end
+ rescue Resolv::ResolvError, Resolv::ResolvTimeout
+ nil
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/platforms.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/platforms.rb
new file mode 100644
index 0000000..a6c6da9
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/platforms.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Utils
+ module Platforms
+ extend self
+
+ def jruby?
+ RUBY_ENGINE == "jruby"
+ end
+
+ def mri?
+ RUBY_ENGINE == "ruby"
+ end
+
+ def windows?
+ vanilla_windows? || bash_on_windows?
+ end
+
+ # Not a Windows Subsystem for Linux (WSL)
+ def vanilla_windows?
+ rbconfig_host.match?(%r!mswin|mingw|cygwin!) && proc_version.empty?
+ end
+ alias_method :really_windows?, :vanilla_windows?
+
+ # Determine if Windows Subsystem for Linux (WSL)
+ def bash_on_windows?
+ linux_os? && microsoft_proc_version?
+ end
+
+ def linux?
+ linux_os? && !microsoft_proc_version?
+ end
+
+ def osx?
+ rbconfig_host.match?(%r!darwin|mac os!)
+ end
+
+ def unix?
+ rbconfig_host.match?(%r!solaris|bsd!)
+ end
+
+ private
+
+ def proc_version
+ @proc_version ||= \
+ begin
+ File.read("/proc/version").downcase
+ rescue Errno::ENOENT, Errno::EACCES
+ ""
+ end
+ end
+
+ def rbconfig_host
+ @rbconfig_host ||= RbConfig::CONFIG["host_os"].downcase
+ end
+
+ def linux_os?
+ rbconfig_host.include?("linux")
+ end
+
+ def microsoft_proc_version?
+ proc_version.include?("microsoft")
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/thread_event.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/thread_event.rb
new file mode 100644
index 0000000..801022e
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/thread_event.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Utils
+ # Based on the pattern and code from
+ # https://emptysqua.re/blog/an-event-synchronization-primitive-for-ruby/
+ class ThreadEvent
+ attr_reader :flag
+
+ def initialize
+ @lock = Mutex.new
+ @cond = ConditionVariable.new
+ @flag = false
+ end
+
+ def set
+ @lock.synchronize do
+ yield if block_given?
+ @flag = true
+ @cond.broadcast
+ end
+ end
+
+ def wait
+ @lock.synchronize do
+ @cond.wait(@lock) unless @flag
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/win_tz.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/win_tz.rb
new file mode 100644
index 0000000..ad277d3
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/utils/win_tz.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Jekyll
+ module Utils
+ module WinTZ
+ extend self
+
+ # Public: Calculate the Timezone for Windows when the config file has a defined
+ # 'timezone' key.
+ #
+ # timezone - the IANA Time Zone specified in "_config.yml"
+ #
+ # Returns a string that ultimately re-defines ENV["TZ"] in Windows
+ def calculate(timezone, now = Time.now)
+ External.require_with_graceful_fail("tzinfo") unless defined?(TZInfo)
+ tz = TZInfo::Timezone.get(timezone)
+
+ #
+ # Use period_for_utc and utc_total_offset instead of
+ # period_for and observed_utc_offset for compatibility with tzinfo v1.
+ offset = tz.period_for_utc(now.getutc).utc_total_offset
+
+ #
+ # POSIX style definition reverses the offset sign.
+ # e.g. Eastern Standard Time (EST) that is 5Hrs. to the 'west' of Prime Meridian
+ # is denoted as:
+ # EST+5 (or) EST+05:00
+ # Reference: https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
+ sign = offset.positive? ? "-" : "+"
+
+ rational_hours = offset.abs.to_r / 3600
+ hours = rational_hours.to_i
+ minutes = ((rational_hours - hours) * 60).to_i
+
+ #
+ # Format the hours and minutes as two-digit numbers.
+ time = format("%<hours>02d:%<minutes>02d", :hours => hours, :minutes => minutes)
+
+ Jekyll.logger.debug "Timezone:", "#{timezone} #{sign}#{time}"
+ #
+ # Note: The 3-letter-word below doesn't have a particular significance.
+ "WTZ#{sign}#{time}"
+ end
+ end
+ end
+end
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/version.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/version.rb
new file mode 100644
index 0000000..eff0d1d
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll/version.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+module Jekyll
+ VERSION = "4.4.1"
+end