summaryrefslogtreecommitdiff
path: root/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib
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
parent359f3309c97fc894b63e0a295c76ab298504d635 (diff)
Vendor bundled gems for deployment
Diffstat (limited to 'vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib')
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/_config.yml3
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/_layouts/default.html12
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/_sass/base.scss9
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/assets/css/main.scss4
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/index.md8
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll.rb195
-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
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/.gitignore5
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/404.html25
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/_config.yml55
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb29
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/about.markdown18
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/index.markdown6
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/CODE_OF_CONDUCT.md.erb74
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/Gemfile4
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/LICENSE.txt.erb21
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/README.md.erb50
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/_layouts/default.html1
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/_layouts/page.html5
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/_layouts/post.html5
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/_config.yml.erb1
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/_post.md12
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/index.html14
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/style.scss7
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/gitignore.erb6
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/theme.gemspec.erb16
116 files changed, 13346 insertions, 0 deletions
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/_config.yml b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/_config.yml
new file mode 100644
index 0000000..a0cd66a
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/_config.yml
@@ -0,0 +1,3 @@
+url: "" # the base hostname & protocol for your site, e.g. http://example.com
+baseurl: "" # the subpath of your site, e.g. /blog
+title: "" # the name of your site, e.g. ACME Corp.
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/_layouts/default.html b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/_layouts/default.html
new file mode 100644
index 0000000..fa0b00a
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/_layouts/default.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="{{ site.lang | default: "en-US" }}">
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta charset="utf-8">
+ <title>{{ page.title }} - {{ site.title }}</title>
+ <link rel="stylesheet" href="{{ "/assets/css/main.css" | relative_url }}">
+ </head>
+ <body>
+ {{ content }}
+ </body>
+</html>
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/_sass/base.scss b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/_sass/base.scss
new file mode 100644
index 0000000..126160d
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/_sass/base.scss
@@ -0,0 +1,9 @@
+$backgroundColor: #ffffff;
+$bodyColor: #000000;
+$bodyFont: -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";
+
+body {
+ background: $backgroundColor;
+ color: $bodyColor;
+ font-family: $bodyFont;
+}
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/assets/css/main.scss b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/assets/css/main.scss
new file mode 100644
index 0000000..9c288c5
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/assets/css/main.scss
@@ -0,0 +1,4 @@
+---
+---
+
+@import "base";
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/index.md b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/index.md
new file mode 100644
index 0000000..82eaafb
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/blank_template/index.md
@@ -0,0 +1,8 @@
+---
+layout: default
+title: "Happy Jekylling!"
+---
+
+## You're ready to go!
+
+Start developing your Jekyll website.
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll.rb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll.rb
new file mode 100644
index 0000000..231f8fd
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/jekyll.rb
@@ -0,0 +1,195 @@
+# frozen_string_literal: true
+
+$LOAD_PATH.unshift __dir__ # For use/testing when no gem is installed
+
+# Require all of the Ruby files in the given directory.
+#
+# path - The String relative path from here to the directory.
+#
+# Returns nothing.
+def require_all(path)
+ glob = File.join(__dir__, path, "*.rb")
+ Dir[glob].sort.each do |f|
+ require f
+ end
+end
+
+# rubygems
+require "rubygems"
+
+# stdlib
+require "forwardable"
+require "fileutils"
+require "time"
+require "English"
+require "pathname"
+require "logger"
+require "set"
+require "csv"
+require "json"
+
+# 3rd party
+require "pathutil"
+require "addressable/uri"
+require "safe_yaml/load"
+require "liquid"
+require "kramdown"
+require "colorator"
+require "i18n"
+
+SafeYAML::OPTIONS[:suppress_warnings] = true
+
+module Jekyll
+ # internal requires
+ autoload :Cleaner, "jekyll/cleaner"
+ autoload :Collection, "jekyll/collection"
+ autoload :Configuration, "jekyll/configuration"
+ autoload :Convertible, "jekyll/convertible"
+ autoload :Deprecator, "jekyll/deprecator"
+ autoload :Document, "jekyll/document"
+ autoload :EntryFilter, "jekyll/entry_filter"
+ autoload :Errors, "jekyll/errors"
+ autoload :Excerpt, "jekyll/excerpt"
+ autoload :PageExcerpt, "jekyll/page_excerpt"
+ autoload :External, "jekyll/external"
+ autoload :FrontmatterDefaults, "jekyll/frontmatter_defaults"
+ autoload :Hooks, "jekyll/hooks"
+ autoload :Layout, "jekyll/layout"
+ autoload :Inclusion, "jekyll/inclusion"
+ autoload :Cache, "jekyll/cache"
+ autoload :CollectionReader, "jekyll/readers/collection_reader"
+ autoload :DataReader, "jekyll/readers/data_reader"
+ autoload :LayoutReader, "jekyll/readers/layout_reader"
+ autoload :PostReader, "jekyll/readers/post_reader"
+ autoload :PageReader, "jekyll/readers/page_reader"
+ autoload :StaticFileReader, "jekyll/readers/static_file_reader"
+ autoload :ThemeAssetsReader, "jekyll/readers/theme_assets_reader"
+ autoload :LogAdapter, "jekyll/log_adapter"
+ autoload :Page, "jekyll/page"
+ autoload :PageWithoutAFile, "jekyll/page_without_a_file"
+ autoload :PathManager, "jekyll/path_manager"
+ autoload :PluginManager, "jekyll/plugin_manager"
+ autoload :Publisher, "jekyll/publisher"
+ autoload :Profiler, "jekyll/profiler"
+ autoload :Reader, "jekyll/reader"
+ autoload :Regenerator, "jekyll/regenerator"
+ autoload :RelatedPosts, "jekyll/related_posts"
+ autoload :Renderer, "jekyll/renderer"
+ autoload :LiquidRenderer, "jekyll/liquid_renderer"
+ autoload :Site, "jekyll/site"
+ autoload :StaticFile, "jekyll/static_file"
+ autoload :Stevenson, "jekyll/stevenson"
+ autoload :Theme, "jekyll/theme"
+ autoload :ThemeBuilder, "jekyll/theme_builder"
+ autoload :URL, "jekyll/url"
+ autoload :Utils, "jekyll/utils"
+ autoload :VERSION, "jekyll/version"
+
+ # extensions
+ require "jekyll/plugin"
+ require "jekyll/converter"
+ require "jekyll/generator"
+ require "jekyll/command"
+ require "jekyll/liquid_extensions"
+ require "jekyll/filters"
+
+ class << self
+ # Public: Tells you which Jekyll environment you are building in so you can skip tasks
+ # if you need to. This is useful when doing expensive compression tasks on css and
+ # images and allows you to skip that when working in development.
+
+ def env
+ ENV["JEKYLL_ENV"] || "development"
+ end
+
+ # Public: Generate a Jekyll configuration Hash by merging the default
+ # options with anything in _config.yml, and adding the given options on top.
+ #
+ # override - A Hash of config directives that override any options in both
+ # the defaults and the config file.
+ # See Jekyll::Configuration::DEFAULTS for a
+ # list of option names and their defaults.
+ #
+ # Returns the final configuration Hash.
+ def configuration(override = {})
+ config = Configuration.new
+ override = Configuration[override].stringify_keys
+ unless override.delete("skip_config_files")
+ config = config.read_config_files(config.config_files(override))
+ end
+
+ # Merge DEFAULTS < _config.yml < override
+ Configuration.from(Utils.deep_merge_hashes(config, override)).tap do |obj|
+ set_timezone(obj["timezone"]) if obj["timezone"]
+ end
+ end
+
+ # Public: Set the TZ environment variable to use the timezone specified
+ #
+ # timezone - the IANA Time Zone
+ #
+ # Returns nothing
+ # rubocop:disable Naming/AccessorMethodName
+ def set_timezone(timezone)
+ ENV["TZ"] = if Utils::Platforms.really_windows?
+ Utils::WinTZ.calculate(timezone)
+ else
+ timezone
+ end
+ end
+ # rubocop:enable Naming/AccessorMethodName
+
+ # Public: Fetch the logger instance for this Jekyll process.
+ #
+ # Returns the LogAdapter instance.
+ def logger
+ @logger ||= LogAdapter.new(Stevenson.new, (ENV["JEKYLL_LOG_LEVEL"] || :info).to_sym)
+ end
+
+ # Public: Set the log writer.
+ # New log writer must respond to the same methods
+ # as Ruby's internal Logger.
+ #
+ # writer - the new Logger-compatible log transport
+ #
+ # Returns the new logger.
+ def logger=(writer)
+ @logger = LogAdapter.new(writer, (ENV["JEKYLL_LOG_LEVEL"] || :info).to_sym)
+ end
+
+ # Public: An array of sites
+ #
+ # Returns the Jekyll sites created.
+ def sites
+ @sites ||= []
+ end
+
+ # Public: Ensures the questionable path is prefixed with the base directory
+ # and prepends the questionable path with the base directory if false.
+ #
+ # base_directory - the directory with which to prefix the questionable path
+ # questionable_path - the path we're unsure about, and want prefixed
+ #
+ # Returns the sanitized path.
+ def sanitized_path(base_directory, questionable_path)
+ return base_directory if base_directory.eql?(questionable_path)
+ return base_directory if questionable_path.nil?
+
+ +Jekyll::PathManager.sanitized_path(base_directory, questionable_path)
+ end
+
+ # Conditional optimizations
+ Jekyll::External.require_if_present("liquid/c")
+ end
+end
+
+require "jekyll/drops/drop"
+require "jekyll/drops/document_drop"
+require_all "jekyll/commands"
+require_all "jekyll/converters"
+require_all "jekyll/converters/markdown"
+require_all "jekyll/drops"
+require_all "jekyll/generators"
+require_all "jekyll/tags"
+
+require "jekyll-sass-converter"
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
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/.gitignore b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/.gitignore
new file mode 100644
index 0000000..f40fbd8
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/.gitignore
@@ -0,0 +1,5 @@
+_site
+.sass-cache
+.jekyll-cache
+.jekyll-metadata
+vendor
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/404.html b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/404.html
new file mode 100644
index 0000000..3a16ab5
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/404.html
@@ -0,0 +1,25 @@
+---
+permalink: /404.html
+layout: page
+---
+
+<style type="text/css" media="screen">
+ .container {
+ margin: 10px auto;
+ max-width: 600px;
+ text-align: center;
+ }
+ h1 {
+ margin: 30px 0;
+ font-size: 4em;
+ line-height: 1;
+ letter-spacing: -1px;
+ }
+</style>
+
+<div class="container">
+ <h1>404</h1>
+
+ <p><strong>Page not found :(</strong></p>
+ <p>The requested page could not be found.</p>
+</div>
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/_config.yml b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/_config.yml
new file mode 100644
index 0000000..ef7ba7c
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/_config.yml
@@ -0,0 +1,55 @@
+# Welcome to Jekyll!
+#
+# This config file is meant for settings that affect your whole blog, values
+# which you are expected to set up once and rarely edit after that. If you find
+# yourself editing this file very often, consider using Jekyll's data files
+# feature for the data you need to update frequently.
+#
+# For technical reasons, this file is *NOT* reloaded automatically when you use
+# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
+#
+# If you need help with YAML syntax, here are some quick references for you:
+# https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml
+# https://learnxinyminutes.com/docs/yaml/
+#
+# Site settings
+# These are used to personalize your new site. If you look in the HTML files,
+# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
+# You can create any custom variable you would like, and they will be accessible
+# in the templates via {{ site.myvariable }}.
+
+title: Your awesome title
+email: your-email@example.com
+description: >- # this means to ignore newlines until "baseurl:"
+ Write an awesome description for your new site here. You can edit this
+ line in _config.yml. It will appear in your document head meta (for
+ Google search results) and in your feed.xml site description.
+baseurl: "" # the subpath of your site, e.g. /blog
+url: "" # the base hostname & protocol for your site, e.g. http://example.com
+twitter_username: jekyllrb
+github_username: jekyll
+
+# Build settings
+theme: minima
+plugins:
+ - jekyll-feed
+
+# Exclude from processing.
+# The following items will not be processed, by default.
+# Any item listed under the `exclude:` key here will be automatically added to
+# the internal "default list".
+#
+# Excluded items can be processed by explicitly listing the directories or
+# their entries' file path in the `include:` list.
+#
+# exclude:
+# - .sass-cache/
+# - .jekyll-cache/
+# - gemfiles/
+# - Gemfile
+# - Gemfile.lock
+# - node_modules/
+# - vendor/bundle/
+# - vendor/cache/
+# - vendor/gems/
+# - vendor/ruby/
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb
new file mode 100644
index 0000000..187a4d9
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb
@@ -0,0 +1,29 @@
+---
+layout: post
+title: "Welcome to Jekyll!"
+date: <%= Time.now.strftime('%Y-%m-%d %H:%M:%S %z') %>
+categories: jekyll update
+---
+You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `jekyll serve`, which launches a web server and auto-regenerates your site when a file is updated.
+
+Jekyll requires blog post files to be named according to the following format:
+
+`YEAR-MONTH-DAY-title.MARKUP`
+
+Where `YEAR` is a four-digit number, `MONTH` and `DAY` are both two-digit numbers, and `MARKUP` is the file extension representing the format used in the file. After that, include the necessary front matter. Take a look at the source for this post to get an idea about how it works.
+
+Jekyll also offers powerful support for code snippets:
+
+{% highlight ruby %}
+def print_hi(name)
+ puts "Hi, #{name}"
+end
+print_hi('Tom')
+#=> prints 'Hi, Tom' to STDOUT.
+{% endhighlight %}
+
+Check out the [Jekyll docs][jekyll-docs] for more info on how to get the most out of Jekyll. File all bugs/feature requests at [Jekyll’s GitHub repo][jekyll-gh]. If you have questions, you can ask them on [Jekyll Talk][jekyll-talk].
+
+[jekyll-docs]: https://jekyllrb.com/docs/home
+[jekyll-gh]: https://github.com/jekyll/jekyll
+[jekyll-talk]: https://talk.jekyllrb.com/
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/about.markdown b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/about.markdown
new file mode 100644
index 0000000..8b4e0b2
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/about.markdown
@@ -0,0 +1,18 @@
+---
+layout: page
+title: About
+permalink: /about/
+---
+
+This is the base Jekyll theme. You can find out more info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at [jekyllrb.com](https://jekyllrb.com/)
+
+You can find the source code for Minima at GitHub:
+[jekyll][jekyll-organization] /
+[minima](https://github.com/jekyll/minima)
+
+You can find the source code for Jekyll at GitHub:
+[jekyll][jekyll-organization] /
+[jekyll](https://github.com/jekyll/jekyll)
+
+
+[jekyll-organization]: https://github.com/jekyll
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/index.markdown b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/index.markdown
new file mode 100644
index 0000000..0671507
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/site_template/index.markdown
@@ -0,0 +1,6 @@
+---
+# Feel free to add content and custom Front Matter to this file.
+# To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults
+
+layout: home
+---
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/CODE_OF_CONDUCT.md.erb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/CODE_OF_CONDUCT.md.erb
new file mode 100644
index 0000000..2b2c773
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/CODE_OF_CONDUCT.md.erb
@@ -0,0 +1,74 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at <%= user_email %>. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/Gemfile b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/Gemfile
new file mode 100644
index 0000000..bb94df8
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/Gemfile
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+gemspec
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/LICENSE.txt.erb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/LICENSE.txt.erb
new file mode 100644
index 0000000..38a0eb4
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/LICENSE.txt.erb
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <%= Time.now.year %> <%= user_name %>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/README.md.erb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/README.md.erb
new file mode 100644
index 0000000..9e18034
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/README.md.erb
@@ -0,0 +1,50 @@
+# <%= theme_name %>
+
+Welcome to your new Jekyll theme! In this directory, you'll find the files you need to be able to package up your theme into a gem. Put your layouts in `_layouts`, your includes in `_includes`, your sass files in `_sass` and any other assets in `assets`.
+
+To experiment with this code, add some sample content and run `bundle exec jekyll serve` – this directory is setup just like a Jekyll site!
+
+TODO: Delete this and the text above, and describe your gem
+
+## Installation
+
+Add this line to your Jekyll site's `Gemfile`:
+
+```ruby
+gem <%= theme_name.inspect %>
+```
+
+And add this line to your Jekyll site's `_config.yml`:
+
+```yaml
+theme: <%= theme_name %>
+```
+
+And then execute:
+
+ $ bundle
+
+Or install it yourself as:
+
+ $ gem install <%= theme_name %>
+
+## Usage
+
+TODO: Write usage instructions here. Describe your available layouts, includes, sass and/or assets.
+
+## Contributing
+
+Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/<%= theme_name %>. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](https://www.contributor-covenant.org/) code of conduct.
+
+## Development
+
+To set up your environment to develop this theme, run `bundle install`.
+
+Your theme is setup just like a normal Jekyll site! To test your theme, run `bundle exec jekyll serve` and open your browser at `http://localhost:4000`. This starts a Jekyll server using your theme. Add pages, documents, data, etc. like normal to test your theme's contents. As you make modifications to your theme and to your content, your site will regenerate and you should see the changes in the browser after a refresh, just like normal.
+
+When your theme is released, only the files in `_layouts`, `_includes`, `_sass` and `assets` tracked with Git will be bundled.
+To add a custom directory to your theme-gem, please edit the regexp in `<%= theme_name %>.gemspec` accordingly.
+
+## License
+
+The theme is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/_layouts/default.html b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/_layouts/default.html
new file mode 100644
index 0000000..cddd070
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/_layouts/default.html
@@ -0,0 +1 @@
+{{ content }}
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/_layouts/page.html b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/_layouts/page.html
new file mode 100644
index 0000000..5e71126
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/_layouts/page.html
@@ -0,0 +1,5 @@
+---
+layout: default
+---
+
+{{ content }}
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/_layouts/post.html b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/_layouts/post.html
new file mode 100644
index 0000000..5e71126
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/_layouts/post.html
@@ -0,0 +1,5 @@
+---
+layout: default
+---
+
+{{ content }}
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/_config.yml.erb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/_config.yml.erb
new file mode 100644
index 0000000..82e8d42
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/_config.yml.erb
@@ -0,0 +1 @@
+theme: <%= theme_name %>
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/_post.md b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/_post.md
new file mode 100644
index 0000000..145b21d
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/_post.md
@@ -0,0 +1,12 @@
+---
+layout: post
+---
+
+Eos eu docendi tractatos sapientem, brute option menandri in vix, quando vivendo accommodare te ius. Nec melius fastidii constituam id, viderer theophrastus ad sit, hinc semper periculis cum id. Noluisse postulant assentior est in, no choro sadipscing repudiandae vix. Vis in euismod delenit dignissim. Ex quod nostrum sit, suas decore animal id ius, nobis solet detracto quo te.
+
+{% comment %}
+Might you have an include in your theme? Why not try it here!
+{% include my-themes-great-include.html %}
+{% endcomment %}
+
+No laudem altera adolescens has, volumus lucilius eum no. Eam ei nulla audiam efficiantur. Suas affert per no, ei tale nibh sea. Sea ne magna harum, in denique scriptorem sea, cetero alienum tibique ei eos. Labores persequeris referrentur eos ei.
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/index.html b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/index.html
new file mode 100644
index 0000000..b688538
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/index.html
@@ -0,0 +1,14 @@
+---
+layout: page
+---
+
+Lorem ipsum dolor sit amet, quo id prima corrumpit pertinacia, id ius dolor dolores, an veri pertinax explicari mea. Agam solum et qui, his id ludus graeco adipiscing. Duis theophrastus nam in, at his vidisse atomorum. Tantas gloriatur scripserit ne eos. Est wisi tempor habemus at, ei graeco dissentiet eos. Ne usu aliquip sanctus conceptam, te vis ignota animal, modus latine contentiones ius te.
+
+{% for post in site.posts %}
+<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
+<blockquote>{{ post.excerpt }}</blockquote>
+{% endfor %}
+
+Te falli veritus sea, at molestiae scribentur deterruisset vix, et mea zril phaedrum vulputate. No cum dicit consulatu. Ut has nostro noluisse expetendis, te pro quaeque disputando, eu sed summo omnes. Eos at tale aperiam, usu cu propriae quaestio constituto, sed aperiam erroribus temporibus an.
+
+Quo eu liber mediocritatem, vix an delectus eleifend, iuvaret suscipit ei vel. Partem invenire per an, mea postulant dissentias eu, ius tantas audire nominavi eu. Dicunt tritani veritus ex vis, mei in case sententiae. At exerci democritum nam, cu lobortis iracundia mei. Alia eligendi consectetuer eu sed, paulo docendi noluisse sit ex.
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/style.scss b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/style.scss
new file mode 100644
index 0000000..7388f52
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/example/style.scss
@@ -0,0 +1,7 @@
+---
+---
+
+// Here, you can test out the Sass/SCSS that you include in your theme.
+// Simply `@import` the necessary file(s) to get the proper styles on the site.
+// E.g.:
+// @import "a-file-from-my-theme";
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/gitignore.erb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/gitignore.erb
new file mode 100644
index 0000000..736d740
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/gitignore.erb
@@ -0,0 +1,6 @@
+*.gem
+.bundle
+.jekyll-cache
+.sass-cache
+_site
+Gemfile.lock
diff --git a/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/theme.gemspec.erb b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/theme.gemspec.erb
new file mode 100644
index 0000000..7c13cd3
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/jekyll-4.4.1/lib/theme_template/theme.gemspec.erb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+Gem::Specification.new do |spec|
+ spec.name = <%= theme_name.inspect %>
+ spec.version = "0.1.0"
+ spec.authors = [<%= user_name.inspect %>]
+ spec.email = [<%= user_email.inspect %>]
+
+ spec.summary = "TODO: Write a short summary, because Rubygems requires one."
+ spec.homepage = "TODO: Put your gem's website or public repo URL here."
+ spec.license = "MIT"
+
+ spec.files = `git ls-files -z`.split("\x0").select { |f| f.match(%r!^(<%= theme_directories.join("|") %>|LICENSE|README|_config\.yml)!i) }
+
+ spec.add_runtime_dependency "jekyll", "~> <%= jekyll_version_with_minor %>"
+end