Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoSign in
Socket

mkdocs-material

Package Overview
Dependencies
Maintainers
1
Versions
439
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mkdocs-material - pypi Package Compare versions

Comparing version
9.6.23
to
9.7.0
+223
material/extensions/preview.py
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
from __future__ import annotations
import logging
from material.utilities.filter import FileFilter, FilterConfig
from mkdocs.structure.pages import _RelativePathTreeprocessor
from markdown import Extension, Markdown
from markdown.treeprocessors import Treeprocessor
from mkdocs.exceptions import ConfigurationError
from urllib.parse import urlparse
from xml.etree.ElementTree import Element
# -----------------------------------------------------------------------------
# Classes
# -----------------------------------------------------------------------------
class PreviewProcessor(Treeprocessor):
"""
A Markdown treeprocessor to enable instant previews on links.
Note that this treeprocessor is dependent on the `relpath` treeprocessor
registered programmatically by MkDocs before rendering a page.
"""
def __init__(self, md: Markdown, config: dict):
"""
Initialize the treeprocessor.
Arguments:
md: The Markdown instance.
config: The configuration.
"""
super().__init__(md)
self.config = config
def run(self, root: Element):
"""
Run the treeprocessor.
Arguments:
root: The root element of the parsed Markdown document.
"""
at = self.md.treeprocessors.get_index_for_name("relpath")
# Hack: Python Markdown has no notion of where it is, i.e., which file
# is being processed. This seems to be a deliberate design decision, as
# it is not possible to access the file path of the current page, but
# it might also be an oversight that is now impossible to fix. However,
# since this extension is only useful in the context of Material for
# MkDocs, we can assume that the _RelativePathTreeprocessor is always
# present, telling us the file path of the current page. If that ever
# changes, we would need to wrap this extension in a plugin, but for
# the time being we are sneaky and will probably get away with it.
processor = self.md.treeprocessors[at]
if not isinstance(processor, _RelativePathTreeprocessor):
raise TypeError("Relative path processor not registered")
# Normalize configurations
configurations = self.config["configurations"]
configurations.append({
"sources": self.config.get("sources"),
"targets": self.config.get("targets")
})
# Walk through all configurations - @todo refactor so that we don't
# iterate multiple times over the same elements
for configuration in configurations:
# Skip, if the configuration defines nothing – we could also fix
# this in the file filter, but we first fix it here and check if
# it generalizes well enough to other inclusion/exclusion sites,
# because here, it would hinder the ability to automaticaly
# include all sources, while excluding specific targets.
if (
not configuration.get("sources") and
not configuration.get("targets")
):
continue
# Skip if page should not be considered
filter = get_filter(configuration, "sources")
if not filter(processor.file):
continue
# Walk through all links and add preview attributes
filter = get_filter(configuration, "targets")
for el in root.iter("a"):
href = el.get("href")
if not href:
continue
# Skip footnotes
if "footnote-ref" in el.get("class", ""):
continue
# Skip external links
url = urlparse(href)
if url.scheme or url.netloc:
continue
# Add preview attribute to internal links
for path in processor._possible_target_uris(
processor.file, url.path,
processor.config.use_directory_urls
):
target = processor.files.get_file_from_path(path)
if not target:
continue
# Include, if filter matches
if filter(target):
el.set("data-preview", "")
# -----------------------------------------------------------------------------
class PreviewExtension(Extension):
"""
A Markdown extension to enable instant previews on links.
This extensions allows to automatically add the `data-preview` attribute to
internal links matching specific criteria, so Material for MkDocs renders a
nice preview on hover as part of a tooltip. It is the recommended way to
add previews to links in a programmatic way.
"""
def __init__(self, *args, **kwargs):
"""
"""
self.config = {
"configurations": [[], "Filter configurations"],
"sources": [{}, "Link sources"],
"targets": [{}, "Link targets"]
}
super().__init__(*args, **kwargs)
def extendMarkdown(self, md: Markdown):
"""
Register Markdown extension.
Arguments:
md: The Markdown instance.
"""
md.registerExtension(self)
# Create and register treeprocessor - we use the same priority as the
# `relpath` treeprocessor, the latter of which is guaranteed to run
# after our treeprocessor, so we can check the original Markdown URIs
# before they are resolved to URLs.
processor = PreviewProcessor(md, self.getConfigs())
md.treeprocessors.register(processor, "preview", 0)
# -----------------------------------------------------------------------------
# Functions
# -----------------------------------------------------------------------------
def get_filter(settings: dict, key: str):
"""
Get file filter from settings.
Arguments:
settings: The settings.
key: The key in the settings.
Returns:
The file filter.
"""
config = FilterConfig()
config.load_dict(settings.get(key) or {})
# Validate filter configuration
errors, warnings = config.validate()
for _, w in warnings:
log.warning(
f"Error reading filter configuration in '{key}':\n"
f"{w}"
)
for _, e in errors:
raise ConfigurationError(
f"Error reading filter configuration in '{key}':\n"
f"{e}"
)
# Return file filter
return FileFilter(config = config) # type: ignore
def makeExtension(**kwargs):
"""
Register Markdown extension.
Arguments:
**kwargs: Configuration options.
Returns:
The Markdown extension.
"""
return PreviewExtension(**kwargs)
# -----------------------------------------------------------------------------
# Data
# -----------------------------------------------------------------------------
# Set up logging
log = logging.getLogger("mkdocs.material.extensions.preview")
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
import os
from mkdocs.config.base import Config
from mkdocs.config.config_options import ListOfItems, Type
# -----------------------------------------------------------------------------
# Classes
# -----------------------------------------------------------------------------
# Optimize plugin configuration
class OptimizeConfig(Config):
enabled = Type(bool, default = True)
concurrency = Type(int, default = max(1, os.cpu_count() - 1))
# Settings for caching
cache = Type(bool, default = True)
cache_dir = Type(str, default = ".cache/plugin/optimize")
# Settings for optimization
optimize = Type(bool, default = True)
optimize_png = Type(bool, default = True)
optimize_png_speed = Type(int, default = 3)
optimize_png_strip = Type(bool, default = True)
optimize_jpg = Type(bool, default = True)
optimize_jpg_quality = Type(int, default = 60)
optimize_jpg_progressive = Type(bool, default = True)
optimize_include = ListOfItems(Type(str), default = [])
optimize_exclude = ListOfItems(Type(str), default = [])
# Settings for reporting
print_gain = Type(bool, default = True)
print_gain_summary = Type(bool, default = True)
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
from __future__ import annotations
import functools
import json
import logging
import os
import subprocess
import sys
from fnmatch import fnmatch
from colorama import Fore, Style
from concurrent.futures import Future
from concurrent.futures.thread import ThreadPoolExecutor
from hashlib import sha1
from mkdocs import utils
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.exceptions import PluginError
from mkdocs.plugins import BasePlugin
from mkdocs.structure.files import File
from shutil import which
try:
from PIL import Image
except ImportError:
pass
from .config import OptimizeConfig
# -----------------------------------------------------------------------------
# Classes
# -----------------------------------------------------------------------------
# Optimize plugin
class OptimizePlugin(BasePlugin[OptimizeConfig]):
supports_multiple_instances = True
# Manifest
manifest: dict[str, str] = {}
# Initialize plugin
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Initialize incremental builds
self.is_serve = False
# Determine whether we're serving the site
def on_startup(self, *, command, dirty):
self.is_serve = command == "serve"
# Initialize thread pool
self.pool = ThreadPoolExecutor(self.config.concurrency)
self.pool_jobs: dict[str, Future] = {}
# Resolve and load manifest
def on_config(self, config):
if not self.config.enabled:
return
# Resolve cache directory (once) - this is necessary, so the cache is
# always relative to the configuration file, and thus project, and not
# relative to the current working directory, or it would not work with
# the projects plugin.
path = os.path.abspath(self.config.cache_dir)
if path != self.config.cache_dir:
self.config.cache_dir = os.path.join(
os.path.dirname(config.config_file_path),
os.path.normpath(self.config.cache_dir)
)
# Ensure cache directory exists
os.makedirs(self.config.cache_dir, exist_ok = True)
# Initialize manifest
self.manifest_file = os.path.join(
self.config.cache_dir, "manifest.json"
)
# Load manifest if it exists and the cache should be used
if os.path.isfile(self.manifest_file) and self.config.cache:
try:
with open(self.manifest_file) as f:
self.manifest = json.load(f)
except:
pass
# Initialize optimization pipeline
def on_env(self, env, *, config, files):
if not self.config.enabled:
return
# Skip if media files should not be optimized
if not self.config.optimize:
return
# Filter all optimizable media files and steal reponsibility from MkDocs
# by removing them from the files collection. Then, start a concurrent
# job that checks if an image was already optimized and can be returned
# from the cache, or optimize it accordingly.
for file in files.media_files():
if self._is_excluded(file):
continue
# Spawn concurrent job to optimize the given image and add future
# to job dictionary, as it returns the file we need to copy later
path = os.path.join(self.config.cache_dir, file.src_path)
self.pool_jobs[file.abs_src_path] = self.pool.submit(
self._optimize_image, file, path, config
)
# Steal responsibility from MkDocs
files.remove(file)
# Finish optimization pipeline
def on_post_build(self, *, config):
if not self.config.enabled:
return
# Skip if media files should not be optimized
if not self.config.optimize:
return
# Reconcile concurrent jobs - we need to wait for all jobs to finish
# before we can copy the optimized files to the output directory. If an
# exception occurred in one of the jobs, we raise it here, so the build
# fails and the author can fix the issue.
for path, future in self.pool_jobs.items():
if future.exception():
raise future.exception()
else:
file: File = future.result()
file.copy_file()
# Save manifest if cache should be used
if self.config.cache:
with open(self.manifest_file, "w") as f:
f.write(json.dumps(self.manifest, indent = 2, sort_keys = True))
# Compute and print gains through optimization
if self.config.print_gain_summary:
print(Style.NORMAL)
print(f" Optimizations:")
# Print summary for file extension
for seek in [".png", ".jpg"]:
size = size_opt = 0
for path, future in self.pool_jobs.items():
file: File = future.result()
# Skip files that are not of the given type
_, extension = os.path.splitext(path)
extension = ".jpg" if extension == ".jpeg" else extension
if extension != seek:
continue
# Compute size before and after optimization
size += os.path.getsize(path)
size_opt += os.path.getsize(file.abs_dest_path)
# Compute absolute and relative gain
if size and size_opt:
gain_abs = size - size_opt
gain_rel = (1 - size_opt / size) * 100
# Print summary for files
print(
f" *{seek} {Fore.GREEN}{_size(size_opt)}"
f"{Fore.WHITE}{Style.DIM} ↓ "
f"{_size(gain_abs)} [{gain_rel:3.1f}%]"
f"{Style.RESET_ALL}"
)
# Reset all styles
print(Style.RESET_ALL)
# Save manifest on shutdown
def on_shutdown(self):
if not self.config.enabled:
return
# Shutdown thread pool - if we're on Python 3.9 and above, cancel all
# pending futures that have not yet been scheduled
if sys.version_info >= (3, 9):
self.pool.shutdown(cancel_futures = True)
else:
self.pool.shutdown()
# Save manifest if cache should be used
if self.manifest and self.config.cache:
with open(self.manifest_file, "w") as f:
f.write(json.dumps(self.manifest, indent = 2, sort_keys = True))
# -------------------------------------------------------------------------
# Check if a file can be optimized
def _is_optimizable(self, file: File):
# Check if PNG images should be optimized
if file.url.endswith((".png")):
return self.config.optimize_png
# Check if JPG images should be optimized
if file.url.endswith((".jpg", ".jpeg")):
return self.config.optimize_jpg
# File can not be optimized by the plugin
return False
# Check if the given file is excluded
def _is_excluded(self, file: File):
if not self._is_optimizable(file):
return True
# Check if file matches one of the inclusion patterns
path = file.src_path
if self.config.optimize_include:
for pattern in self.config.optimize_include:
if fnmatch(file.src_uri, pattern):
return False
# File is not included
log.debug(f"Excluding file '{path}' due to inclusion patterns")
return True
# Check if file matches one of the exclusion patterns
for pattern in self.config.optimize_exclude:
if fnmatch(file.src_uri, pattern):
log.debug(f"Excluding file '{path}' due to exclusion patterns")
return True
# File is not excluded
return False
# Optimize image and write to cache
def _optimize_image(self, file: File, path: str, config: MkDocsConfig):
with open(file.abs_src_path, "rb") as f:
data = f.read()
hash = sha1(data).hexdigest()
# Check if file hash changed, so we need to optimize again
prev = self.manifest.get(file.url, "")
if hash != prev or not os.path.isfile(path):
os.makedirs(os.path.dirname(path), exist_ok = True)
# Optimize PNG image using pngquant
if file.url.endswith((".png")):
self._optimize_image_png(file, path, config)
# Optimize JPG image using pillow
if file.url.endswith((".jpg", ".jpeg")):
self._optimize_image_jpg(file, path, config)
# Compute size before and after optimization
size = len(data)
size_opt = os.path.getsize(path)
# Compute absolute and relative gain
gain_abs = size - size_opt
gain_rel = (1 - size_opt / size) * 100
# Print how much we gained, if we did and desired
gain = ""
if gain_abs and self.config.print_gain:
gain += " ↓ "
gain += " ".join([_size(gain_abs), f"[{gain_rel:3.1f}%]"])
# Print summary for file
log.info(
f"Optimized media file: {file.src_uri} "
f"{Fore.GREEN}{_size(size_opt)}"
f"{Fore.WHITE}{Style.DIM}{gain}"
f"{Style.RESET_ALL}"
)
# Update manifest by associating file with hash
self.manifest[file.url] = hash
# Compute project root
root = os.path.dirname(config.config_file_path)
# Compute source file system path
file.abs_src_path = path
file.src_path = os.path.relpath(path, root)
# Return file to be copied from cache
return file
# Optimize PNG image - we first tried to use libimagequant, but encountered
# the occassional segmentation fault, which means it's probably not a good
# choice. Instead, we just rely on pngquant which seems much more stable.
def _optimize_image_png(self, file: File, path: str, config: MkDocsConfig):
# Check if the required dependencies for optimizing are available, which
# is, at the absolute minimum, the 'pngquant' binary, and raise an error
# to the caller, so he can decide what to do with the error. The caller
# can treat this as a warning or an error to abort the build.
if not which("pngquant"):
docs = os.path.relpath(config.docs_dir)
path = os.path.relpath(file.abs_src_path, docs)
raise PluginError(
f"Couldn't optimize image '{path}' in '{docs}': 'pngquant' "
f"not found. Make sure 'pngquant' is installed and in your path"
)
# Build command line arguments
args = ["pngquant",
"--force", "--skip-if-larger",
"--output", path,
"--speed", f"{self.config.optimize_png_speed}"
]
# Add flag to remove optional metadata
if self.config.optimize_png_strip:
args.append("--strip")
# Set input file and run, then check if pngquant actually wrote a file,
# as we instruct it not to if the size of the optimized file is larger.
# This can happen if files are already compressed and optimized by
# the author. In that case, just copy the original file.
subprocess.run([*args, file.abs_src_path])
if not os.path.isfile(path):
utils.copy_file(file.abs_src_path, path)
# Optimize JPG image
def _optimize_image_jpg(self, file: File, path: str, config: MkDocsConfig):
# Check if the required dependencies for optimizing are available, which
# is, at the absolute minimum, the 'pillow' package, and raise an error
# to the caller, so he can decide what to do with the error. The caller
# can treat this as a warning or an error to abort the build.
if not _supports("Image"):
docs = os.path.relpath(config.docs_dir)
path = os.path.relpath(file.abs_src_path, docs)
raise PluginError(
f"Couldn't optimize image '{path}' in '{docs}': install "
f"required dependencies – pip install 'mkdocs-material[imaging]'"
)
# Open and save optimized image
image = Image.open(file.abs_src_path)
image.save(path, "jpeg",
quality = self.config.optimize_jpg_quality,
progressive = self.config.optimize_jpg_progressive
)
# -----------------------------------------------------------------------------
# Helper functions
# -----------------------------------------------------------------------------
# Check for presence of optional imports
@functools.lru_cache(maxsize = None)
def _supports(name: str):
return name in globals()
# -----------------------------------------------------------------------------
# Print human-readable size
def _size(value):
for unit in ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB"]:
if abs(value) < 1000.0:
return f"{value:3.1f} {unit}"
value /= 1000.0
# -----------------------------------------------------------------------------
# Data
# -----------------------------------------------------------------------------
# Set up logging
log = logging.getLogger("mkdocs.material.optimize")
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
from __future__ import annotations
import logging
import multiprocessing
import os
import posixpath
from collections.abc import Callable
from concurrent.futures import Future, as_completed
from concurrent.futures.process import ProcessPoolExecutor
from logging import Logger
from material.plugins.projects.config import ProjectsConfig
from material.plugins.projects.structure import Project, ProjectJob
from mkdocs.commands.build import build
from mkdocs.config.base import ConfigErrors, ConfigWarnings
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.exceptions import Abort
from mkdocs.livereload import LiveReloadServer
from urllib.parse import urlparse
from .log import (
get_log_for,
get_log_formatter,
get_log_handler,
get_log_level_for
)
from .watcher import ProjectsWatcher
# -----------------------------------------------------------------------------
# Classes
# -----------------------------------------------------------------------------
# Projects builder
class ProjectsBuilder:
# Set of projects
projects: set[Project] = set()
# Projects watcher
watcher: ProjectsWatcher | None = None
# Initialize projects builder - compared to our other concurrent plugins,
# this plugin is forced to use a process pool in order to guarantee proper
# isolation, as MkDocs itself is not thread-safe. We also need to recreate
# the process pool on every build, or CTRL-C is broken
def __init__(self, config: MkDocsConfig, plugin: ProjectsConfig):
# Initialize root project
self.root = Project(config.config_file_path, plugin)
self.root.config = config
# Initialize process pool
self.pool = ProcessPoolExecutor
self.pool_jobs: dict[str, Future] = {}
# Build projects
def build(self, serve: bool = False, dirty: bool = False):
self.pool = ProcessPoolExecutor(
self.root.plugin.concurrency,
mp_context = multiprocessing.get_context("spawn")
)
# Determine projects in topological order and prepare for building
built: list[str] = []
queue = [*self.root.jobs()]
for job in queue:
_setup(job.project, self.root, serve)
if serve:
self._link(job.project)
# Schedule projects for building
for job in reversed(queue):
if self._schedule(job, serve, dirty):
queue.remove(job)
# Build loop - iteratively build more projects while there are still
# projects to be built, sticking to the topological order.
while len(built) < len(self.pool_jobs):
for future in as_completed(self.pool_jobs.values()):
slug, errors, warnings = future.result()
if slug in built:
continue
# Mark project as built
built.append(slug)
# Schedule projects for building
for job in reversed(queue):
if self._schedule(job, serve, dirty):
queue.remove(job)
# Print errors and warnings
for project in self.projects:
if project.slug == slug:
_print(get_log_for(project), errors, warnings)
break
# Shutdown process pool
self.pool.shutdown()
if self.watcher:
# Update watched paths
for project in self.projects:
if project.slug not in built:
self.pool_jobs.pop(project.slug, None)
self.watcher.unwatch(project)
else:
self.watcher.watch(project, self.taint)
# Taint a project to schedule it for building
def taint(self, project: Project):
self.pool_jobs.pop(project.slug, None)
# Watch and serve projects
def serve(self, server: LiveReloadServer, is_dirty: bool = False):
self.watcher = ProjectsWatcher(server)
self.watcher.watch(self.root, self.taint)
for project in self.projects:
self.watcher.watch(project, self.taint)
# -------------------------------------------------------------------------
# Create symlink for project if we're serving the site
def _link(self, project: Project):
# Compute path for slug from current project - normalize path,
# as paths computed from slugs or site URLs use forward slashes
path = project.path(self.root)
path = os.path.normpath(path)
# Create symbolic link, if we haven't already
path = os.path.join(self.root.config.site_dir, path)
if not os.path.islink(path):
# Ensure link target exists
target = os.path.realpath(os.path.dirname(path))
if not os.path.exists(target):
os.makedirs(target, exist_ok = True)
# Create symbolic link
os.makedirs(os.path.dirname(path), exist_ok = True)
os.symlink(project.config.site_dir, path)
# Schedule project for building - spawn concurrent job to build the project
# and add a future to the jobs dictionary to link build results to projects
def _schedule(self, job: ProjectJob, serve: bool, dirty: bool):
self.projects.add(job.project)
# Exit early, if project doesn't need to be re built
if job.project.slug in self.pool_jobs:
return True
# Check if dependencies have been built already, and if so, remove
# them from the list of dependencies. If a dependency has failed to
# build, we'll raise an exception, which will be caught by the main
# process, and the entire build will be aborted.
for dependency in [*job.dependencies]:
future = self.pool_jobs[dependency.slug]
if future.running():
continue
# If the dependency has failed to build, we'll raise an exception
# to abort the entire build, as we can't build the project itself
# without the dependency. This will be caught by the main process.
# Otherwise, we'll remove the dependency from the list.
if future.exception():
raise future.exception()
elif future.done():
job.dependencies.remove(dependency)
# If all dependencies of the project have been built, we can build
# the project itself by spawning a concurrent job
if not job.dependencies:
self.pool_jobs[job.project.slug] = self.pool.submit(
_build, job.project, serve, dirty,
get_log_level_for(job.project)
)
# Return whether the project has been scheduled
return not job.dependencies
# -----------------------------------------------------------------------------
# Helper functions
# -----------------------------------------------------------------------------
# Setup project by preparing it for building
def _setup(project: Project, root: Project, serve: bool):
assert project.slug != "."
# Retrieve configuration of top-level project and transform project
transform = root.plugin.projects_config_transform
if isinstance(transform, Callable):
transform(project, root)
# If the top-level project defines a site URL, we need to make sure that the
# site URL of the project is set as well, setting it to the path we derive
# from the slug. This allows to define the URL independent of the entire
# project's directory structure. If the top-level project doesn't define a
# site URL, it might be the case that the author is building a consolidated
# project of several nested projects that are independent, but which should
# be bundled together for distribution. As this is a case that is quite
# common, we're not raising a warning or error.
path = project.path(root)
if root.config.site_url:
# If the project doesn't have a site URL, compute it from the site URL
# of the top-level project and the path derived from the slug
if not project.config.site_url:
project.config.site_url = posixpath.join(
root.config.site_url,
path
)
# If we're serving the site, replace the project's host name with the
# dev server address, so we can serve nested projects as well
if serve:
url = urlparse(project.config.site_url)
url = url._replace(
scheme = "http",
netloc = str(root.config.dev_addr)
)
# Update site URL with dev server address
project.config.site_url = url.geturl()
# If we're building the site, the project's output must be written to the
# site directory of the top-level project, so we can serve it from there
if not serve:
project.config.site_dir = os.path.join(
root.config.site_dir,
os.path.normpath(path)
)
# If we're serving the site, we must fall back to symbolic links, as MkDocs
# will empty the entire site directory every time it performs a build
else:
project.config.site_dir = os.path.join(
os.path.dirname(project.config.config_file_path),
project.config.site_dir
)
# Build project - note that regardless of whether MkDocs was started in build
# or serve mode, projects must always be built, as they're served by the root
def _build(project: Project, serve: bool, dirty: bool, level = logging.WARN):
config = project.config
# Change working directory to project root - this is necessary, or relative
# paths used in extensions and plugins will be resolved incorrectly
os.chdir(os.path.dirname(config.config_file_path))
# Validate configuration
errors, warnings = config.validate()
if not errors:
# Retrieve and configure MkDocs' logger
log = logging.getLogger("mkdocs")
log.setLevel(level)
# Hack: there seems to be an inconsistency between operating systems,
# and it's yet unclear where this is coming from - on macOS, the MkDocs
# default logger has no designated handler registered, but on Linux it
# does. If there's no handler, we need to create one. If there is, we
# must only set the formatter, as otherwise we'll end up with the same
# message printed on two log handlers - see https://t.ly/q7UEq
handler = get_log_handler(project)
if not log.hasHandlers():
log.addHandler(handler)
else:
for handler in log.handlers:
handler.setFormatter(get_log_formatter(project))
# Build project and dispatch startup and shutdown plugin events - note
# that we must pass the correct command to the event handler, but run
# the build command anyway, because otherwise some plugins will not
# run in serve mode.
command = "serve" if serve else "build"
config.plugins.run_event("startup", command = command, dirty = dirty)
try:
build(config, dirty = dirty)
finally:
config.plugins.run_event("shutdown")
log.removeHandler(handler)
# Return slug, errors and warnings
return project.slug, errors, warnings
# Print errors and warnings resulting from building a project
def _print(log: Logger, errors: ConfigErrors, warnings: ConfigWarnings):
# Print warnings
for value, message in warnings:
log.warning(f"Config value '{value}': {message}")
# Print errors
for value, message in errors:
log.error(f"Config value '{value}': {message}")
# Abort if there were errors
if errors:
raise Abort(f"Aborted with {len(errors)} configuration errors")
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
from __future__ import annotations
import logging
from click import style
from logging import Filter
from material.plugins.projects.structure import Project
from mkdocs.__main__ import ColorFormatter
# -----------------------------------------------------------------------------
# Classes
# -----------------------------------------------------------------------------
# Dirty build warning filter
class ProjectsFilter(Filter):
# Filter log messages
def filter(self, record):
message = record.getMessage()
return not message.startswith("A 'dirty' build")
# -----------------------------------------------------------------------------
# Functions
# -----------------------------------------------------------------------------
# Retrieve logger for project
def get_log_for(project: Project):
log = logging.getLogger("".join(["mkdocs.material.projects", project.slug]))
# Ensure logger does not propagate messags to parent logger, or messages
# will be printed multiple times, and attach handler with color formatter
log.propagate = False
if not log.hasHandlers():
log.addHandler(get_log_handler(project))
log.setLevel(get_log_level_for(project))
# Return logger
return log
# Retrieve log level for project
def get_log_level_for(project: Project):
level = logging.INFO
# Determine log level as set in MkDocs - if the build is started with the
# `--quiet` flag, the log level is set to `ERROR` to suppress all messages,
# except for errors. If it's started with `--verbose`, MkDocs sets the log
# level to `DEBUG`, the most verbose of all log levels.
log = logging.getLogger("mkdocs")
for handler in log.handlers:
level = handler.level
break
# Determine if MkDocs was invoked with the `--quiet` flag and the log level
# as configured in the plugin configuration. When `--quiet` is set, or the
# projects plugin configuration disables logging, ignore the configured log
# level and set it to `ERROR` to suppress all messages.
quiet = level == logging.ERROR
level = project.plugin.log_level.upper()
if quiet or not project.plugin.log:
level = logging.ERROR
# Retun log level
return level
# -----------------------------------------------------------------------------
# Retrieve log handler for project
def get_log_handler(project: Project):
handler = logging.StreamHandler()
handler.setFormatter(get_log_formatter(project))
# Add filter to suppress dirty build warning, or we'll get as many of those
# as projects are built - one warning is surely enough, KTHXBYE
handler.addFilter(ProjectsFilter())
return handler
# Retrieve log formatter for project
def get_log_formatter(project: Project):
prefix = style(f"project://{project.slug}", underline = True)
return ColorFormatter(f"[{prefix}] %(message)s")
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
from __future__ import annotations
import os
from collections.abc import Callable
from material.plugins.projects.structure import Project
from mkdocs.livereload import LiveReloadServer
from .handler import ProjectChanged, ProjectAddedOrRemoved
# -----------------------------------------------------------------------------
# Classes
# -----------------------------------------------------------------------------
# Projects watcher
class ProjectsWatcher:
# Set of watched paths
watched: set[str] = set()
# Initialize projects watcher
def __init__(self, server: LiveReloadServer):
self.server = server
# Watch project and invoke function on change
def watch(self, project: Project, fn: Callable):
self._on_project_changed(project, fn)
self._on_project_added_or_removed(project, fn)
# Stop watching project
def unwatch(self, project: Project):
# Traverse all watched paths
root = os.path.dirname(project.config.config_file_path)
for path in [*self.watched]:
# Remove path from watched paths
if path.startswith(root):
self.server.unwatch(path)
self.watched.remove(path)
# -------------------------------------------------------------------------
# Register event handler for project changes
def _on_project_changed(self, project: Project, fn: Callable):
# Resolve project root and docs directory
root = os.path.dirname(project.config.config_file_path)
docs = os.path.join(root, project.config.docs_dir)
# Collect all paths to watch
paths = set([docs, project.config.config_file_path])
for path in project.config.watch:
paths.add(os.path.join(root, path))
# Register event handler for unwatched paths
handler = ProjectChanged(project, fn)
for path in paths - self.watched:
self.server.watch(path)
# Add path and its descendents to watched paths
self.server.observer.schedule(handler, path, recursive = True)
self.watched.add(path)
# Register event handler for project additions and removals
def _on_project_added_or_removed(self, project: Project, fn: Callable):
# Resolve project root and path to projects directory
root = os.path.dirname(project.config.config_file_path)
path = os.path.join(root, project.plugin.projects_dir)
# Register event handler for unwatched paths
handler = ProjectAddedOrRemoved(project, fn)
if path not in self.watched and os.path.isdir(path):
# Add path to watched paths
self.server.observer.schedule(handler, path)
self.watched.add(path)
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
from __future__ import annotations
import logging
import os
from collections.abc import Callable
from material.plugins.projects.structure import Project
from watchdog.events import FileSystemEvent, FileSystemEventHandler
# -----------------------------------------------------------------------------
# Classes
# -----------------------------------------------------------------------------
# Project changed
class ProjectChanged(FileSystemEventHandler):
# Initialize event handler
def __init__(self, project: Project, handler: Callable):
self.project = project
self.handler = handler
# Handle file event
def on_any_event(self, event: FileSystemEvent):
self._handle(event)
# -------------------------------------------------------------------------
# Invoke file event handler
def _handle(self, event: FileSystemEvent):
config = self.project.config
# Resolve path to docs directory
base = os.path.dirname(config.config_file_path)
docs = os.path.join(base, config.docs_dir)
# Resolve project root and path to changed file
root = os.path.relpath(base)
path = os.path.relpath(event.src_path, root)
# Check if mkdocs.yml or docs directory was deleted
if event.src_path in [docs, config.config_file_path]:
if event.event_type == "deleted":
return
# Invoke handler and print message that we're scheduling a build
log.info(f"Schedule build due to '{path}' in '{root}'")
self.handler(self.project)
# -----------------------------------------------------------------------------
# Project added or removed
class ProjectAddedOrRemoved(FileSystemEventHandler):
# Initialize event handler
def __init__(self, project: Project, handler: Callable):
self.project = project
self.handler = handler
# Handle file creation event
def on_created(self, event: FileSystemEvent):
self._handle(event)
# Handle file deletion event
def on_deleted(self, event: FileSystemEvent):
self._handle(event)
# ------------------------------------------------------------------------
# Invoke file event handler
def _handle(self, event: FileSystemEvent):
config = self.project.config
# Touch mkdocs.yml to trigger rebuild
if os.path.isfile(config.config_file_path):
os.utime(config.config_file_path, None)
# Invoke handler
self.handler(self.project)
# -----------------------------------------------------------------------------
# Data
# -----------------------------------------------------------------------------
# Set up logging
log = logging.getLogger("mkdocs")
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
import os
from collections.abc import Callable
from mkdocs.config.config_options import Choice, Optional, Type
from mkdocs.config.base import Config
# -----------------------------------------------------------------------------
# Options
# -----------------------------------------------------------------------------
# Options for log level
LogLevel = (
"error",
"warn",
"info",
"debug"
)
# -----------------------------------------------------------------------------
# Classes
# -----------------------------------------------------------------------------
# Projects plugin configuration
class ProjectsConfig(Config):
enabled = Type(bool, default = True)
concurrency = Type(int, default = max(1, os.cpu_count() - 1))
# Settings for caching
cache = Type(bool, default = True)
cache_dir = Type(str, default = ".cache/plugin/projects")
# Settings for logging
log = Type(bool, default = True)
log_level = Choice(LogLevel, default = "info")
# Settings for projects
projects = Type(bool, default = True)
projects_dir = Type(str, default = "projects")
projects_config_files = Type(str, default = "*/mkdocs.yml")
projects_config_transform = Optional(Type(Callable))
projects_root_dir = Optional(Type(str))
# Settings for hoisting
hoisting = Type(bool, default = True)
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
from __future__ import annotations
import json
import os
import posixpath
from jinja2 import pass_context
from jinja2.runtime import Context
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.exceptions import PluginError
from mkdocs import utils
from mkdocs.plugins import BasePlugin, event_priority
from mkdocs.structure import StructureItem
from mkdocs.structure.files import Files
from mkdocs.structure.nav import Link, Section
from mkdocs.utils import get_theme_dir
from urllib.parse import ParseResult as URL, urlparse
from .builder import ProjectsBuilder
from .config import ProjectsConfig
from .structure import Project, ProjectLink
# -----------------------------------------------------------------------------
# Classes
# -----------------------------------------------------------------------------
# Projects plugin
class ProjectsPlugin(BasePlugin[ProjectsConfig]):
# Projects builder
builder: ProjectsBuilder = None
# Initialize plugin
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Initialize incremental builds
self.is_serve = False
self.is_dirty = False
# Hack: Since we're building in topological order, we cannot let MkDocs
# clean the directory, because it means that nested projects are always
# deleted before a project is built. We also don't need to restore this
# functionality, because it's only used once in the process.
utils.clean_directory = lambda _: _
# Determine whether we're serving the site
def on_startup(self, *, command, dirty):
self.is_serve = command == "serve"
self.is_dirty = dirty
# Resolve projects – compared to our other concurrent plugins, this plugin
# is forced to use a process pool in order to guarantee proper isolation, as
# MkDocs itself is not thread-safe. Additionally, all project configurations
# are resolved and written to the cache (if enabled), as it's sufficient to
# resolve them once on the top-level before projects are built. We might
# need adjacent project configurations for interlinking projects.
def on_config(self, config):
if not self.config.enabled:
return
# Skip if projects should not be built - we can only exit here if we're
# at the top-level, but not when building a nested project
root = self.config.projects_root_dir is None
if root and not self.config.projects:
return
# Set projects root directory to the top-level project
if not self.config.projects_root_dir:
self.config.projects_root_dir = os.path.dirname(
config.config_file_path
)
# Initialize manifest
self.manifest: dict[str, str] = {}
self.manifest_file = os.path.join(
self.config.projects_root_dir,
self.config.cache_dir,
"manifest.json"
)
# Load manifest if it exists and the cache should be used
if os.path.isfile(self.manifest_file):
try:
with open(self.manifest_file) as f:
self.manifest = json.load(f)
except:
pass
# Building the top-level project, we must resolve and load all project
# configurations, as we need all information upfront to build them in
# the correct order, and to resolve links between projects. Furthermore,
# the author might influence a project's path by setting the site URL.
if root:
if not self.builder:
self.builder = ProjectsBuilder(config, self.config)
# @todo: detach project resolution from build
self.manifest = { ".": os.path.relpath(config.config_file_path) }
for job in self.builder.root.jobs():
path = os.path.relpath(job.project.config.config_file_path)
self.manifest[job.project.slug] = path
# Save manifest, a we need it in nested projects
os.makedirs(os.path.dirname(self.manifest_file), exist_ok = True)
with open(self.manifest_file, "w") as f:
f.write(json.dumps(self.manifest, indent = 2, sort_keys = True))
# Schedule projects for building - the general case is that all projects
# can be considered independent of each other, so we build them in parallel
def on_pre_build(self, config):
if not self.config.enabled:
return
# Skip if projects should not be built or we're not at the top-level
if not self.config.projects or not self.builder:
return
# Build projects
self.builder.build(self.is_serve, self.is_dirty)
# Patch environment to allow for hoisting of media files provided by the
# theme itself, which will also work for other themes, not only this one
def on_env(self, env, *, config, files):
if not self.config.enabled:
return
# Skip if projects should not be built or we're at the top-level
if not self.config.projects or self.builder:
return
# If hoisting is enabled and we're building a project, remove all media
# files that are provided by the theme and hoist them to the top
if self.config.hoisting:
theme = get_theme_dir(config.theme.name)
hoist = Files([])
# Retrieve top-level project and check if the current project uses
# the same theme as the top-level project - if not, don't hoist
root = Project("mkdocs.yml", self.config)
if config.theme.name != root.config.theme["name"]:
return
# Remove all media files that are provided by the theme
for file in files.media_files():
if file.abs_src_path.startswith(theme):
files.remove(file)
hoist.append(file)
# Resolve source and target project
source: Project | None = None
target: Project | None = None
for ref, file in self.manifest.items():
base = os.path.join(self.config.projects_root_dir, file)
if file == os.path.relpath(
config.config_file_path, self.config.projects_root_dir
):
source = Project(base, self.config, ref)
if "." == ref:
target = Project(base, self.config, ref)
# Compute path for slug from source and target project
path = target.path(source)
# Fetch URL template filter from environment - the filter might
# be overridden by other plugins, so we must retrieve and wrap it
url_filter = env.filters["url"]
# Patch URL template filter to add support for correctly resolving
# media files that were hoisted to the top-level project
@pass_context
def url_filter_with_hoisting(context: Context, url: str | None):
if url and hoist.get_file_from_path(url):
return posixpath.join(path, url_filter(context, url))
else:
return url_filter(context, url)
# Register custom template filters
env.filters["url"] = url_filter_with_hoisting
# Adjust project navigation in page (run latest) - as always, allow
# other plugins to alter the navigation before we process it here
@event_priority(-100)
def on_page_context(self, context, *, page, config, nav):
if not self.config.enabled:
return
# Skip if projects should not be built
if not self.config.projects:
return
# Replace project URLs in navigation
self._replace(nav.items, config)
# Adjust project navigation in template (run latest) - as always, allow
# other plugins to alter the navigation before we process it here
@event_priority(-100)
def on_template_context(self, context, *, template_name, config):
if not self.config.enabled:
return
# Skip if projects should not be built
if not self.config.projects:
return
# Replace project URLs in navigation
self._replace(context["nav"].items, config)
# Serve projects
def on_serve(self, server, *, config, builder):
if self.config.enabled:
self.builder.serve(server, self.is_dirty)
# -------------------------------------------------------------------------
# Replace project links in the given list of navigation items
def _replace(self, items: list[StructureItem], config: MkDocsConfig):
for index, item in enumerate(items):
# Handle section
if isinstance(item, Section):
self._replace(item.children, config)
# Handle link
if isinstance(item, Link):
url = urlparse(item.url)
if url.scheme == "project":
project, url = self._resolve_project_url(url, config)
# Append file name if directory URLs are disabled
if not project.config.use_directory_urls:
url += "index.html"
# Replace link with project link
items[index] = ProjectLink(
item.title or project.config.site_name,
url
)
# Resolve project URL and slug
def _resolve_project_url(self, url: URL, config: MkDocsConfig):
# Abort if the project URL contains a path, as we first need to collect
# use cases for when, how and whether we need and want to support this
if url.path != "":
raise PluginError(
f"Couldn't resolve project URL: paths currently not supported\n"
f"Please only use 'project://{url.hostname}'"
)
# Compute slug from host name and convert to dot notation
slug = url.hostname
slug = slug if slug.startswith(".") else f".{slug}"
# Resolve source and target project
source: Project | None = None
target: Project | None = None
for ref, file in self.manifest.items():
base = os.path.join(self.config.projects_root_dir, file)
if file == os.path.relpath(
config.config_file_path, self.config.projects_root_dir
):
source = Project(base, self.config, ref)
if slug == ref:
target = Project(base, self.config, ref)
# Abort if slug doesn't match a known project
if not target:
raise PluginError(f"Couldn't find project '{slug}'")
# Return project slug and path
return target, target.path(source)
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
from __future__ import annotations
import os
import posixpath
import re
from copy import deepcopy
from glob import iglob
from material.plugins.projects.config import ProjectsConfig
from mkdocs.structure.nav import Link
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.config.config_options import Plugins
from urllib.parse import urlparse
# -----------------------------------------------------------------------------
# Classes
# -----------------------------------------------------------------------------
# Project
class Project:
# Initialize project - note that the configuration of the projects plugin
# of the enclosing project is necessary to resolve nested projects
def __init__(self, file: str, plugin: ProjectsConfig, slug = "."):
self.config, self.plugin = self._resolve(file, plugin)
# The slug should not be changed after initialization, as it's used for
# correct resolution of projects and nested projects
self.slug = slug
# Find and yield nested projects of the current project - the project's
# slug is prepended to the computed slug for a simple resolution of nested
# projects, allowing authors to use the project:// protocol for linking to
# projects from the top-level project or nested and adjacent projects
def __iter__(self):
seen: list[str] = []
# Compute project root and base directory
root = os.path.dirname(self.config.config_file_path)
base = os.path.join(root, self.plugin.projects_dir)
# Find and yield all projects - note that we need to filter for nested
# projects at this point, as we're only interested in the projects on
# the next level, not in projects inside projects as they are resolved
# recursively to preserve topological ordering. This is also why we must
# sort the list of projects by path, ordering shorted paths first which
# ensures that nested projects are resolved before their parents.
glob = os.path.join(base, self.plugin.projects_config_files)
glob = iglob(os.path.normpath(glob), recursive = True)
for file in sorted(glob, key = os.path.dirname):
path = os.path.join(os.path.dirname(file), "")
if any(path.startswith(_) for _ in seen):
continue
else:
seen.append(path)
# Extract the first level of the project's directory relative to
# the projects directory as the computed slug of the project. This
# allows authors to build projects whose mkdocs.yml files are not
# located at the project root, e.g., when using git submodules.
slug = os.path.relpath(file, base)
slug, *_ = slug.split(os.path.sep)
# Normalize slug to an internal dot notation which we convert to
# file system or URL paths when necessary. Each slug starts with
# a dot to denote that it is resolved from the top-level project,
# which also allows for resolving slugs in nested projects.
root = self.slug.rstrip(".")
slug = f"{root}.{slug}"
# Create and yield project
yield Project(file, self.plugin, slug)
# Compute project hash
def __hash__(self):
return hash(self.slug)
# Find and yield all nested projects (excluding this project) in reverse
# topological order, by performing a post-order traversal on the tree of
# projects. This function returns project jobs, which are projects with
# their immediate dependencies, to build them in the correct order.
def jobs(self):
stack = [*self]
while stack:
# Pop project from stack and get its dependencies
project = stack.pop()
dependencies = [*project]
# Add project dependencies to stack and yield job
stack.extend(dependencies)
yield ProjectJob(project, dependencies)
# Compute relative path between two projects
def path(self, that: Project):
# If both, the top-level and the current project have a site URL set,
# compute slug from the common path of both site URLs
if self.config.site_url and that.config.site_url:
source = self._path_from_config(that.config)
target = self._path_from_config(self.config)
# Edge case: the author has set a site URL that does not include a
# path, so the path of the project is equal to the top-level path.
# In this case, we need to fall back to the path computed from the
# slug - see https://t.ly/5vqMr
if target == source:
target = self._path_from_slug(self.slug)
# Otherwise, always compute the path from the slugs of both projects,
# as we want to support consolidation of unrelated projects
else:
source = self._path_from_slug(that.slug)
target = self._path_from_slug(self.slug)
# Compute path between projects, and add trailing slash
path = posixpath.relpath(target, source)
return posixpath.join(path, "")
# -------------------------------------------------------------------------
# Resolve project and plugin configuration
def _resolve(self, file: str, plugin: ProjectsConfig):
config = self._resolve_config(file)
plugin = self._resolve_plugin(config, plugin)
# Return project and plugin configuration
return config, plugin
# Resolve project configuration
def _resolve_config(self, file: str):
with open(file, encoding = "utf-8-sig") as f:
config: MkDocsConfig = MkDocsConfig(config_file_path = file)
config.load_file(f)
# Return project configuration
return config
# Resolve project plugin configuration
def _resolve_plugin(self, config: MkDocsConfig, plugin: ProjectsConfig):
# Make sure that every project has a plugin configuration set - we need
# to deep copy the configuration object, as it's mutated during parsing.
# We're using an internal method of the Plugins class to ensure that we
# always stick to the syntaxes allowed by MkDocs (list and dictionary).
plugins = Plugins._parse_configs(deepcopy(config.plugins))
for index, (key, settings) in enumerate(plugins):
if not re.match(r"^(material/)?projects$", key):
continue
# Forward these settings of the plugin configuration to the project,
# as we need to build nested projects consistently
for name in ["cache", "projects", "projects_root_dir", "hoisting"]:
settings[name] = plugin[name]
# Forward these settings only if they have not been set in the
# project configuration, as they might be overwritten by the author
for name in ["log", "log_level"]:
if not name in settings:
settings[name] = plugin[name]
# Initialize and expand the plugin configuration, and mutate the
# plugin collection to persist the patched configuration
plugin: ProjectsConfig = ProjectsConfig()
plugin.load_dict(settings)
if isinstance(config.plugins, list):
config.plugins[index] = { key: dict(plugin.items()) }
else:
config.plugins[key] = dict(plugin.items())
# Return project plugin configuration
return plugin
# If no plugin configuration was found, add the default configuration
# and call this function recursively to ensure that it's present
config.plugins.append("material/projects")
return self._resolve_plugin(config, plugin)
# -------------------------------------------------------------------------
# Compute path from given slug - split slug at dots, ignoring the first one,
# and join the segments to a path, prefixed with a dot. This is necessary
# to compute the common path correctly, so we can use the same logic for
# when the path is computed from the site URL (see below).
def _path_from_slug(self, slug: str):
_, *segments = slug.split(".")
return posixpath.join(".", *segments)
# Compute path from given project configuration - parse site URL and return
# canonicalized path. Paths always start with a dot and trailing slashes are
# always removed. This is necessary so that we can compute the common path
# correctly, since the site URL might or might not contain a trailing slash.
def _path_from_config(self, config: MkDocsConfig):
url = urlparse(config.site_url)
# Remove leading slash, if any
path = url.path
if path.startswith("/"):
path = path[1:]
# Return normalized path
path = posixpath.normpath(path) if path else path
return posixpath.join(".", path)
# -----------------------------------------------------------------------------
# Project job
class ProjectJob:
# Initialize project job
def __init__(self, project: Project, dependencies: list[Project]):
self.project = project
self.dependencies = dependencies
# -----------------------------------------------------------------------------
# Project link
class ProjectLink(Link):
# Indicate that the link points to a project
is_project = True
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
from __future__ import annotations
import re
from mkdocs.config.base import Config
from mkdocs.config.config_options import (
Choice, DictOfItems, ListOfItems, SubConfig, Type
)
try:
from PIL.Image import Image as _Image
except ImportError:
pass
# -----------------------------------------------------------------------------
# Options
# -----------------------------------------------------------------------------
# Options for origin
Origin = (
"start top", "center top", "end top",
"start center", "center", "end center",
"start bottom", "center bottom", "end bottom",
"start", "end"
)
# Options for overflow
Overflow = (
"truncate",
"shrink"
)
# -----------------------------------------------------------------------------
# Classes
# -----------------------------------------------------------------------------
# Size
class Size(Config):
width = Type(int, default = 0)
height = Type(int, default = 0)
# Offset
class Offset(Config):
x = Type(int, default = 0)
y = Type(int, default = 0)
# # -----------------------------------------------------------------------------
# Background
class Background(Config):
color = Type(str, default = "")
image = Type(str, default = "")
# # -----------------------------------------------------------------------------
# Icon
class Icon(Config):
value = Type(str, default = "")
color = Type(str, default = "")
# # -----------------------------------------------------------------------------
# Line
class Line(Config):
amount = Type((int, float), default = 1)
height = Type((int, float), default = 1)
# Font
class Font(Config):
family = Type(str, default = "Roboto")
variant = Type(str, default = "")
style = Type(str, default = "Regular")
# Typography
class Typography(Config):
content = Type(str, default = "")
align = Choice(Origin, default = "start top")
overflow = Choice(Overflow, default = "truncate")
color = Type(str, default = "")
line = SubConfig(Line)
font = SubConfig(Font)
# -----------------------------------------------------------------------------
# Layer
class Layer(Config):
size = SubConfig(Size)
offset = SubConfig(Offset)
origin = Choice(Origin, default = "start top")
background = SubConfig(Background)
icon = SubConfig(Icon)
typography = SubConfig(Typography)
# -----------------------------------------------------------------------------
# Layout
class Layout(Config):
definitions = ListOfItems(Type(str), default = [])
tags = DictOfItems(Type(str), default = {})
size = SubConfig(Size)
layers = ListOfItems(SubConfig(Layer), default = [])
# -----------------------------------------------------------------------------
# Functions
# -----------------------------------------------------------------------------
# Get layer or layout size as tuple
def get_size(layer: Layer | Layout):
return layer.size.width, layer.size.height
# Get layer offset as tuple
def get_offset(layer: Layer, image: _Image):
x, y = layer.offset.x, layer.offset.y
# Compute offset from origin - if an origin is given, compute the offset
# relative to the image and layer size to allow for flexible positioning
if layer.origin != "start top":
origin = re.split(r"\s+", layer.origin)
# Get layer size
w, h = get_size(layer)
# Compute origin on x-axis
if "start" in origin: pass
elif "end" in origin: x += (image.width - w) - 2 * x
elif "center" in origin: x += (image.width - w) >> 1
# Compute origin on y-axis
if "top" in origin: pass
elif "bottom" in origin: y += (image.height - h) - 2 * y
elif "center" in origin: y += (image.height - h) >> 1
# Return offset
return x, y
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
from __future__ import annotations
# -----------------------------------------------------------------------------
# Functions
# -----------------------------------------------------------------------------
# Filter for coercing everthing that is falsy to an empty string
def x_filter(value: str | None):
return value or ""
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
# -----------------------------------------------------------------------------
# Configuration
# -----------------------------------------------------------------------------
# Definitions
definitions:
# Background image
- &background_image >-
{{ layout.background_image | x }}
# Background color (default: indigo)
- &background_color >-
{%- if layout.background_color -%}
{{ layout.background_color }}
{%- else -%}
{%- set palette = config.theme.palette or {} -%}
{%- if not palette is mapping -%}
{%- set list = palette | selectattr("primary") | list + palette -%}
{%- set palette = list | first -%}
{%- endif -%}
{%- set primary = palette.get("primary", "indigo") -%}
{%- set primary = primary.replace(" ", "-") -%}
{{ {
"red": "#ef5552",
"pink": "#e92063",
"purple": "#ab47bd",
"deep-purple": "#7e56c2",
"indigo": "#4051b5",
"blue": "#2094f3",
"light-blue": "#02a6f2",
"cyan": "#00bdd6",
"teal": "#009485",
"green": "#4cae4f",
"light-green": "#8bc34b",
"lime": "#cbdc38",
"yellow": "#ffec3d",
"amber": "#ffc105",
"orange": "#ffa724",
"deep-orange": "#ff6e42",
"brown": "#795649",
"grey": "#757575",
"blue-grey": "#546d78",
"black": "#000000",
"white": "#ffffff"
}[primary] or "#4051b5" }}
{%- endif -%}
# Text color (default: white)
- &color >-
{%- if layout.color -%}
{{ layout.color }}
{%- else -%}
{%- set palette = config.theme.palette or {} -%}
{%- if not palette is mapping -%}
{%- set list = palette | selectattr("primary") | list + palette -%}
{%- set palette = list | first -%}
{%- endif -%}
{%- set primary = palette.get("primary", "indigo") -%}
{%- set primary = primary.replace(" ", "-") -%}
{{ {
"red": "#ffffff",
"pink": "#ffffff",
"purple": "#ffffff",
"deep-purple": "#ffffff",
"indigo": "#ffffff",
"blue": "#ffffff",
"light-blue": "#ffffff",
"cyan": "#ffffff",
"teal": "#ffffff",
"green": "#ffffff",
"light-green": "#ffffff",
"lime": "#000000",
"yellow": "#000000",
"amber": "#000000",
"orange": "#000000",
"deep-orange": "#ffffff",
"brown": "#ffffff",
"grey": "#ffffff",
"blue-grey": "#ffffff",
"black": "#ffffff",
"white": "#000000"
}[primary] or "#ffffff" }}
{%- endif -%}
# Font family (default: Roboto)
- &font_family >-
{%- if layout.font_family -%}
{{ layout.font_family }}
{%- elif config.theme.font is mapping -%}
{{ config.theme.font.get("text", "Roboto") }}
{%- else -%}
Roboto
{%- endif -%}
# Font variant
- &font_variant >-
{%- if layout.font_variant -%}
{{ layout.font_variant }}
{%- endif -%}
# Site name
- &site_name >-
{{ config.site_name }}
# Page title
- &page_title >-
{%- if layout.title -%}
{{ layout.title }}
{%- else -%}
{{ page.meta.get("title", page.title) }}
{%- endif -%}
# Page title with site name
- &page_title_with_site_name >-
{%- if not page.is_homepage -%}
{{ page.meta.get("title", page.title) }} - {{ config.site_name }}
{%- else -%}
{{ config.site_name }}
{%- endif -%}
# Page description
- &page_description >-
{%- if layout.description -%}
{{ layout.description }}
{%- else -%}
{{ page.meta.get("description", config.site_description) | x }}
{%- endif -%}
# Logo
- &logo >-
{%- if layout.logo -%}
{{ layout.logo }}
{%- elif config.theme.logo -%}
{{ config.docs_dir }}/{{ config.theme.logo }}
{%- endif -%}
# Logo (icon)
- &logo_icon >-
{%- if not layout.logo and config.theme.icon -%}
{{ config.theme.icon.logo | x }}
{%- endif -%}
# Meta tags
tags:
# Open Graph
og:type: website
og:title: *page_title_with_site_name
og:description: *page_description
og:image: "{{ image.url }}"
og:image:type: "{{ image.type }}"
og:image:width: "{{ image.width }}"
og:image:height: "{{ image.height }}"
og:url: "{{ page.canonical_url }}"
# Twitter
twitter:card: summary_large_image
twitter:title: *page_title_with_site_name
twitter:description: *page_description
twitter:image: "{{ image.url }}"
# -----------------------------------------------------------------------------
# Specification
# -----------------------------------------------------------------------------
# Card size and layers
size: { width: 1200, height: 630 }
layers:
# Background
- background:
image: *background_image
color: *background_color
# Logo
- size: { width: 144, height: 144 }
offset: { x: 992, y: 64 }
background:
image: *logo
icon:
value: *logo_icon
color: *color
# Site name
- size: { width: 832, height: 42 }
offset: { x: 64, y: 64 }
typography:
content: *site_name
color: *color
font:
family: *font_family
variant: *font_variant
style: Bold
# Page title
- size: { width: 832, height: 310 }
offset: { x: 62, y: 160 }
typography:
content: *page_title
align: start
color: *color
line:
amount: 3
height: 1.25
font:
family: *font_family
variant: *font_variant
style: Bold
# Page description
- size: { width: 832, height: 64 }
offset: { x: 64, y: 512 }
typography:
content: *page_description
align: start
color: *color
line:
amount: 2
height: 1.5
font:
family: *font_family
variant: *font_variant
style: Regular
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
# -----------------------------------------------------------------------------
# Configuration
# -----------------------------------------------------------------------------
# Definitions
definitions:
# Background image
- &background_image >-
{{ layout.background_image | x }}
# Background color (default: indigo)
- &background_color >-
{%- if layout.background_color -%}
{{ layout.background_color }}
{%- else -%}
{%- set palette = config.theme.palette or {} -%}
{%- if not palette is mapping -%}
{%- set list = palette | selectattr("accent") | list + palette -%}
{%- set palette = list | first -%}
{%- endif -%}
{%- set accent = palette.get("accent", "indigo") -%}
{%- set accent = accent.replace(" ", "-") -%}
{{ {
"red": "#ff1a47",
"pink": "#f50056",
"purple": "#df41fb",
"deep-purple": "#7c4dff",
"indigo": "#526cfe",
"blue": "#4287ff",
"light-blue": "#0091eb",
"cyan": "#00bad6",
"teal": "#00bda4",
"green": "#00c753",
"light-green": "#63de17",
"lime": "#b0eb00",
"yellow": "#ffd500",
"amber": "#ffaa00",
"orange": "#ff9100",
"deep-orange": "#ff6e42"
}[accent] or "#4051b5" }}
{%- endif -%}
# Text color (default: white)
- &color >-
{%- if layout.color -%}
{{ layout.color }}
{%- else -%}
{%- set palette = config.theme.palette or {} -%}
{%- if not palette is mapping -%}
{%- set list = palette | selectattr("accent") | list + palette -%}
{%- set palette = list | first -%}
{%- endif -%}
{%- set accent = palette.get("accent", "indigo") -%}
{%- set accent = accent.replace(" ", "-") -%}
{{ {
"red": "#ffffff",
"pink": "#ffffff",
"purple": "#ffffff",
"deep-purple": "#ffffff",
"indigo": "#ffffff",
"blue": "#ffffff",
"light-blue": "#ffffff",
"cyan": "#ffffff",
"teal": "#ffffff",
"green": "#ffffff",
"light-green": "#ffffff",
"lime": "#000000",
"yellow": "#000000",
"amber": "#000000",
"orange": "#000000",
"deep-orange": "#ffffff"
}[accent] or "#ffffff" }}
{%- endif -%}
# Font family (default: Roboto)
- &font_family >-
{%- if layout.font_family -%}
{{ layout.font_family }}
{%- elif config.theme.font is mapping -%}
{{ config.theme.font.get("text", "Roboto") }}
{%- else -%}
Roboto
{%- endif -%}
# Font variant
- &font_variant >-
{%- if layout.font_variant -%}
{{ layout.font_variant }}
{%- endif -%}
# Site name
- &site_name >-
{{ config.site_name }}
# Page title
- &page_title >-
{%- if layout.title -%}
{{ layout.title }}
{%- else -%}
{{ page.meta.get("title", page.title) }}
{%- endif -%}
# Page title with site name
- &page_title_with_site_name >-
{%- if not page.is_homepage -%}
{{ page.meta.get("title", page.title) }} - {{ config.site_name }}
{%- else -%}
{{ config.site_name }}
{%- endif -%}
# Page description
- &page_description >-
{%- if layout.description -%}
{{ layout.description }}
{%- else -%}
{{ page.meta.get("description", config.site_description) | x }}
{%- endif -%}
# Logo
- &logo >-
{%- if layout.logo -%}
{{ layout.logo }}
{%- elif config.theme.logo -%}
{{ config.docs_dir }}/{{ config.theme.logo }}
{%- endif -%}
# Logo (icon)
- &logo_icon >-
{%- if not layout.logo and config.theme.icon -%}
{{ config.theme.icon.logo | x }}
{%- endif -%}
# Meta tags
tags:
# Open Graph
og:type: website
og:title: *page_title_with_site_name
og:description: *page_description
og:image: "{{ image.url }}"
og:image:type: "{{ image.type }}"
og:image:width: "{{ image.width }}"
og:image:height: "{{ image.height }}"
og:url: "{{ page.canonical_url }}"
# Twitter
twitter:card: summary_large_image
twitter:title: *page_title_with_site_name
twitter:description: *page_description
twitter:image: "{{ image.url }}"
# -----------------------------------------------------------------------------
# Specification
# -----------------------------------------------------------------------------
# Card size and layers
size: { width: 1200, height: 630 }
layers:
# Background
- background:
image: *background_image
color: *background_color
# Logo
- size: { width: 144, height: 144 }
offset: { x: 992, y: 64 }
background:
image: *logo
icon:
value: *logo_icon
color: *color
# Site name
- size: { width: 832, height: 42 }
offset: { x: 64, y: 64 }
typography:
content: *site_name
color: *color
font:
family: *font_family
variant: *font_variant
style: Bold
# Page title
- size: { width: 832, height: 310 }
offset: { x: 62, y: 160 }
typography:
content: *page_title
align: start
color: *color
line:
amount: 3
height: 1.25
font:
family: *font_family
variant: *font_variant
style: Bold
# Page description
- size: { width: 832, height: 64 }
offset: { x: 64, y: 512 }
typography:
content: *page_description
align: start
color: *color
line:
amount: 2
height: 1.5
font:
family: *font_family
variant: *font_variant
style: Regular
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
# -----------------------------------------------------------------------------
# Configuration
# -----------------------------------------------------------------------------
# Definitions
definitions:
# Background image
- &background_image >-
{{ layout.background_image | x }}
# Background color (default: white)
- &background_color >-
{%- if layout.background_color -%}
{{ layout.background_color }}
{%- else -%}
{%- set palette = config.theme.palette or {} -%}
{%- if not palette is mapping -%}
{%- set list = palette | selectattr("primary") | list + palette -%}
{%- set palette = list | first -%}
{%- endif -%}
{%- set primary = palette.get("primary", "indigo") -%}
{%- set primary = primary.replace(" ", "-") -%}
{{ {
"red": "#ffffff",
"pink": "#ffffff",
"purple": "#ffffff",
"deep-purple": "#ffffff",
"indigo": "#ffffff",
"blue": "#ffffff",
"light-blue": "#ffffff",
"cyan": "#ffffff",
"teal": "#ffffff",
"green": "#ffffff",
"light-green": "#ffffff",
"lime": "#000000",
"yellow": "#000000",
"amber": "#000000",
"orange": "#000000",
"deep-orange": "#ffffff",
"brown": "#ffffff",
"grey": "#ffffff",
"blue-grey": "#ffffff",
"black": "#ffffff",
"white": "#000000"
}[primary] or "#ffffff" }}
{%- endif -%}
# Text color (default: indigo)
- &color >-
{%- if layout.color -%}
{{ layout.color }}
{%- else -%}
{%- set palette = config.theme.palette or {} -%}
{%- if not palette is mapping -%}
{%- set list = palette | selectattr("primary") | list + palette -%}
{%- set palette = list | first -%}
{%- endif -%}
{%- set primary = palette.get("primary", "indigo") -%}
{%- set primary = primary.replace(" ", "-") -%}
{{ {
"red": "#ef5552",
"pink": "#e92063",
"purple": "#ab47bd",
"deep-purple": "#7e56c2",
"indigo": "#4051b5",
"blue": "#2094f3",
"light-blue": "#02a6f2",
"cyan": "#00bdd6",
"teal": "#009485",
"green": "#4cae4f",
"light-green": "#8bc34b",
"lime": "#cbdc38",
"yellow": "#ffec3d",
"amber": "#ffc105",
"orange": "#ffa724",
"deep-orange": "#ff6e42",
"brown": "#795649",
"grey": "#757575",
"blue-grey": "#546d78",
"black": "#000000",
"white": "#ffffff"
}[primary] or "#4051b5" }}
{%- endif -%}
# Font family (default: Roboto)
- &font_family >-
{%- if layout.font_family -%}
{{ layout.font_family }}
{%- elif config.theme.font is mapping -%}
{{ config.theme.font.get("text", "Roboto") }}
{%- else -%}
Roboto
{%- endif -%}
# Font variant
- &font_variant >-
{%- if layout.font_variant -%}
{{ layout.font_variant }}
{%- endif -%}
# Site name
- &site_name >-
{{ config.site_name }}
# Page title
- &page_title >-
{%- if layout.title -%}
{{ layout.title }}
{%- else -%}
{{ page.meta.get("title", page.title) }}
{%- endif -%}
# Page title with site name
- &page_title_with_site_name >-
{%- if not page.is_homepage -%}
{{ page.meta.get("title", page.title) }} - {{ config.site_name }}
{%- else -%}
{{ config.site_name }}
{%- endif -%}
# Page description
- &page_description >-
{%- if layout.description -%}
{{ layout.description }}
{%- else -%}
{{ page.meta.get("description", config.site_description) | x }}
{%- endif -%}
# Logo
- &logo >-
{%- if layout.logo -%}
{{ layout.logo }}
{%- elif config.theme.logo -%}
{{ config.docs_dir }}/{{ config.theme.logo }}
{%- endif -%}
# Logo (icon)
- &logo_icon >-
{%- if not layout.logo and config.theme.icon -%}
{{ config.theme.icon.logo | x }}
{%- endif -%}
# Meta tags
tags:
# Open Graph
og:type: website
og:title: *page_title_with_site_name
og:description: *page_description
og:image: "{{ image.url }}"
og:image:type: "{{ image.type }}"
og:image:width: "{{ image.width }}"
og:image:height: "{{ image.height }}"
og:url: "{{ page.canonical_url }}"
# Twitter
twitter:card: summary_large_image
twitter:title: *page_title_with_site_name
twitter:description: *page_description
twitter:image: "{{ image.url }}"
# -----------------------------------------------------------------------------
# Specification
# -----------------------------------------------------------------------------
# Card size and layers
size: { width: 1200, height: 630 }
layers:
# Background
- background:
image: *background_image
color: *background_color
# Logo
- size: { width: 144, height: 144 }
offset: { x: 992, y: 64 }
background:
image: *logo
icon:
value: *logo_icon
color: *color
# Site name
- size: { width: 832, height: 42 }
offset: { x: 64, y: 64 }
typography:
content: *site_name
color: *color
font:
family: *font_family
variant: *font_variant
style: Bold
# Page title
- size: { width: 832, height: 310 }
offset: { x: 62, y: 160 }
typography:
content: *page_title
align: start
color: *color
line:
amount: 3
height: 1.25
font:
family: *font_family
variant: *font_variant
style: Bold
# Page description
- size: { width: 832, height: 64 }
offset: { x: 64, y: 512 }
typography:
content: *page_description
align: start
color: *color
line:
amount: 2
height: 1.5
font:
family: *font_family
variant: *font_variant
style: Regular
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
# -----------------------------------------------------------------------------
# Configuration
# -----------------------------------------------------------------------------
# Definitions
definitions:
# Background image
- &background_image >-
{{ layout.background_image }}
# Page title with site name
- &page_title_with_site_name >-
{%- if not page.is_homepage -%}
{{ page.meta.get("title", page.title) }} - {{ config.site_name }}
{%- else -%}
{{ page.meta.get("title", page.title) }}
{%- endif -%}
# Page description
- &page_description >-
{%- if layout.description -%}
{{ layout.description }}
{%- else -%}
{{ page.meta.get("description", config.site_description) | x }}
{%- endif -%}
# Meta tags
tags:
# Open Graph
og:type: website
og:title: *page_title_with_site_name
og:description: *page_description
og:image: "{{ image.url }}"
og:image:type: "{{ image.type }}"
og:image:width: "{{ image.width }}"
og:image:height: "{{ image.height }}"
og:url: "{{ page.canonical_url }}"
# Twitter
twitter:card: summary_large_image
twitter:title: *page_title_with_site_name
twitter:description: *page_description
twitter:image: "{{ image.url }}"
# -----------------------------------------------------------------------------
# Specification
# -----------------------------------------------------------------------------
# Card size and layers
size: { width: 1200, height: 630 }
layers:
# Background
- background:
image: *background_image
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
# -----------------------------------------------------------------------------
# Configuration
# -----------------------------------------------------------------------------
# Definitions
definitions:
# Background image
- &background_image >-
{{ layout.background_image | x }}
# Background color (default: indigo)
- &background_color >-
{%- if layout.background_color -%}
{{ layout.background_color }}
{%- else -%}
{%- set palette = config.theme.palette or {} -%}
{%- if not palette is mapping -%}
{%- set list = palette | selectattr("primary") | list + palette -%}
{%- set palette = list | first -%}
{%- endif -%}
{%- set primary = palette.get("primary", "indigo") -%}
{%- set primary = primary.replace(" ", "-") -%}
{{ {
"red": "#ef5552",
"pink": "#e92063",
"purple": "#ab47bd",
"deep-purple": "#7e56c2",
"indigo": "#4051b5",
"blue": "#2094f3",
"light-blue": "#02a6f2",
"cyan": "#00bdd6",
"teal": "#009485",
"green": "#4cae4f",
"light-green": "#8bc34b",
"lime": "#cbdc38",
"yellow": "#ffec3d",
"amber": "#ffc105",
"orange": "#ffa724",
"deep-orange": "#ff6e42",
"brown": "#795649",
"grey": "#757575",
"blue-grey": "#546d78",
"black": "#000000",
"white": "#ffffff"
}[primary] or "#4051b5" }}
{%- endif -%}
# Text color (default: white)
- &color >-
{%- if layout.color -%}
{{ layout.color }}
{%- else -%}
{%- set palette = config.theme.palette or {} -%}
{%- if not palette is mapping -%}
{%- set list = palette | selectattr("primary") | list + palette -%}
{%- set palette = list | first -%}
{%- endif -%}
{%- set primary = palette.get("primary", "indigo") -%}
{%- set primary = primary.replace(" ", "-") -%}
{{ {
"red": "#ffffff",
"pink": "#ffffff",
"purple": "#ffffff",
"deep-purple": "#ffffff",
"indigo": "#ffffff",
"blue": "#ffffff",
"light-blue": "#ffffff",
"cyan": "#ffffff",
"teal": "#ffffff",
"green": "#ffffff",
"light-green": "#ffffff",
"lime": "#000000",
"yellow": "#000000",
"amber": "#000000",
"orange": "#000000",
"deep-orange": "#ffffff",
"brown": "#ffffff",
"grey": "#ffffff",
"blue-grey": "#ffffff",
"black": "#ffffff",
"white": "#000000"
}[primary] or "#ffffff" }}
{%- endif -%}
# Font family (default: Roboto)
- &font_family >-
{%- if layout.font_family -%}
{{ layout.font_family }}
{%- elif config.theme.font is mapping -%}
{{ config.theme.font.get("text", "Roboto") }}
{%- else -%}
Roboto
{%- endif -%}
# Font variant
- &font_variant >-
{%- if layout.font_variant -%}
{{ layout.font_variant }}
{%- endif -%}
# Site name
- &site_name >-
{{ config.site_name }}
# Page title
- &page_title >-
{%- if layout.title -%}
{{ layout.title }}
{%- else -%}
{{ page.meta.get("title", page.title) }}
{%- endif -%}
# Page title with site name
- &page_title_with_site_name >-
{%- if not page.is_homepage -%}
{{ page.meta.get("title", page.title) }} - {{ config.site_name }}
{%- else -%}
{{ config.site_name }}
{%- endif -%}
# Page description
- &page_description >-
{%- if layout.description -%}
{{ layout.description }}
{%- else -%}
{{ page.meta.get("description", config.site_description) | x }}
{%- endif -%}
# Page icon
- &page_icon >-
{{ page.meta.icon | x }}
# Logo
- &logo >-
{%- if layout.logo -%}
{{ layout.logo }}
{%- elif config.theme.logo -%}
{{ config.docs_dir }}/{{ config.theme.logo }}
{%- endif -%}
# Logo (icon)
- &logo_icon >-
{%- if not layout.logo and config.theme.icon -%}
{{ config.theme.icon.logo | x }}
{%- endif -%}
# Meta tags
tags:
# Open Graph
og:type: website
og:title: *page_title_with_site_name
og:description: *page_description
og:image: "{{ image.url }}"
og:image:type: "{{ image.type }}"
og:image:width: "{{ image.width }}"
og:image:height: "{{ image.height }}"
og:url: "{{ page.canonical_url }}"
# Twitter
twitter:card: summary_large_image
twitter:title: *page_title_with_site_name
twitter:description: *page_description
twitter:image: "{{ image.url }}"
# -----------------------------------------------------------------------------
# Specification
# -----------------------------------------------------------------------------
# Card size and layers
size: { width: 1200, height: 630 }
layers:
# Background
- background:
image: *background_image
color: *background_color
# Page icon
- size: { width: 630, height: 630 }
offset: { x: 800, y: 0 }
icon:
value: *page_icon
color: "#00000033"
# Logo
- size: { width: 64, height: 64 }
offset: { x: 64, y: 64 }
background:
image: *logo
icon:
value: *logo_icon
color: *color
# Site name
- size: { width: 768, height: 42 }
offset: { x: 160, y: 74 }
typography:
content: *site_name
color: *color
font:
family: *font_family
variant: *font_variant
style: Bold
# Page title
- size: { width: 864, height: 256 }
offset: { x: 62, y: 192 }
typography:
content: *page_title
align: start
color: *color
line:
amount: 3
height: 1.25
font:
family: *font_family
variant: *font_variant
style: Bold
# Page description
- size: { width: 864, height: 64 }
offset: { x: 64, y: 512 }
typography:
content: *page_description
align: start
color: *color
line:
amount: 2
height: 1.5
font:
family: *font_family
variant: *font_variant
style: Regular
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
from mkdocs.config.config_options import Type
from mkdocs.config.base import Config
# -----------------------------------------------------------------------------
# Classes
# -----------------------------------------------------------------------------
# Typeset plugin configuration
class TypesetConfig(Config):
enabled = Type(bool, default = True)
# Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>
# 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 NON-INFRINGEMENT. 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.
import re
from mkdocs.plugins import BasePlugin
from .config import TypesetConfig
# -----------------------------------------------------------------------------
# Classes
# -----------------------------------------------------------------------------
# Typeset plugin
class TypesetPlugin(BasePlugin[TypesetConfig]):
# Initialize plugin
def on_config(self, config):
if not self.config.enabled:
return
# Initialize titles
self.title_map: dict[str, str] = {}
# Extract source of page title before it's lost
def on_pre_page(self, page, *, config, files):
if not self.config.enabled:
return
# Check if page title was set in configuration
if page.title:
path = page.file.src_uri
self.title_map[path] = "config"
# Extract typeset content for headlines
def on_page_content(self, html, *, page, config, files):
if not self.config.enabled:
return
# Check if page title was set in metadata
path = page.file.src_uri
if path not in self.title_map:
if "title" in page.meta:
self.title_map[path] = "meta"
# Flatten anchors and map to headlines
anchors = _flatten(page.toc.items)
for (level, id, title) in re.findall(
r"<h(\d)[^>]+id=\"([^\"]+)[^>]*>(.*?)</h\1>",
html, flags = re.I | re.M
):
if id not in anchors:
continue
# If the author uses `data-toc-label` to override a heading (which
# doesn't support adding of HTML tags), we can abort here, since
# the headline will be rendered as-is. It's more or less a hack, so
# we should check if we can improve it in the future.
label = re.escape(anchors[id].title)
if re.search(rf"data-toc-label=['\"]{label}", page.markdown):
continue
# Remove anchor links from headlines – we need to do that, or we
# end up with anchor links inside anchor links, which is invalid
# HTML5. There are two cases we need to account for here:
#
# 1. If toc.anchorlink is enabled, the entire headline is wrapped
# in an anchor link, so we unpack its contents
#
# 2. If toc.permalink is enabled, an anchor link is appended to the
# contents of the headline, so we just remove it
#
# Albeit it doesn't make much sense, both options can be used at
# the same time, so we need to account for both cases. This problem
# was first reported in https://bit.ly/456AjUm
title = re.sub(r"^<a\s+[^>]+>(.*?)</a>", r"\1", title)
title = re.sub(r"<a\s+[^>]+>[^<]+?</a>$", "", title)
# Remove author-provided ids - see https://bit.ly/3ngiZea
title = re.sub(r"id=\"?[^\">]+\"?", "", title)
# Assign headline content to anchor
anchors[id].typeset = { "title": title }
if path not in self.title_map:
# Assign first top-level headline to page
if not hasattr(page, "typeset") and int(level) == 1:
page.typeset = anchors[id].typeset
page.title = re.sub(r"<[^>]+>", "", title)
# -----------------------------------------------------------------------------
# Helper functions
# -----------------------------------------------------------------------------
# Flatten a tree of anchors
def _flatten(items):
anchors = {}
for item in items:
anchors[item.id] = item
# Recursively expand children
if item.children:
anchors.update(_flatten(item.children))
# Return anchors
return anchors

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

"use strict";(()=>{var xe=Object.create;var G=Object.defineProperty,ve=Object.defineProperties,Se=Object.getOwnPropertyDescriptor,Te=Object.getOwnPropertyDescriptors,Qe=Object.getOwnPropertyNames,J=Object.getOwnPropertySymbols,Ee=Object.getPrototypeOf,Z=Object.prototype.hasOwnProperty,be=Object.prototype.propertyIsEnumerable;var K=Math.pow,X=(t,e,r)=>e in t?G(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,_=(t,e)=>{for(var r in e||(e={}))Z.call(e,r)&&X(t,r,e[r]);if(J)for(var r of J(e))be.call(e,r)&&X(t,r,e[r]);return t},B=(t,e)=>ve(t,Te(e));var Le=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var we=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Qe(e))!Z.call(t,i)&&i!==r&&G(t,i,{get:()=>e[i],enumerable:!(n=Se(e,i))||n.enumerable});return t};var Pe=(t,e,r)=>(r=t!=null?xe(Ee(t)):{},we(e||!t||!t.__esModule?G(r,"default",{value:t,enumerable:!0}):r,t));var W=(t,e,r)=>new Promise((n,i)=>{var s=u=>{try{a(r.next(u))}catch(c){i(c)}},o=u=>{try{a(r.throw(u))}catch(c){i(c)}},a=u=>u.done?n(u.value):Promise.resolve(u.value).then(s,o);a((r=r.apply(t,e)).next())});var re=Le((ee,te)=>{/**
* lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9
* Copyright (C) 2020 Oliver Nightingale
* @license MIT
*/(function(){var t=function(e){var r=new t.Builder;return r.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),r.searchPipeline.add(t.stemmer),e.call(r,r),r.build()};t.version="2.3.9";/*!
* lunr.utils
* Copyright (C) 2020 Oliver Nightingale
*/t.utils={},t.utils.warn=(function(e){return function(r){e.console&&console.warn&&console.warn(r)}})(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var r=Object.create(null),n=Object.keys(e),i=0;i<n.length;i++){var s=n[i],o=e[s];if(Array.isArray(o)){r[s]=o.slice();continue}if(typeof o=="string"||typeof o=="number"||typeof o=="boolean"){r[s]=o;continue}throw new TypeError("clone is not deep and does not support nested objects")}return r},t.FieldRef=function(e,r,n){this.docRef=e,this.fieldName=r,this._stringValue=n},t.FieldRef.joiner="/",t.FieldRef.fromString=function(e){var r=e.indexOf(t.FieldRef.joiner);if(r===-1)throw"malformed field ref string";var n=e.slice(0,r),i=e.slice(r+1);return new t.FieldRef(i,n,e)},t.FieldRef.prototype.toString=function(){return this._stringValue==null&&(this._stringValue=this.fieldName+t.FieldRef.joiner+this.docRef),this._stringValue};/*!
* lunr.Set
* Copyright (C) 2020 Oliver Nightingale
*/t.Set=function(e){if(this.elements=Object.create(null),e){this.length=e.length;for(var r=0;r<this.length;r++)this.elements[e[r]]=!0}else this.length=0},t.Set.complete={intersect:function(e){return e},union:function(){return this},contains:function(){return!0}},t.Set.empty={intersect:function(){return this},union:function(e){return e},contains:function(){return!1}},t.Set.prototype.contains=function(e){return!!this.elements[e]},t.Set.prototype.intersect=function(e){var r,n,i,s=[];if(e===t.Set.complete)return this;if(e===t.Set.empty)return e;this.length<e.length?(r=this,n=e):(r=e,n=this),i=Object.keys(r.elements);for(var o=0;o<i.length;o++){var a=i[o];a in n.elements&&s.push(a)}return new t.Set(s)},t.Set.prototype.union=function(e){return e===t.Set.complete?t.Set.complete:e===t.Set.empty?this:new t.Set(Object.keys(this.elements).concat(Object.keys(e.elements)))},t.idf=function(e,r){var n=0;for(var i in e)i!="_index"&&(n+=Object.keys(e[i]).length);var s=(r-n+.5)/(n+.5);return Math.log(1+Math.abs(s))},t.Token=function(e,r){this.str=e||"",this.metadata=r||{}},t.Token.prototype.toString=function(){return this.str},t.Token.prototype.update=function(e){return this.str=e(this.str,this.metadata),this},t.Token.prototype.clone=function(e){return e=e||function(r){return r},new t.Token(e(this.str,this.metadata),this.metadata)};/*!
* lunr.tokenizer
* Copyright (C) 2020 Oliver Nightingale
*/t.tokenizer=function(e,r){if(e==null||e==null)return[];if(Array.isArray(e))return e.map(function(g){return new t.Token(t.utils.asString(g).toLowerCase(),t.utils.clone(r))});for(var n=e.toString().toLowerCase(),i=n.length,s=[],o=0,a=0;o<=i;o++){var u=n.charAt(o),c=o-a;if(u.match(t.tokenizer.separator)||o==i){if(c>0){var f=t.utils.clone(r)||{};f.position=[a,c],f.index=s.length,s.push(new t.Token(n.slice(a,o),f))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;/*!
* lunr.Pipeline
* Copyright (C) 2020 Oliver Nightingale
*/t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,r){r in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+r),e.label=r,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var r=e.label&&e.label in this.registeredFunctions;r||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index.
`,e)},t.Pipeline.load=function(e){var r=new t.Pipeline;return e.forEach(function(n){var i=t.Pipeline.registeredFunctions[n];if(i)r.add(i);else throw new Error("Cannot load unregistered function: "+n)}),r},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(r){t.Pipeline.warnIfFunctionNotRegistered(r),this._stack.push(r)},this)},t.Pipeline.prototype.after=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");n=n+1,this._stack.splice(n,0,r)},t.Pipeline.prototype.before=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");this._stack.splice(n,0,r)},t.Pipeline.prototype.remove=function(e){var r=this._stack.indexOf(e);r!=-1&&this._stack.splice(r,1)},t.Pipeline.prototype.run=function(e){for(var r=this._stack.length,n=0;n<r;n++){for(var i=this._stack[n],s=[],o=0;o<e.length;o++){var a=i(e[o],o,e);if(!(a==null||a===""))if(Array.isArray(a))for(var u=0;u<a.length;u++)s.push(a[u]);else s.push(a)}e=s}return e},t.Pipeline.prototype.runString=function(e,r){var n=new t.Token(e,r);return this.run([n]).map(function(i){return i.toString()})},t.Pipeline.prototype.reset=function(){this._stack=[]},t.Pipeline.prototype.toJSON=function(){return this._stack.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})};/*!
* lunr.Vector
* Copyright (C) 2020 Oliver Nightingale
*/t.Vector=function(e){this._magnitude=0,this.elements=e||[]},t.Vector.prototype.positionForIndex=function(e){if(this.elements.length==0)return 0;for(var r=0,n=this.elements.length/2,i=n-r,s=Math.floor(i/2),o=this.elements[s*2];i>1&&(o<e&&(r=s),o>e&&(n=s),o!=e);)i=n-r,s=r+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(o<e)return(s+1)*2},t.Vector.prototype.insert=function(e,r){this.upsert(e,r,function(){throw"duplicate index"})},t.Vector.prototype.upsert=function(e,r,n){this._magnitude=0;var i=this.positionForIndex(e);this.elements[i]==e?this.elements[i+1]=n(this.elements[i+1],r):this.elements.splice(i,0,e,r)},t.Vector.prototype.magnitude=function(){if(this._magnitude)return this._magnitude;for(var e=0,r=this.elements.length,n=1;n<r;n+=2){var i=this.elements[n];e+=i*i}return this._magnitude=Math.sqrt(e)},t.Vector.prototype.dot=function(e){for(var r=0,n=this.elements,i=e.elements,s=n.length,o=i.length,a=0,u=0,c=0,f=0;c<s&&f<o;)a=n[c],u=i[f],a<u?c+=2:a>u?f+=2:a==u&&(r+=n[c+1]*i[f+1],c+=2,f+=2);return r},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),r=1,n=0;r<this.elements.length;r+=2,n++)e[n]=this.elements[r];return e},t.Vector.prototype.toJSON=function(){return this.elements};/*!
* lunr.stemmer
* Copyright (C) 2020 Oliver Nightingale
* Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt
*/t.stemmer=(function(){var e={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},r={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""},n="[^aeiou]",i="[aeiouy]",s=n+"[^aeiouy]*",o=i+"[aeiou]*",a="^("+s+")?"+o+s,u="^("+s+")?"+o+s+"("+o+")?$",c="^("+s+")?"+o+s+o+s,f="^("+s+")?"+i,g=new RegExp(a),l=new RegExp(c),m=new RegExp(u),x=new RegExp(f),v=/^(.+?)(ss|i)es$/,d=/^(.+?)([^s])s$/,y=/^(.+?)eed$/,b=/^(.+?)(ed|ing)$/,E=/.$/,w=/(at|bl|iz)$/,R=new RegExp("([^aeiouylsz])\\1$"),j=new RegExp("^"+s+i+"[^aeiouwxy]$"),C=/^(.+?[^aeiou])y$/,D=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,N=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,M=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,V=/^(.+?)(s|t)(ion)$/,P=/^(.+?)e$/,z=/ll$/,$=new RegExp("^"+s+i+"[^aeiouwxy]$"),A=function(h){var S,k,L,p,T,O,F;if(h.length<3)return h;if(L=h.substr(0,1),L=="y"&&(h=L.toUpperCase()+h.substr(1)),p=v,T=d,p.test(h)?h=h.replace(p,"$1$2"):T.test(h)&&(h=h.replace(T,"$1$2")),p=y,T=b,p.test(h)){var Q=p.exec(h);p=g,p.test(Q[1])&&(p=E,h=h.replace(p,""))}else if(T.test(h)){var Q=T.exec(h);S=Q[1],T=x,T.test(S)&&(h=S,T=w,O=R,F=j,T.test(h)?h=h+"e":O.test(h)?(p=E,h=h.replace(p,"")):F.test(h)&&(h=h+"e"))}if(p=C,p.test(h)){var Q=p.exec(h);S=Q[1],h=S+"i"}if(p=D,p.test(h)){var Q=p.exec(h);S=Q[1],k=Q[2],p=g,p.test(S)&&(h=S+e[k])}if(p=N,p.test(h)){var Q=p.exec(h);S=Q[1],k=Q[2],p=g,p.test(S)&&(h=S+r[k])}if(p=M,T=V,p.test(h)){var Q=p.exec(h);S=Q[1],p=l,p.test(S)&&(h=S)}else if(T.test(h)){var Q=T.exec(h);S=Q[1]+Q[2],T=l,T.test(S)&&(h=S)}if(p=P,p.test(h)){var Q=p.exec(h);S=Q[1],p=l,T=m,O=$,(p.test(S)||T.test(S)&&!O.test(S))&&(h=S)}return p=z,T=l,p.test(h)&&T.test(h)&&(p=E,h=h.replace(p,"")),L=="y"&&(h=L.toLowerCase()+h.substr(1)),h};return function(I){return I.update(A)}})(),t.Pipeline.registerFunction(t.stemmer,"stemmer");/*!
* lunr.stopWordFilter
* Copyright (C) 2020 Oliver Nightingale
*/t.generateStopWordFilter=function(e){var r=e.reduce(function(n,i){return n[i]=i,n},{});return function(n){if(n&&r[n.toString()]!==n.toString())return n}},t.stopWordFilter=t.generateStopWordFilter(["a","able","about","across","after","all","almost","also","am","among","an","and","any","are","as","at","be","because","been","but","by","can","cannot","could","dear","did","do","does","either","else","ever","every","for","from","get","got","had","has","have","he","her","hers","him","his","how","however","i","if","in","into","is","it","its","just","least","let","like","likely","may","me","might","most","must","my","neither","no","nor","not","of","off","often","on","only","or","other","our","own","rather","said","say","says","she","should","since","so","some","than","that","the","their","them","then","there","these","they","this","tis","to","too","twas","us","wants","was","we","were","what","when","where","which","while","who","whom","why","will","with","would","yet","you","your"]),t.Pipeline.registerFunction(t.stopWordFilter,"stopWordFilter");/*!
* lunr.trimmer
* Copyright (C) 2020 Oliver Nightingale
*/t.trimmer=function(e){return e.update(function(r){return r.replace(/^\W+/,"").replace(/\W+$/,"")})},t.Pipeline.registerFunction(t.trimmer,"trimmer");/*!
* lunr.TokenSet
* Copyright (C) 2020 Oliver Nightingale
*/t.TokenSet=function(){this.final=!1,this.edges={},this.id=t.TokenSet._nextId,t.TokenSet._nextId+=1},t.TokenSet._nextId=1,t.TokenSet.fromArray=function(e){for(var r=new t.TokenSet.Builder,n=0,i=e.length;n<i;n++)r.insert(e[n]);return r.finish(),r.root},t.TokenSet.fromClause=function(e){return"editDistance"in e?t.TokenSet.fromFuzzyString(e.term,e.editDistance):t.TokenSet.fromString(e.term)},t.TokenSet.fromFuzzyString=function(e,r){for(var n=new t.TokenSet,i=[{node:n,editsRemaining:r,str:e}];i.length;){var s=i.pop();if(s.str.length>0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}if(s.str.length==0&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var c=s.node.edges["*"];else{var c=new t.TokenSet;s.node.edges["*"]=c}s.str.length==1&&(c.final=!0),i.push({node:c,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var f=s.str.charAt(0),g=s.str.charAt(1),l;g in s.node.edges?l=s.node.edges[g]:(l=new t.TokenSet,s.node.edges[g]=l),s.str.length==1&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:f+s.str.slice(2)})}}}return n},t.TokenSet.fromString=function(e){for(var r=new t.TokenSet,n=r,i=0,s=e.length;i<s;i++){var o=e[i],a=i==s-1;if(o=="*")r.edges[o]=r,r.final=a;else{var u=new t.TokenSet;u.final=a,r.edges[o]=u,r=u}}return n},t.TokenSet.prototype.toArray=function(){for(var e=[],r=[{prefix:"",node:this}];r.length;){var n=r.pop(),i=Object.keys(n.node.edges),s=i.length;n.node.final&&(n.prefix.charAt(0),e.push(n.prefix));for(var o=0;o<s;o++){var a=i[o];r.push({prefix:n.prefix.concat(a),node:n.node.edges[a]})}}return e},t.TokenSet.prototype.toString=function(){if(this._str)return this._str;for(var e=this.final?"1":"0",r=Object.keys(this.edges).sort(),n=r.length,i=0;i<n;i++){var s=r[i],o=this.edges[s];e=e+s+o.id}return e},t.TokenSet.prototype.intersect=function(e){for(var r=new t.TokenSet,n=void 0,i=[{qNode:e,output:r,node:this}];i.length;){n=i.pop();for(var s=Object.keys(n.qNode.edges),o=s.length,a=Object.keys(n.node.edges),u=a.length,c=0;c<o;c++)for(var f=s[c],g=0;g<u;g++){var l=a[g];if(l==f||f=="*"){var m=n.node.edges[l],x=n.qNode.edges[f],v=m.final&&x.final,d=void 0;l in n.output.edges?(d=n.output.edges[l],d.final=d.final||v):(d=new t.TokenSet,d.final=v,n.output.edges[l]=d),i.push({qNode:x,output:d,node:m})}}}return r},t.TokenSet.Builder=function(){this.previousWord="",this.root=new t.TokenSet,this.uncheckedNodes=[],this.minimizedNodes={}},t.TokenSet.Builder.prototype.insert=function(e){var r,n=0;if(e<this.previousWord)throw new Error("Out of order word insertion");for(var i=0;i<e.length&&i<this.previousWord.length&&e[i]==this.previousWord[i];i++)n++;this.minimize(n),this.uncheckedNodes.length==0?r=this.root:r=this.uncheckedNodes[this.uncheckedNodes.length-1].child;for(var i=n;i<e.length;i++){var s=new t.TokenSet,o=e[i];r.edges[o]=s,this.uncheckedNodes.push({parent:r,char:o,child:s}),r=s}r.final=!0,this.previousWord=e},t.TokenSet.Builder.prototype.finish=function(){this.minimize(0)},t.TokenSet.Builder.prototype.minimize=function(e){for(var r=this.uncheckedNodes.length-1;r>=e;r--){var n=this.uncheckedNodes[r],i=n.child.toString();i in this.minimizedNodes?n.parent.edges[n.char]=this.minimizedNodes[i]:(n.child._str=i,this.minimizedNodes[i]=n.child),this.uncheckedNodes.pop()}};/*!
* lunr.Index
* Copyright (C) 2020 Oliver Nightingale
*/t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(r){var n=new t.QueryParser(e,r);n.parse()})},t.Index.prototype.query=function(e){for(var r=new t.Query(this.fields),n=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),u=0;u<this.fields.length;u++)i[this.fields[u]]=new t.Vector;e.call(r,r);for(var u=0;u<r.clauses.length;u++){var c=r.clauses[u],f=null,g=t.Set.empty;c.usePipeline?f=this.pipeline.runString(c.term,{fields:c.fields}):f=[c.term];for(var l=0;l<f.length;l++){var m=f[l];c.term=m;var x=t.TokenSet.fromClause(c),v=this.tokenSet.intersect(x).toArray();if(v.length===0&&c.presence===t.Query.presence.REQUIRED){for(var d=0;d<c.fields.length;d++){var y=c.fields[d];o[y]=t.Set.empty}break}for(var b=0;b<v.length;b++)for(var E=v[b],w=this.invertedIndex[E],R=w._index,d=0;d<c.fields.length;d++){var y=c.fields[d],j=w[y],C=Object.keys(j),D=E+"/"+y,N=new t.Set(C);if(c.presence==t.Query.presence.REQUIRED&&(g=g.union(N),o[y]===void 0&&(o[y]=t.Set.complete)),c.presence==t.Query.presence.PROHIBITED){a[y]===void 0&&(a[y]=t.Set.empty),a[y]=a[y].union(N);continue}if(i[y].upsert(R,c.boost,function(ye,me){return ye+me}),!s[D]){for(var M=0;M<C.length;M++){var V=C[M],P=new t.FieldRef(V,y),z=j[V],$;($=n[P])===void 0?n[P]=new t.MatchData(E,y,z):$.add(E,y,z)}s[D]=!0}}}if(c.presence===t.Query.presence.REQUIRED)for(var d=0;d<c.fields.length;d++){var y=c.fields[d];o[y]=o[y].intersect(g)}}for(var A=t.Set.complete,I=t.Set.empty,u=0;u<this.fields.length;u++){var y=this.fields[u];o[y]&&(A=A.intersect(o[y])),a[y]&&(I=I.union(a[y]))}var h=Object.keys(n),S=[],k=Object.create(null);if(r.isNegated()){h=Object.keys(this.fieldVectors);for(var u=0;u<h.length;u++){var P=h[u],L=t.FieldRef.fromString(P);n[P]=new t.MatchData}}for(var u=0;u<h.length;u++){var L=t.FieldRef.fromString(h[u]),p=L.docRef;if(A.contains(p)&&!I.contains(p)){var T=this.fieldVectors[L],O=i[L.fieldName].similarity(T),F;if((F=k[p])!==void 0)F.score+=O,F.matchData.combine(n[L]);else{var Q={ref:p,score:O,matchData:n[L]};k[p]=Q,S.push(Q)}}}return S.sort(function(pe,ge){return ge.score-pe.score})},t.Index.prototype.toJSON=function(){var e=Object.keys(this.invertedIndex).sort().map(function(n){return[n,this.invertedIndex[n]]},this),r=Object.keys(this.fieldVectors).map(function(n){return[n,this.fieldVectors[n].toJSON()]},this);return{version:t.version,fields:this.fields,fieldVectors:r,invertedIndex:e,pipeline:this.pipeline.toJSON()}},t.Index.load=function(e){var r={},n={},i=e.fieldVectors,s=Object.create(null),o=e.invertedIndex,a=new t.TokenSet.Builder,u=t.Pipeline.load(e.pipeline);e.version!=t.version&&t.utils.warn("Version mismatch when loading serialised index. Current version of lunr '"+t.version+"' does not match serialized index '"+e.version+"'");for(var c=0;c<i.length;c++){var f=i[c],g=f[0],l=f[1];n[g]=new t.Vector(l)}for(var c=0;c<o.length;c++){var f=o[c],m=f[0],x=f[1];a.insert(m),s[m]=x}return a.finish(),r.fields=e.fields,r.fieldVectors=n,r.invertedIndex=s,r.tokenSet=a.root,r.pipeline=u,new t.Index(r)};/*!
* lunr.Builder
* Copyright (C) 2020 Oliver Nightingale
*/t.Builder=function(){this._ref="id",this._fields=Object.create(null),this._documents=Object.create(null),this.invertedIndex=Object.create(null),this.fieldTermFrequencies={},this.fieldLengths={},this.tokenizer=t.tokenizer,this.pipeline=new t.Pipeline,this.searchPipeline=new t.Pipeline,this.documentCount=0,this._b=.75,this._k1=1.2,this.termIndex=0,this.metadataWhitelist=[]},t.Builder.prototype.ref=function(e){this._ref=e},t.Builder.prototype.field=function(e,r){if(/\//.test(e))throw new RangeError("Field '"+e+"' contains illegal character '/'");this._fields[e]=r||{}},t.Builder.prototype.b=function(e){e<0?this._b=0:e>1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,r){var n=e[this._ref],i=Object.keys(this._fields);this._documents[n]=r||{},this.documentCount+=1;for(var s=0;s<i.length;s++){var o=i[s],a=this._fields[o].extractor,u=a?a(e):e[o],c=this.tokenizer(u,{fields:[o]}),f=this.pipeline.run(c),g=new t.FieldRef(n,o),l=Object.create(null);this.fieldTermFrequencies[g]=l,this.fieldLengths[g]=0,this.fieldLengths[g]+=f.length;for(var m=0;m<f.length;m++){var x=f[m];if(l[x]==null&&(l[x]=0),l[x]+=1,this.invertedIndex[x]==null){var v=Object.create(null);v._index=this.termIndex,this.termIndex+=1;for(var d=0;d<i.length;d++)v[i[d]]=Object.create(null);this.invertedIndex[x]=v}this.invertedIndex[x][o][n]==null&&(this.invertedIndex[x][o][n]=Object.create(null));for(var y=0;y<this.metadataWhitelist.length;y++){var b=this.metadataWhitelist[y],E=x.metadata[b];this.invertedIndex[x][o][n][b]==null&&(this.invertedIndex[x][o][n][b]=[]),this.invertedIndex[x][o][n][b].push(E)}}}},t.Builder.prototype.calculateAverageFieldLengths=function(){for(var e=Object.keys(this.fieldLengths),r=e.length,n={},i={},s=0;s<r;s++){var o=t.FieldRef.fromString(e[s]),a=o.fieldName;i[a]||(i[a]=0),i[a]+=1,n[a]||(n[a]=0),n[a]+=this.fieldLengths[o]}for(var u=Object.keys(this._fields),s=0;s<u.length;s++){var c=u[s];n[c]=n[c]/i[c]}this.averageFieldLength=n},t.Builder.prototype.createFieldVectors=function(){for(var e={},r=Object.keys(this.fieldTermFrequencies),n=r.length,i=Object.create(null),s=0;s<n;s++){for(var o=t.FieldRef.fromString(r[s]),a=o.fieldName,u=this.fieldLengths[o],c=new t.Vector,f=this.fieldTermFrequencies[o],g=Object.keys(f),l=g.length,m=this._fields[a].boost||1,x=this._documents[o.docRef].boost||1,v=0;v<l;v++){var d=g[v],y=f[d],b=this.invertedIndex[d]._index,E,w,R;i[d]===void 0?(E=t.idf(this.invertedIndex[d],this.documentCount),i[d]=E):E=i[d],w=E*((this._k1+1)*y)/(this._k1*(1-this._b+this._b*(u/this.averageFieldLength[a]))+y),w*=m,w*=x,R=Math.round(w*1e3)/1e3,c.insert(b,R)}e[o]=c}this.fieldVectors=e},t.Builder.prototype.createTokenSet=function(){this.tokenSet=t.TokenSet.fromArray(Object.keys(this.invertedIndex).sort())},t.Builder.prototype.build=function(){return this.calculateAverageFieldLengths(),this.createFieldVectors(),this.createTokenSet(),new t.Index({invertedIndex:this.invertedIndex,fieldVectors:this.fieldVectors,tokenSet:this.tokenSet,fields:Object.keys(this._fields),pipeline:this.searchPipeline})},t.Builder.prototype.use=function(e){var r=Array.prototype.slice.call(arguments,1);r.unshift(this),e.apply(this,r)},t.MatchData=function(e,r,n){for(var i=Object.create(null),s=Object.keys(n||{}),o=0;o<s.length;o++){var a=s[o];i[a]=n[a].slice()}this.metadata=Object.create(null),e!==void 0&&(this.metadata[e]=Object.create(null),this.metadata[e][r]=i)},t.MatchData.prototype.combine=function(e){for(var r=Object.keys(e.metadata),n=0;n<r.length;n++){var i=r[n],s=Object.keys(e.metadata[i]);this.metadata[i]==null&&(this.metadata[i]=Object.create(null));for(var o=0;o<s.length;o++){var a=s[o],u=Object.keys(e.metadata[i][a]);this.metadata[i][a]==null&&(this.metadata[i][a]=Object.create(null));for(var c=0;c<u.length;c++){var f=u[c];this.metadata[i][a][f]==null?this.metadata[i][a][f]=e.metadata[i][a][f]:this.metadata[i][a][f]=this.metadata[i][a][f].concat(e.metadata[i][a][f])}}}},t.MatchData.prototype.add=function(e,r,n){if(!(e in this.metadata)){this.metadata[e]=Object.create(null),this.metadata[e][r]=n;return}if(!(r in this.metadata[e])){this.metadata[e][r]=n;return}for(var i=Object.keys(n),s=0;s<i.length;s++){var o=i[s];o in this.metadata[e][r]?this.metadata[e][r][o]=this.metadata[e][r][o].concat(n[o]):this.metadata[e][r][o]=n[o]}},t.Query=function(e){this.clauses=[],this.allFields=e},t.Query.wildcard=new String("*"),t.Query.wildcard.NONE=0,t.Query.wildcard.LEADING=1,t.Query.wildcard.TRAILING=2,t.Query.presence={OPTIONAL:1,REQUIRED:2,PROHIBITED:3},t.Query.prototype.clause=function(e){return"fields"in e||(e.fields=this.allFields),"boost"in e||(e.boost=1),"usePipeline"in e||(e.usePipeline=!0),"wildcard"in e||(e.wildcard=t.Query.wildcard.NONE),e.wildcard&t.Query.wildcard.LEADING&&e.term.charAt(0)!=t.Query.wildcard&&(e.term="*"+e.term),e.wildcard&t.Query.wildcard.TRAILING&&e.term.slice(-1)!=t.Query.wildcard&&(e.term=""+e.term+"*"),"presence"in e||(e.presence=t.Query.presence.OPTIONAL),this.clauses.push(e),this},t.Query.prototype.isNegated=function(){for(var e=0;e<this.clauses.length;e++)if(this.clauses[e].presence!=t.Query.presence.PROHIBITED)return!1;return!0},t.Query.prototype.term=function(e,r){if(Array.isArray(e))return e.forEach(function(i){this.term(i,t.utils.clone(r))},this),this;var n=r||{};return n.term=e.toString(),this.clause(n),this},t.QueryParseError=function(e,r,n){this.name="QueryParseError",this.message=e,this.start=r,this.end=n},t.QueryParseError.prototype=new Error,t.QueryLexer=function(e){this.lexemes=[],this.str=e,this.length=e.length,this.pos=0,this.start=0,this.escapeCharPositions=[]},t.QueryLexer.prototype.run=function(){for(var e=t.QueryLexer.lexText;e;)e=e(this)},t.QueryLexer.prototype.sliceString=function(){for(var e=[],r=this.start,n=this.pos,i=0;i<this.escapeCharPositions.length;i++)n=this.escapeCharPositions[i],e.push(this.str.slice(r,n)),r=n+1;return e.push(this.str.slice(r,this.pos)),this.escapeCharPositions.length=0,e.join("")},t.QueryLexer.prototype.emit=function(e){this.lexemes.push({type:e,str:this.sliceString(),start:this.start,end:this.pos}),this.start=this.pos},t.QueryLexer.prototype.escapeCharacter=function(){this.escapeCharPositions.push(this.pos-1),this.pos+=1},t.QueryLexer.prototype.next=function(){if(this.pos>=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,r;do e=this.next(),r=e.charCodeAt(0);while(r>47&&r<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos<this.length},t.QueryLexer.EOS="EOS",t.QueryLexer.FIELD="FIELD",t.QueryLexer.TERM="TERM",t.QueryLexer.EDIT_DISTANCE="EDIT_DISTANCE",t.QueryLexer.BOOST="BOOST",t.QueryLexer.PRESENCE="PRESENCE",t.QueryLexer.lexField=function(e){return e.backup(),e.emit(t.QueryLexer.FIELD),e.ignore(),t.QueryLexer.lexText},t.QueryLexer.lexTerm=function(e){if(e.width()>1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var r=e.next();if(r==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(r.charCodeAt(0)==92){e.escapeCharacter();continue}if(r==":")return t.QueryLexer.lexField;if(r=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(r=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(r=="+"&&e.width()===1||r=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(r.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,r){this.lexer=new t.QueryLexer(e),this.query=r,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var r=e.peekLexeme();if(r!=null)switch(r.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expected either a field or a term, found "+r.type;throw r.str.length>=1&&(n+=" with value '"+r.str+"'"),new t.QueryParseError(n,r.start,r.end)}},t.QueryParser.parsePresence=function(e){var r=e.consumeLexeme();if(r!=null){switch(r.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var n="unrecognised presence operator'"+r.str+"'";throw new t.QueryParseError(n,r.start,r.end)}var i=e.peekLexeme();if(i==null){var n="expecting term or field, found nothing";throw new t.QueryParseError(n,r.start,r.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(n,i.start,i.end)}}},t.QueryParser.parseField=function(e){var r=e.consumeLexeme();if(r!=null){if(e.query.allFields.indexOf(r.str)==-1){var n=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+r.str+"', possible fields: "+n;throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.fields=[r.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,r.start,r.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var r=e.consumeLexeme();if(r!=null){e.currentClause.term=r.str.toLowerCase(),r.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var n=e.peekLexeme();if(n==null){e.nextClause();return}switch(n.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+n.type+"'";throw new t.QueryParseError(i,n.start,n.end)}}},t.QueryParser.parseEditDistance=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="edit distance must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.editDistance=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="boost must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.boost=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},(function(e,r){typeof define=="function"&&define.amd?define(r):typeof ee=="object"?te.exports=r():e.lunr=r()})(this,function(){return t})})()});var Y=Pe(re());function ne(t,e=document){let r=ke(t,e);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${t}" to be present`);return r}function ke(t,e=document){return e.querySelector(t)||void 0}Object.entries||(Object.entries=function(t){let e=[];for(let r of Object.keys(t))e.push([r,t[r]]);return e});Object.values||(Object.values=function(t){let e=[];for(let r of Object.keys(t))e.push(t[r]);return e});typeof Element!="undefined"&&(Element.prototype.scrollTo||(Element.prototype.scrollTo=function(t,e){typeof t=="object"?(this.scrollLeft=t.left,this.scrollTop=t.top):(this.scrollLeft=t,this.scrollTop=e)}),Element.prototype.replaceWith||(Element.prototype.replaceWith=function(...t){let e=this.parentNode;if(e){t.length===0&&e.removeChild(this);for(let r=t.length-1;r>=0;r--){let n=t[r];typeof n=="string"?n=document.createTextNode(n):n.parentNode&&n.parentNode.removeChild(n),r?e.insertBefore(this.previousSibling,n):e.replaceChild(n,this)}}}));function ie(t){let e=new Map;for(let r of t){let[n]=r.location.split("#"),i=e.get(n);typeof i=="undefined"?e.set(n,r):(e.set(r.location,r),r.parent=i)}return e}function H(t,e,r){var s;e=new RegExp(e,"g");let n,i=0;do{n=e.exec(t);let o=(s=n==null?void 0:n.index)!=null?s:t.length;if(i<o&&r(i,o),n){let[a]=n;i=n.index+a.length,a.length===0&&(e.lastIndex=n.index+1)}}while(n)}function se(t,e){let r=0,n=0,i=0;for(let s=0;i<t.length;i++)t.charAt(i)==="<"&&i>n?e(r,1,n,n=i):t.charAt(i)===">"&&(t.charAt(n+1)==="/"?--s===0&&e(r++,2,n,i+1):t.charAt(i-1)!=="/"&&s++===0&&e(r,0,n,i+1),n=i+1);i>n&&e(r,1,n,i)}function oe(t,e,r,n=!1){return q([t],e,r,n).pop()}function q(t,e,r,n=!1){let i=[0];for(let s=1;s<e.length;s++){let o=e[s-1],a=e[s],u=o[o.length-1]>>>2&1023,c=a[0]>>>12;i.push(+(u>c)+i[i.length-1])}return t.map((s,o)=>{let a=0,u=new Map;for(let f of r.sort((g,l)=>g-l)){let g=f&1048575,l=f>>>20;if(i[l]!==o)continue;let m=u.get(l);typeof m=="undefined"&&u.set(l,m=[]),m.push(g)}if(u.size===0)return s;let c=[];for(let[f,g]of u){let l=e[f],m=l[0]>>>12,x=l[l.length-1]>>>12,v=l[l.length-1]>>>2&1023;n&&m>a&&c.push(s.slice(a,m));let d=s.slice(m,x+v);for(let y of g.sort((b,E)=>E-b)){let b=(l[y]>>>12)-m,E=(l[y]>>>2&1023)+b;d=[d.slice(0,b),"<mark>",d.slice(b,E),"</mark>",d.slice(E)].join("")}if(a=x+v,c.push(d)===2)break}return n&&a<s.length&&c.push(s.slice(a)),c.join("")})}function ae(t){let e=[];if(typeof t=="undefined")return e;let r=Array.isArray(t)?t:[t];for(let n=0;n<r.length;n++){let i=lunr.tokenizer.table,s=i.length;se(r[n],(o,a,u,c)=>{var f;switch(i[f=o+=s]||(i[f]=[]),a){case 0:case 2:i[o].push(u<<12|c-u<<2|a);break;case 1:let g=r[n].slice(u,c);H(g,lunr.tokenizer.separator,(l,m)=>{if(typeof lunr.segmenter!="undefined"){let x=g.slice(l,m);if(/^[MHIK]$/.test(lunr.segmenter.ctype_(x))){let v=lunr.segmenter.segment(x);for(let d=0,y=0;d<v.length;d++)i[o]||(i[o]=[]),i[o].push(u+l+y<<12|v[d].length<<2|a),e.push(new lunr.Token(v[d].toLowerCase(),{position:o<<20|i[o].length-1})),y+=v[d].length;return}}i[o].push(u+l<<12|m-l<<2|a),e.push(new lunr.Token(g.slice(l,m).toLowerCase(),{position:o<<20|i[o].length-1}))})}})}return e}function ue(t,e=r=>r){return t.trim().split(/"([^"]+)"/g).map((r,n)=>n&1?r.replace(/^\b|^(?![^\x00-\x7F]|$)|\s+/g," +"):r).join("").replace(/"|(?:^|\s+)[*+\-:^~]+(?=\s+|$)/g,"").split(/\s+/g).reduce((r,n)=>{let i=e(n);return[...r,...Array.isArray(i)?i:[i]]},[]).map(r=>/([~^]$)/.test(r)?`${r}1`:r).map(r=>/(^[+-]|[~^]\d+$)/.test(r)?r:`${r}*`).join(" ")}function ce(t){return ue(t,e=>{let r=[],n=new lunr.QueryLexer(e);n.run();for(let{type:i,str:s,start:o,end:a}of n.lexemes)switch(i){case"FIELD":["title","text","tags"].includes(s)||(e=[e.slice(0,a)," ",e.slice(a+1)].join(""));break;case"TERM":H(s,lunr.tokenizer.separator,(...u)=>{r.push([e.slice(0,o),s.slice(...u),e.slice(a)].join(""))})}return r})}function le(t){let e=new lunr.Query(["title","text","tags"]);new lunr.QueryParser(t,e).parse();for(let n of e.clauses)n.usePipeline=!0,n.term.startsWith("*")&&(n.wildcard=lunr.Query.wildcard.LEADING,n.term=n.term.slice(1)),n.term.endsWith("*")&&(n.wildcard=lunr.Query.wildcard.TRAILING,n.term=n.term.slice(0,-1));return e.clauses}function he(t,e){var i;let r=new Set(t),n={};for(let s=0;s<e.length;s++)for(let o of r)e[s].startsWith(o.term)&&(n[o.term]=!0,r.delete(o));for(let s of r)(i=lunr.stopWordFilter)!=null&&i.call(lunr,s.term)&&(n[s.term]=!1);return n}function fe(t,e){let r=new Set,n=new Uint16Array(t.length);for(let s=0;s<t.length;s++)for(let o=s+1;o<t.length;o++)t.slice(s,o)in e&&(n[s]=o-s);let i=[0];for(let s=i.length;s>0;){let o=i[--s];for(let u=1;u<n[o];u++)n[o+u]>n[o]-u&&(r.add(t.slice(o,o+u)),i[s++]=o+u);let a=o+n[o];n[a]&&a<t.length-1&&(i[s++]=a),r.add(t.slice(o,a))}return r.has("")?new Set([t]):r}function Oe(t){return e=>r=>{if(typeof r[e]=="undefined")return;let n=[r.location,e].join(":");return t.set(n,lunr.tokenizer.table=[]),r[e]}}function Re(t,e){let[r,n]=[new Set(t),new Set(e)];return[...new Set([...r].filter(i=>!n.has(i)))]}var U=class{constructor({config:e,docs:r,options:n}){let i=Oe(this.table=new Map);this.map=ie(r),this.options=n,this.index=lunr(function(){this.metadataWhitelist=["position"],this.b(0),e.lang.length===1&&e.lang[0]!=="en"?this.use(lunr[e.lang[0]]):e.lang.length>1&&this.use(lunr.multiLanguage(...e.lang)),this.tokenizer=ae,lunr.tokenizer.separator=new RegExp(e.separator),lunr.segmenter="TinySegmenter"in lunr?new lunr.TinySegmenter:void 0;let s=Re(["trimmer","stopWordFilter","stemmer"],e.pipeline);for(let o of e.lang.map(a=>a==="en"?lunr:lunr[a]))for(let a of s)this.pipeline.remove(o[a]),this.searchPipeline.remove(o[a]);this.ref("location");for(let[o,a]of Object.entries(e.fields))this.field(o,B(_({},a),{extractor:i(o)}));for(let o of r)this.add(o,{boost:o.boost})})}search(e){if(e=e.replace(new RegExp("\\p{sc=Han}+","gu"),s=>[...fe(s,this.index.invertedIndex)].join("* ")),e=ce(e),!e)return{items:[]};let r=le(e).filter(s=>s.presence!==lunr.Query.presence.PROHIBITED),n=this.index.search(e).reduce((s,{ref:o,score:a,matchData:u})=>{let c=this.map.get(o);if(typeof c!="undefined"){c=_({},c),c.tags&&(c.tags=[...c.tags]);let f=he(r,Object.keys(u.metadata));for(let l of this.index.fields){if(typeof c[l]=="undefined")continue;let m=[];for(let d of Object.values(u.metadata))typeof d[l]!="undefined"&&m.push(...d[l].position);if(!m.length)continue;let x=this.table.get([c.location,l].join(":")),v=Array.isArray(c[l])?q:oe;c[l]=v(c[l],x,m,l!=="text")}let g=+!c.parent+Object.values(f).filter(l=>l).length/Object.keys(f).length;s.push(B(_({},c),{score:a*(1+K(g,2)),terms:f}))}return s},[]).sort((s,o)=>o.score-s.score).reduce((s,o)=>{let a=this.map.get(o.location);if(typeof a!="undefined"){let u=a.parent?a.parent.location:a.location;s.set(u,[...s.get(u)||[],o])}return s},new Map);for(let[s,o]of n)if(!o.find(a=>a.location===s)){let a=this.map.get(s);o.push(B(_({},a),{score:0,terms:{}}))}let i;if(this.options.suggest){let s=this.index.query(o=>{for(let a of r)o.term(a.term,{fields:["title"],presence:lunr.Query.presence.REQUIRED,wildcard:lunr.Query.wildcard.TRAILING})});i=s.length?Object.keys(s[0].matchData.metadata):[]}return _({items:[...n.values()]},typeof i!="undefined"&&{suggest:i})}};var de;function Ie(t){return W(this,null,function*(){let e="../lunr";if(typeof parent!="undefined"&&"IFrameWorker"in parent){let n=ne("script[src]"),[i]=n.src.split("/worker");e=e.replace("..",i)}let r=[];for(let n of t.lang){switch(n){case"ja":r.push(`${e}/tinyseg.js`);break;case"hi":case"th":r.push(`${e}/wordcut.js`);break}n!=="en"&&r.push(`${e}/min/lunr.${n}.min.js`)}t.lang.length>1&&r.push(`${e}/min/lunr.multi.min.js`),r.length&&(yield importScripts(`${e}/min/lunr.stemmer.support.min.js`,...r))})}function Fe(t){return W(this,null,function*(){switch(t.type){case 0:return yield Ie(t.data.config),de=new U(t.data),{type:1};case 2:let e=t.data;try{return{type:3,data:de.search(e)}}catch(r){return console.warn(`Invalid query: ${e} \u2013 see https://bit.ly/2s3ChXG`),console.warn(r),{type:3,data:{items:[]}}}default:throw new TypeError("Invalid message type")}})}self.lunr=Y.default;Y.default.utils.warn=console.warn;addEventListener("message",t=>W(null,null,function*(){postMessage(yield Fe(t.data))}));})();
//# sourceMappingURL=search.7a47a382.min.js.map

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

{"version":3,"sources":["src/templates/assets/stylesheets/main/components/_meta.scss","../../../../src/templates/assets/stylesheets/main.scss","src/templates/assets/stylesheets/main/_resets.scss","src/templates/assets/stylesheets/main/_colors.scss","src/templates/assets/stylesheets/main/_icons.scss","src/templates/assets/stylesheets/main/_typeset.scss","src/templates/assets/stylesheets/utilities/_break.scss","src/templates/assets/stylesheets/main/components/_author.scss","src/templates/assets/stylesheets/main/components/_banner.scss","src/templates/assets/stylesheets/main/components/_base.scss","src/templates/assets/stylesheets/main/components/_clipboard.scss","src/templates/assets/stylesheets/main/components/_code.scss","src/templates/assets/stylesheets/main/components/_consent.scss","src/templates/assets/stylesheets/main/components/_content.scss","src/templates/assets/stylesheets/main/components/_dialog.scss","src/templates/assets/stylesheets/main/components/_feedback.scss","src/templates/assets/stylesheets/main/components/_footer.scss","src/templates/assets/stylesheets/main/components/_form.scss","src/templates/assets/stylesheets/main/components/_header.scss","node_modules/material-design-color/material-color.scss","src/templates/assets/stylesheets/main/components/_nav.scss","src/templates/assets/stylesheets/main/components/_pagination.scss","src/templates/assets/stylesheets/main/components/_path.scss","src/templates/assets/stylesheets/main/components/_post.scss","src/templates/assets/stylesheets/main/components/_progress.scss","src/templates/assets/stylesheets/main/components/_search.scss","src/templates/assets/stylesheets/main/components/_select.scss","src/templates/assets/stylesheets/main/components/_sidebar.scss","src/templates/assets/stylesheets/main/components/_source.scss","src/templates/assets/stylesheets/main/components/_status.scss","src/templates/assets/stylesheets/main/components/_tabs.scss","src/templates/assets/stylesheets/main/components/_tag.scss","src/templates/assets/stylesheets/main/components/_tooltip.scss","src/templates/assets/stylesheets/main/components/_tooltip2.scss","src/templates/assets/stylesheets/main/components/_top.scss","src/templates/assets/stylesheets/main/components/_version.scss","src/templates/assets/stylesheets/main/extensions/markdown/_admonition.scss","src/templates/assets/stylesheets/main/extensions/markdown/_footnotes.scss","src/templates/assets/stylesheets/main/extensions/markdown/_toc.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_arithmatex.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_critic.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_details.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_emoji.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_highlight.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_keys.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_tabbed.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_tasklist.scss","src/templates/assets/stylesheets/main/integrations/_giscus.scss","src/templates/assets/stylesheets/main/integrations/_mermaid.scss","src/templates/assets/stylesheets/main/modifiers/_grid.scss","src/templates/assets/stylesheets/main/modifiers/_inline.scss"],"names":[],"mappings":"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CAmBH,iDAAA,CAAA,yCnCkhHN,CmC9gHI,wEACE,anCghHN,CmCriHE,4DACE,oBnCwiHJ,CmCriHI,sFACE,gCnCuiHN,CmCliHE,oEACE,0BnCqiHJ,CmCliHI,kFACE,wBAlBG,CAmBH,qDAAA,CAAA,6CnCoiHN,CmChiHI,gFACE,anCkiHN,CmCvjHE,8DACE,oBnC0jHJ,CmCvjHI,wFACE,gCnCyjHN,CmCpjHE,sEACE,0BnCujHJ,CmCpjHI,oFACE,wBAlBG,CAmBH,sDAAA,CAAA,8CnCsjHN,CmCljHI,kFACE,anCojHN,CmCzkHE,4DACE,oBnC4kHJ,CmCzkHI,sFACE,gCnC2kHN,CmCtkHE,oEACE,0BnCykHJ,CmCtkHI,kFACE,wBAlBG,CAmBH,qDAAA,CAAA,6CnCwkHN,CmCpkHI,gFACE,anCskHN,CmC3lHE,4DACE,oBnC8lHJ,CmC3lHI,sFACE,gCnC6lHN,CmCxlHE,oEACE,0BnC2lHJ,CmCxlHI,kFACE,wBAlBG,CAmBH,qDAAA,CAAA,6CnC0lHN,CmCtlHI,gFACE,anCwlHN,CmC7mHE,0DACE,oBnCgnHJ,CmC7mHI,oFACE,gCnC+mHN,CmC1mHE,kEACE,0BnC6mHJ,CmC1mHI,gFACE,wBAlBG,CAmBH,oDAAA,CAAA,4CnC4mHN,CmCxmHI,8EACE,anC0mHN,CmC/nHE,oDACE,oBnCkoHJ,CmC/nHI,8EACE,gCnCioHN,CmC5nHE,4DACE,0BnC+nHJ,CmC5nHI,0EACE,wBAlBG,CAmBH,iDAAA,CAAA,yCnC8nHN,CmC1nHI,wEACE,anC4nHN,CmCjpHE,4DACE,oBnCopHJ,CmCjpHI,sFACE,gCnCmpHN,CmC9oHE,oEACE,0BnCipHJ,CmC9oHI,kFACE,wBAlBG,CAmBH,qDAAA,CAAA,6CnCgpHN,CmC5oHI,gFACE,anC8oHN,CmCnqHE,wDACE,oBnCsqHJ,CmCnqHI,kFACE,gCnCqqHN,CmChqHE,gEACE,0BnCmqHJ,CmChqHI,8EACE,wBAlBG,CAmBH,mDAAA,CAAA,2CnCkqHN,CmC9pHI,4EACE,anCgqHN,CoCp0HA,MACE,qMpCu0HF,CoC9zHE,sBAEE,uCAAA,CADA,g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Cv7IQ,+CACE,Q5Cy7IV,C4C17IQ,+CACE,Q5C47IV,C4C77IQ,+CACE,Q5C+7IV,C4Ch8IQ,+CACE,Q5Ck8IV,C4Cn8IQ,+CACE,Q5Cq8IV,C4Ct8IQ,+CACE,Q5Cw8IV,C4Cz8IQ,+CACE,Q5C28IV,C4C58IQ,+CACE,Q5C88IV,CACF,C4Cz8IM,uCACE,gC5C28IR,C4Cv8IM,oDACE,a5Cy8IR,C4Cp8II,yCACE,S5Cs8IN,C4Cl8IM,2CACE,aAAA,CACA,8B5Co8IR,C4C97IE,4BACE,U5Cg8IJ,C4C77II,aAJF,4BAKI,gB5Cg8IJ,CACF,C4C57IE,0BACE,Y5C87IJ,C4C37II,aAJF,0BAKI,a5C87IJ,C4C17IM,sCACE,O5C47IR,C4C77IM,uCACE,O5C+7IR,C4Ch8IM,uCACE,O5Ck8IR,C4Cn8IM,uCACE,O5Cq8IR,C4Ct8IM,uCACE,O5Cw8IR,C4Cz8IM,uCACE,O5C28IR,C4C58IM,uCACE,O5C88IR,C4C/8IM,uCACE,O5Ci9IR,C4Cl9IM,uCACE,O5Co9IR,C4Cr9IM,wCACE,Q5Cu9IR,C4Cx9IM,wCACE,Q5C09IR,C4C39IM,wCACE,Q5C69IR,C4C99IM,wCACE,Q5Cg+IR,C4Cj+IM,wCACE,Q5Cm+IR,C4Cp+IM,wCACE,Q5Cs+IR,C4Cv+IM,wCACE,Q5Cy+IR,C4C1+IM,wCACE,Q5C4+IR,C4C7+IM,wCACE,Q5C++IR,C4Ch/IM,wCACE,Q5Ck/IR,C4Cn/IM,wCACE,Q5Cq/IR,CACF,C4C/+II,+FAEE,Q5Ci/IN,C4C9+IM,yGACE,wBAAA,CACA,yB5Ci/IR,C4Cx+IM,2DAEE,wBAAA,CACA,yBAAA,CAFA,Q5C4+IR,C4Cr+IM,iEACE,Q5Cu+IR,C4Cp+IQ,qLAGE,wBAAA,CACA,yBAAA,CAFA,Q5Cw+IV,C4Cl+IQ,6FACE,wBAAA,CACA,yB5Co+IV,C4C/9IM,yDACE,kB5Ci+IR,C4C59II,sCACE,Q5C89IN,C4Cz9IE,2BAEE,iBAAA,CAOA,kBAAA,CAHA,uCAAA,CAEA,cAAA,CAPA,aAAA,CAGA,YAAA,CACA,gBAAA,CAEA,mBAAA,CAGA,gCAAA,CAPA,W5Ck+IJ,C4Cx9II,i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","file":"main.css"}
@media screen{[data-md-color-scheme=slate]{--md-default-fg-color:hsla(var(--md-hue),15%,90%,0.82);--md-default-fg-color--light:hsla(var(--md-hue),15%,90%,0.56);--md-default-fg-color--lighter:hsla(var(--md-hue),15%,90%,0.32);--md-default-fg-color--lightest:hsla(var(--md-hue),15%,90%,0.12);--md-default-bg-color:hsla(var(--md-hue),15%,14%,1);--md-default-bg-color--light:hsla(var(--md-hue),15%,14%,0.54);--md-default-bg-color--lighter:hsla(var(--md-hue),15%,14%,0.26);--md-default-bg-color--lightest:hsla(var(--md-hue),15%,14%,0.07);--md-code-fg-color:hsla(var(--md-hue),18%,86%,0.82);--md-code-bg-color:hsla(var(--md-hue),15%,18%,1);--md-code-bg-color--light:hsla(var(--md-hue),15%,18%,0.9);--md-code-bg-color--lighter:hsla(var(--md-hue),15%,18%,0.54);--md-code-hl-color:#2977ff;--md-code-hl-color--light:#2977ff1a;--md-code-hl-number-color:#e6695b;--md-code-hl-special-color:#f06090;--md-code-hl-function-color:#c973d9;--md-code-hl-constant-color:#9383e2;--md-code-hl-keyword-color:#6791e0;--md-code-hl-string-color:#2fb170;--md-code-hl-name-color:var(--md-code-fg-color);--md-code-hl-operator-color:var(--md-default-fg-color--light);--md-code-hl-punctuation-color:var(--md-default-fg-color--light);--md-code-hl-comment-color:var(--md-default-fg-color--light);--md-code-hl-generic-color:var(--md-default-fg-color--light);--md-code-hl-variable-color:var(--md-default-fg-color--light);--md-typeset-color:var(--md-default-fg-color);--md-typeset-a-color:var(--md-primary-fg-color);--md-typeset-kbd-color:hsla(var(--md-hue),15%,90%,0.12);--md-typeset-kbd-accent-color:hsla(var(--md-hue),15%,90%,0.2);--md-typeset-kbd-border-color:hsla(var(--md-hue),15%,14%,1);--md-typeset-mark-color:#4287ff4d;--md-typeset-table-color:hsla(var(--md-hue),15%,95%,0.12);--md-typeset-table-color--light:hsla(var(--md-hue),15%,95%,0.035);--md-admonition-fg-color:var(--md-default-fg-color);--md-admonition-bg-color:var(--md-default-bg-color);--md-footer-bg-color:hsla(var(--md-hue),15%,10%,0.87);--md-footer-bg-color--dark:hsla(var(--md-hue),15%,8%,1);--md-shadow-z1:0 0.2rem 0.5rem #0000000d,0 0 0.05rem #0000001a;--md-shadow-z2:0 0.2rem 0.5rem #00000040,0 0 0.05rem #00000040;--md-shadow-z3:0 0.2rem 0.5rem #0006,0 0 0.05rem #00000059;color-scheme:dark}[data-md-color-scheme=slate] img[src$="#gh-light-mode-only"],[data-md-color-scheme=slate] img[src$="#only-light"]{display:none}[data-md-color-scheme=slate][data-md-color-primary=pink]{--md-typeset-a-color:#ed5487}[data-md-color-scheme=slate][data-md-color-primary=purple]{--md-typeset-a-color:#c46fd3}[data-md-color-scheme=slate][data-md-color-primary=deep-purple]{--md-typeset-a-color:#a47bea}[data-md-color-scheme=slate][data-md-color-primary=indigo]{--md-typeset-a-color:#5488e8}[data-md-color-scheme=slate][data-md-color-primary=teal]{--md-typeset-a-color:#00ccb8}[data-md-color-scheme=slate][data-md-color-primary=green]{--md-typeset-a-color:#71c174}[data-md-color-scheme=slate][data-md-color-primary=deep-orange]{--md-typeset-a-color:#ff764d}[data-md-color-scheme=slate][data-md-color-primary=brown]{--md-typeset-a-color:#c1775c}[data-md-color-scheme=slate][data-md-color-primary=black],[data-md-color-scheme=slate][data-md-color-primary=blue-grey],[data-md-color-scheme=slate][data-md-color-primary=grey],[data-md-color-scheme=slate][data-md-color-primary=white]{--md-typeset-a-color:#5e8bde}[data-md-color-switching] *,[data-md-color-switching] :after,[data-md-color-switching] :before{transition-duration:0ms!important}}[data-md-color-accent=red]{--md-accent-fg-color:#ff1947;--md-accent-fg-color--transparent:#ff19471a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=pink]{--md-accent-fg-color:#f50056;--md-accent-fg-color--transparent:#f500561a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=purple]{--md-accent-fg-color:#df41fb;--md-accent-fg-color--transparent:#df41fb1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=deep-purple]{--md-accent-fg-color:#7c4dff;--md-accent-fg-color--transparent:#7c4dff1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=indigo]{--md-accent-fg-color:#526cfe;--md-accent-fg-color--transparent:#526cfe1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=blue]{--md-accent-fg-color:#4287ff;--md-accent-fg-color--transparent:#4287ff1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=light-blue]{--md-accent-fg-color:#0091eb;--md-accent-fg-color--transparent:#0091eb1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=cyan]{--md-accent-fg-color:#00bad6;--md-accent-fg-color--transparent:#00bad61a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=teal]{--md-accent-fg-color:#00bda4;--md-accent-fg-color--transparent:#00bda41a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=green]{--md-accent-fg-color:#00c753;--md-accent-fg-color--transparent:#00c7531a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=light-green]{--md-accent-fg-color:#63de17;--md-accent-fg-color--transparent:#63de171a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=lime]{--md-accent-fg-color:#b0eb00;--md-accent-fg-color--transparent:#b0eb001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=yellow]{--md-accent-fg-color:#ffd500;--md-accent-fg-color--transparent:#ffd5001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=amber]{--md-accent-fg-color:#fa0;--md-accent-fg-color--transparent:#ffaa001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=orange]{--md-accent-fg-color:#ff9100;--md-accent-fg-color--transparent:#ff91001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=deep-orange]{--md-accent-fg-color:#ff6e42;--md-accent-fg-color--transparent:#ff6e421a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-primary=red]{--md-primary-fg-color:#ef5552;--md-primary-fg-color--light:#e57171;--md-primary-fg-color--dark:#e53734;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=pink]{--md-primary-fg-color:#e92063;--md-primary-fg-color--light:#ec417a;--md-primary-fg-color--dark:#c3185d;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=purple]{--md-primary-fg-color:#ab47bd;--md-primary-fg-color--light:#bb69c9;--md-primary-fg-color--dark:#8c24a8;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=deep-purple]{--md-primary-fg-color:#7e56c2;--md-primary-fg-color--light:#9574cd;--md-primary-fg-color--dark:#673ab6;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=indigo]{--md-primary-fg-color:#4051b5;--md-primary-fg-color--light:#5d6cc0;--md-primary-fg-color--dark:#303fa1;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=blue]{--md-primary-fg-color:#2094f3;--md-primary-fg-color--light:#42a5f5;--md-primary-fg-color--dark:#1975d2;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=light-blue]{--md-primary-fg-color:#02a6f2;--md-primary-fg-color--light:#28b5f6;--md-primary-fg-color--dark:#0287cf;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=cyan]{--md-primary-fg-color:#00bdd6;--md-primary-fg-color--light:#25c5da;--md-primary-fg-color--dark:#0097a8;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=teal]{--md-primary-fg-color:#009485;--md-primary-fg-color--light:#26a699;--md-primary-fg-color--dark:#007a6c;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=green]{--md-primary-fg-color:#4cae4f;--md-primary-fg-color--light:#68bb6c;--md-primary-fg-color--dark:#398e3d;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=light-green]{--md-primary-fg-color:#8bc34b;--md-primary-fg-color--light:#9ccc66;--md-primary-fg-color--dark:#689f38;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=lime]{--md-primary-fg-color:#cbdc38;--md-primary-fg-color--light:#d3e156;--md-primary-fg-color--dark:#b0b52c;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=yellow]{--md-primary-fg-color:#ffec3d;--md-primary-fg-color--light:#ffee57;--md-primary-fg-color--dark:#fbc02d;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=amber]{--md-primary-fg-color:#ffc105;--md-primary-fg-color--light:#ffc929;--md-primary-fg-color--dark:#ffa200;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=orange]{--md-primary-fg-color:#ffa724;--md-primary-fg-color--light:#ffa724;--md-primary-fg-color--dark:#fa8900;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=deep-orange]{--md-primary-fg-color:#ff6e42;--md-primary-fg-color--light:#ff8a66;--md-primary-fg-color--dark:#f4511f;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=brown]{--md-primary-fg-color:#795649;--md-primary-fg-color--light:#8d6e62;--md-primary-fg-color--dark:#5d4037;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=grey]{--md-primary-fg-color:#757575;--md-primary-fg-color--light:#9e9e9e;--md-primary-fg-color--dark:#616161;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3;--md-typeset-a-color:#4051b5}[data-md-color-primary=blue-grey]{--md-primary-fg-color:#546d78;--md-primary-fg-color--light:#607c8a;--md-primary-fg-color--dark:#455a63;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3;--md-typeset-a-color:#4051b5}[data-md-color-primary=light-green]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#72ad2e}[data-md-color-primary=lime]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#8b990a}[data-md-color-primary=yellow]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#b8a500}[data-md-color-primary=amber]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#d19d00}[data-md-color-primary=orange]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#e68a00}[data-md-color-primary=white]{--md-primary-fg-color:hsla(var(--md-hue),0%,100%,1);--md-primary-fg-color--light:hsla(var(--md-hue),0%,100%,0.7);--md-primary-fg-color--dark:hsla(var(--md-hue),0%,0%,0.07);--md-primary-bg-color:hsla(var(--md-hue),0%,0%,0.87);--md-primary-bg-color--light:hsla(var(--md-hue),0%,0%,0.54);--md-typeset-a-color:#4051b5}[data-md-color-primary=white] .md-button{color:var(--md-typeset-a-color)}[data-md-color-primary=white] .md-button--primary{background-color:var(--md-typeset-a-color);border-color:var(--md-typeset-a-color);color:hsla(var(--md-hue),0%,100%,1)}@media screen and (min-width:60em){[data-md-color-primary=white] .md-search__form{background-color:hsla(var(--md-hue),0%,0%,.07)}[data-md-color-primary=white] .md-search__form:hover{background-color:hsla(var(--md-hue),0%,0%,.32)}[data-md-color-primary=white] .md-search__input+.md-search__icon{color:hsla(var(--md-hue),0%,0%,.87)}}@media screen and (min-width:76.25em){[data-md-color-primary=white] .md-tabs{border-bottom:.05rem solid #00000012}}[data-md-color-primary=black]{--md-primary-fg-color:hsla(var(--md-hue),15%,9%,1);--md-primary-fg-color--light:hsla(var(--md-hue),15%,9%,0.54);--md-primary-fg-color--dark:hsla(var(--md-hue),15%,9%,1);--md-primary-bg-color:hsla(var(--md-hue),15%,100%,1);--md-primary-bg-color--light:hsla(var(--md-hue),15%,100%,0.7);--md-typeset-a-color:#4051b5}[data-md-color-primary=black] .md-button{color:var(--md-typeset-a-color)}[data-md-color-primary=black] .md-button--primary{background-color:var(--md-typeset-a-color);border-color:var(--md-typeset-a-color);color:hsla(var(--md-hue),0%,100%,1)}[data-md-color-primary=black] .md-header{background-color:hsla(var(--md-hue),15%,9%,1)}@media screen and (max-width:59.984375em){[data-md-color-primary=black] .md-nav__source{background-color:hsla(var(--md-hue),15%,11%,.87)}}@media screen and (max-width:76.234375em){html [data-md-color-primary=black] .md-nav--primary .md-nav__title[for=__drawer]{background-color:hsla(var(--md-hue),15%,9%,1)}}@media screen and (min-width:76.25em){[data-md-color-primary=black] .md-tabs{background-color:hsla(var(--md-hue),15%,9%,1)}}
{"version":3,"sources":["src/templates/assets/stylesheets/palette/_scheme.scss","../../../../src/templates/assets/stylesheets/palette.scss","src/templates/assets/stylesheets/palette/_accent.scss","src/templates/assets/stylesheets/palette/_primary.scss","src/templates/assets/stylesheets/utilities/_break.scss"],"names":[],"mappings":"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","file":"palette.css"}
{#-
This file was automatically generated - do not edit
-#}
{% macro render_content(nav_item) %}
<span class="md-ellipsis">
{{ nav_item.title }}
</span>
{% endmacro %}
{% macro render(nav_item, ref) %}
{% set ref = ref or nav_item %}
{% if nav_item.children %}
{% set first = nav_item.children | first %}
{% if first.children %}
{{ render(first, ref) }}
{% else %}
<li class="md-path__item">
<a href="{{ first.url | url }}" class="md-path__link">
{{ render_content(ref) }}
</a>
</li>
{% endif %}
{% else %}
<li class="md-path__item">
<a href="{{ nav_item.url | url }}" class="md-path__link">
{{ render_content(ref) }}
</a>
</li>
{% endif %}
{% endmacro %}
{#-
This file was automatically generated - do not edit
-#}
{% import "partials/path-item.html" as item with context %}
{% if page.meta and page.meta.hide %}
{% set hidden = "hidden" if "path" in page.meta.hide %}
{% endif %}
{% set depth = page.ancestors | length %}
{% if nav.homepage %}
{% set depth = depth + 1 %}
{% endif %}
{% if depth > 1 %}
<nav class="md-path" aria-label="{{ lang.t('nav') }}" {{ hidden }}>
<ol class="md-path__list">
{% if nav.homepage %}
{{ item.render(nav.homepage) }}
{% endif %}
{% for nav_item in page.ancestors | reverse %}
{{ item.render(nav_item) }}
{% endfor %}
</ol>
</nav>
{% endif %}
+1
-1

@@ -21,2 +21,2 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

__version__ = "9.6.23"
__version__ = "9.7.0"

@@ -20,1 +20,15 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

# IN THE SOFTWARE.
from .structure import View
# -----------------------------------------------------------------------------
# Functions
# -----------------------------------------------------------------------------
# Sort views by name
def view_name(view: View):
return view.name
# Sort views by post count
def view_post_count(view: View):
return len(view.posts)

@@ -26,2 +26,4 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

from . import view_name
# -----------------------------------------------------------------------------

@@ -60,2 +62,4 @@ # Classes

archive_url_format = Type(str, default = "archive/{date}")
archive_pagination = Optional(Type(bool))
archive_pagination_per_page = Optional(Type(int))
archive_toc = Optional(Type(bool))

@@ -69,3 +73,7 @@

categories_slugify_separator = Type(str, default = "-")
categories_sort_by = Type(Callable, default = view_name)
categories_sort_reverse = Type(bool, default = False)
categories_allowed = Type(list, default = [])
categories_pagination = Optional(Type(bool))
categories_pagination_per_page = Optional(Type(int))
categories_toc = Optional(Type(bool))

@@ -76,2 +84,8 @@

authors_file = Type(str, default = "{blog}/.authors.yml")
authors_profiles = Type(bool, default = False)
authors_profiles_name = Type(str, default = "blog.authors")
authors_profiles_url_format = Type(str, default = "author/{slug}")
authors_profiles_pagination = Optional(Type(bool))
authors_profiles_pagination_per_page = Optional(Type(int))
authors_profiles_toc = Optional(Type(bool))

@@ -78,0 +92,0 @@ # Settings for pagination

@@ -48,6 +48,11 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

from .author import Authors
from . import view_name
from .author import Author, Authors
from .config import BlogConfig
from .readtime import readtime
from .structure import Archive, Category, Excerpt, Post, Reference, View
from .structure import (
Archive, Category, Profile,
Excerpt, Post, View,
Reference
)

@@ -90,8 +95,2 @@ # -----------------------------------------------------------------------------

# Initialize table of contents settings
if not isinstance(self.config.archive_toc, bool):
self.config.archive_toc = self.config.blog_toc
if not isinstance(self.config.categories_toc, bool):
self.config.categories_toc = self.config.blog_toc
# By default, drafts are rendered when the documentation is served,

@@ -139,3 +138,6 @@ # but not when it is built, for a better user experience

self._resolve_posts(files, config),
key = lambda post: post.config.date.created,
key = lambda post: (
post.config.pin,
post.config.date.created
),
reverse = True

@@ -146,17 +148,27 @@ )

if self.config.archive:
self.blog.views.extend(
self._generate_archive(config, files)
)
views = self._generate_archive(config, files)
self.blog.views.extend(views)
# Generate views for categories
if self.config.categories:
views = self._generate_categories(config, files)
# We always sort the list of categories by name first, so that any
# custom sorting function that returns the same value for two items
# returns them in a predictable and logical order, because sorting
# in Python is stable, i.e., order of equal items is preserved
self.blog.views.extend(sorted(
self._generate_categories(config, files),
key = lambda view: view.name,
reverse = False
sorted(views, key = view_name),
key = self.config.categories_sort_by,
reverse = self.config.categories_sort_reverse
))
# Generate views for profiles
if self.config.authors_profiles:
views = self._generate_profiles(config, files)
self.blog.views.extend(views)
# Generate pages for views
if self.config.pagination:
for view in self._resolve_views(self.blog):
for view in self._resolve_views(self.blog):
if self._config_pagination(view):
for page in self._generate_pages(view, config, files):

@@ -216,5 +228,14 @@ view.pages.append(page)

# Attach views for profiles
if self.config.authors_profiles:
title = self._translate(self.config.authors_profiles_name, config)
views = [_ for _ in self.blog.views if isinstance(_, Profile)]
# Attach and link views for categories, if any
if self.blog.file.inclusion.is_in_nav() and views:
self._attach_to(self.blog, Section(title, views), nav)
# Attach pages for views
if self.config.pagination:
for view in self._resolve_views(self.blog):
for view in self._resolve_views(self.blog):
if self._config_pagination(view):
for at in range(1, len(view.pages)):

@@ -235,3 +256,3 @@ self._attach_at(view.parent, view, view.pages[at])

if page not in self.blog.posts:
if not self.config.pagination:
if not self._config_pagination(page):
return

@@ -259,8 +280,8 @@

if self.config.authors:
for name in page.config.authors:
if name not in self.authors:
raise PluginError(f"Couldn't find author '{name}'")
for id in page.config.authors:
if id not in self.authors:
raise PluginError(f"Couldn't find author '{id}'")
# Append to list of authors
page.authors.append(self.authors[name])
page.authors.append(self.authors[id])

@@ -324,3 +345,3 @@ # Extract settings for excerpts

# Patch URL template filter to add support for paginated views, i.e.,
# that paginated views never link to themselves but to the main view
# that paginated views never link to themselves but to the main vie
@pass_context

@@ -601,2 +622,33 @@ def url_filter_with_pagination(context: Context, url: str | None):

# Generate views for profiles - analyze posts and generate the necessary
# views to provide a profile page for each author listing all posts
def _generate_profiles(self, config: MkDocsConfig, files: Files):
for post in self.blog.posts:
for id in post.config.authors:
author = self.authors[id]
path = self._format_path_for_profile(id, author)
# Create file for view, if it does not exist
file = files.get_file_from_path(path)
if not file:
file = self._path_to_file(path, config)
files.append(file)
# Create file in temporary directory
self._save_to_file(file.abs_src_path, f"# {author.name}")
# Temporarily remove view from navigation and assign profile
# URL to author, if not explicitly set
file.inclusion = InclusionLevel.EXCLUDED
if not author.url:
author.url = file.url
# Create and yield view
if not isinstance(file.page, Profile):
yield Profile(author.name, file, config)
# Assign post to profile
assert isinstance(file.page, Profile)
file.page.posts.append(post)
# Generate pages for pagination - analyze view and generate the necessary

@@ -609,3 +661,3 @@ # pages, creating a chain of views for simple rendering and replacement

# handled as copies of a view, as they map to the same source location
step = self.config.pagination_per_page
step = self._config_pagination_per_page(view)
for at in range(step, len(view.posts), step):

@@ -760,7 +812,7 @@ path = self._format_path_for_pagination(view, 1 + at // step)

# Create pagination, if enabled
if self.config.pagination:
if self._config_pagination(view):
at = view.pages.index(view)
# Compute pagination boundaries
step = self.config.pagination_per_page
step = self._config_pagination_per_page(view)
p, q = at * step, at * step + step

@@ -785,14 +837,5 @@

# Determine whether to add posts to the table of contents of the view -
# note that those settings can be changed individually for each type of
# view, which is why we need to check the type of view and the table of
# contents setting for that type of view
toc = self.config.blog_toc
if isinstance(view, Archive):
toc = self.config.archive_toc
if isinstance(view, Category):
toc = self.config.categories_toc
# Attach top-level table of contents item to view if it should be added
# and both, the view and excerpt contain table of contents items
toc = self._config_toc(view)
if toc and excerpt.toc.items and view.toc.items:

@@ -821,2 +864,44 @@ view.toc.items[0].children.append(excerpt.toc.items[0])

# Retrieve configuration value or return default
def _config(self, key: str, default: any):
return default if self.config[key] is None else self.config[key]
# Retrieve configuration value for table of contents
def _config_toc(self, view: View):
default = self.config.blog_toc
if isinstance(view, Archive):
return self._config("archive_toc", default)
if isinstance(view, Category):
return self._config("categories_toc", default)
if isinstance(view, Profile):
return self._config("authors_profiles_toc", default)
else:
return default
# Retrieve configuration value for pagination
def _config_pagination(self, view: View):
default = self.config.pagination
if isinstance(view, Archive):
return self._config("archive_pagination", default)
if isinstance(view, Category):
return self._config("categories_pagination", default)
if isinstance(view, Profile):
return self._config("authors_profiles_pagination", default)
else:
return default
# Retrieve configuration value for pagination per page
def _config_pagination_per_page(self, view: View):
default = self.config.pagination_per_page
if isinstance(view, Archive):
return self._config("archive_pagination_per_page", default)
if isinstance(view, Category):
return self._config("categories_pagination_per_page", default)
if isinstance(view, Profile):
return self._config("authors_profiles_pagination_per_page", default)
else:
return default
# -------------------------------------------------------------------------
# Format path for post

@@ -861,2 +946,13 @@ def _format_path_for_post(self, post: Post, config: MkDocsConfig):

# Format path for profile
def _format_path_for_profile(self, id: str, author: Author):
path = self.config.authors_profiles_url_format.format(
slug = author.slug or id,
name = author.name
)
# Normalize path and strip slashes at the beginning and end
path = posixpath.normpath(path.strip("/"))
return posixpath.join(self.config.blog_dir, f"{path}.md")
# Format path for pagination

@@ -863,0 +959,0 @@ def _format_path_for_pagination(self, view: View, page: int):

@@ -276,2 +276,8 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

# Profile view
class Profile(View):
pass
# -----------------------------------------------------------------------------
# Reference

@@ -278,0 +284,0 @@ class Reference(Link):

@@ -36,4 +36,5 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

draft = Optional(Type(bool))
pin = Type(bool, default = False)
links = Optional(PostLinks())
readtime = Optional(Type(int))
slug = Optional(Type(str))

@@ -39,3 +39,3 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

from mkdocs.plugins import BasePlugin, event_priority
from mkdocs.utils import get_yaml_loader
from mkdocs.utils.yaml import get_yaml_loader
from zipfile import ZipFile, ZIP_DEFLATED

@@ -184,3 +184,3 @@

if paths_to_validate:
log.error(f"One or more paths aren't children of root")
log.error("One or more paths aren't children of root")
self._help_on_not_in_cwd(paths_to_validate)

@@ -187,0 +187,0 @@

@@ -24,5 +24,19 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

from mkdocs.config.base import Config
from mkdocs.config.config_options import DictOfItems, Type
from mkdocs.config.config_options import (
Choice, Deprecated, DictOfItems, ListOfItems, Type
)
# -----------------------------------------------------------------------------
# Options
# -----------------------------------------------------------------------------
# Options for log level
LogLevel = (
"error",
"warn",
"info",
"debug"
)
# -----------------------------------------------------------------------------
# Classes

@@ -40,2 +54,6 @@ # -----------------------------------------------------------------------------

# Settings for logging
log = Type(bool, default = True)
log_level = Choice(LogLevel, default = "info")
# Settings for external assets

@@ -45,2 +63,19 @@ assets = Type(bool, default = True)

assets_fetch_dir = Type(str, default = "assets/external")
assets_include = ListOfItems(Type(str), default = [])
assets_exclude = ListOfItems(Type(str), default = [])
assets_expr_map = DictOfItems(Type(str), default = {})
# Settings for external links
links = Type(bool, default = True)
links_attr_map = DictOfItems(Type(str), default = {})
links_noopener = Type(bool, default = True)
# Deprecated settings
external_assets = Deprecated(message = "Deprecated, use 'assets_fetch'")
external_assets_dir = Deprecated(moved_to = "assets_fetch_dir")
external_assets_include = Deprecated(moved_to = "assets_include")
external_assets_exclude = Deprecated(moved_to = "assets_exclude")
external_assets_expr = Deprecated(moved_to = "assets_expr_map")
external_links = Deprecated(moved_to = "links")
external_links_attr_map = Deprecated(moved_to = "links_attr_map")
external_links_noopener = Deprecated(moved_to = "links_noopener")

@@ -32,3 +32,5 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

from colorama import Fore, Style
from concurrent.futures import Future, ThreadPoolExecutor, wait
from concurrent.futures import Future, wait
from concurrent.futures.thread import ThreadPoolExecutor
from fnmatch import fnmatch
from hashlib import sha1

@@ -56,2 +58,3 @@ from mkdocs.config.config_options import ExtraScriptValue

class PrivacyPlugin(BasePlugin[PrivacyConfig]):
supports_multiple_instances = True

@@ -70,2 +73,3 @@ # Initialize thread pools and asset collections

self.assets = Files([])
self.assets_done: list[File] = []
self.assets_expr_map = {

@@ -77,2 +81,9 @@ ".css": r"url\(\s*([\"']?)(?P<url>http?[^)'\"]+)\1\s*\)",

# Set log level or disable logging altogether - @todo when refactoring
# this plugin for the next time, we should put this into a factory
if not self.config.log:
log.disabled = True
else:
log.setLevel(self.config.log_level.upper())
# Process external style sheets and scripts (run latest) - run this after

@@ -134,3 +145,9 @@ # all other plugins, so they can add additional assets

# type of external asset when writing. Thus, we create and enqueue a job for
# each image we find that checks if the image needs to be downloaded.
# each image we find that checks if the image needs to be downloaded. Also,
# downloading all external images at this stage, we reconcile all concurrent
# jobs in `on_env`, which is the stage in which the optimize plugin will
# evaluate what images can and need to be optimized. This means we can pass
# external images through the optimization pipeline. Additionally, we run
# this after all other plugins, so we allow them to add additional images
# to the content of the page. How cool is that?
@event_priority(-100)

@@ -157,3 +174,5 @@ def on_page_content(self, html, *, page, config, files):

# Sync all concurrent jobs
# Reconcile jobs and pass external assets to MkDocs (run earlier) - allow
# other plugins (e.g. optimize plugin) to post-process external assets
@event_priority(50)
def on_env(self, env, *, config, files):

@@ -163,5 +182,17 @@ if not self.config.enabled:

# Wait until all jobs until now are finished
# Reconcile concurrent jobs and clear thread pool, as we will reuse the
# same thread pool for fetching all remaining external assets
wait(self.pool_jobs)
self.pool_jobs.clear()
# Append all downloaded assets that are not style sheets or scripts to
# MkDocs's collection of files, making them available to other plugins
# for further processing. The remaining exteral assets are patched
# before copying, which is done at the end of the build process.
for file in self.assets:
_, extension = posixpath.splitext(file.dest_uri)
if extension not in [".css", ".js"]:
self.assets_done.append(file)
files.append(file)
# Process external assets in template (run later)

@@ -190,3 +221,4 @@ @event_priority(-50)

# Reconcile jobs (run earlier)
# Reconcile jobs (run earlier) - allow other plugins (e.g. optimize plugin)
# to process all downloaded assets, which is why we must reconcile here
@event_priority(50)

@@ -211,6 +243,6 @@ def on_post_build(self, *, config):

# Otherwise just copy external asset to output directory if it
# exists, i.e., if the download succeeded
else:
if os.path.exists(file.abs_src_path):
# Otherwise just copy external asset to output directory, if we
# haven't handed control to MkDocs in `on_env` before
elif file not in self.assets_done:
if os.path.exists(str(file.abs_src_path)):
file.copy_file()

@@ -248,2 +280,24 @@

# Check if URL matches one of the inclusion patterns
if self.config.assets_include:
for pattern in self.config.assets_include:
if fnmatch(self._path_from_url(url), pattern):
return False
# File is not included
log.debug(
f"Excluding external file '{url.geturl()}' {via}due to "
f"inclusion patterns"
)
return True
# Check if URL matches one of the exclusion patterns
for pattern in self.config.assets_exclude:
if fnmatch(self._path_from_url(url), pattern):
log.debug(
f"Excluding external file '{url.geturl()}' {via}due to "
f"exclusion patterns"
)
return True
# Print warning if fetching is not enabled

@@ -314,2 +368,17 @@ if not self.config.assets_fetch:

# Handle external link
if self.config.links and el.tag == "a":
for key, value in self.config.links_attr_map.items():
el.set(key, value)
# Set `rel=noopener` if link opens in a new window
if self.config.links_noopener:
if el.get("target") == "_blank":
rel = re.findall(r"\S+", el.get("rel", ""))
if "noopener" not in rel:
rel.append("noopener")
# Set relationships after adding `noopener`
el.set("rel", " ".join(rel))
# Handle external style sheet or preconnect hint

@@ -316,0 +385,0 @@ if el.tag == "link":

@@ -42,2 +42,6 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

# Search field configuration
class SearchFieldConfig(Config):
boost = Type((int, float), default = 1.0)
# Search plugin configuration

@@ -51,2 +55,3 @@ class SearchConfig(Config):

pipeline = Optional(ListOfItems(Choice(pipeline)))
fields = Type(dict, default = {})

@@ -53,0 +58,0 @@ # Settings for text segmentation (Chinese)

@@ -30,5 +30,6 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

from mkdocs import utils
from mkdocs.config.config_options import SubConfig
from mkdocs.plugins import BasePlugin
from .config import SearchConfig
from .config import SearchConfig, SearchFieldConfig

@@ -85,2 +86,15 @@ try:

# Validate field configuration
validator = SubConfig(SearchFieldConfig)
for config in self.config.fields.values():
validator.run_validation(config)
# Merge with default fields
if "title" not in self.config.fields:
self.config.fields["title"] = { "boost": 1e3 }
if "text" not in self.config.fields:
self.config.fields["text"] = { "boost": 1e0 }
if "tags" not in self.config.fields:
self.config.fields["tags"] = { "boost": 1e6 }
# Initialize search index

@@ -235,3 +249,3 @@ self.search_index = SearchIndex(**self.config)

key: self.config[key]
for key in ["lang", "separator", "pipeline"]
for key in ["lang", "separator", "pipeline", "fields"]
}

@@ -238,0 +252,0 @@

@@ -21,4 +21,7 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

import os
from mkdocs.config.base import Config
from mkdocs.config.config_options import Deprecated, Type
from mkdocs.config.config_options import Deprecated, ListOfItems, Type
from mkdocs.config.defaults import _LogLevel

@@ -32,19 +35,36 @@ # -----------------------------------------------------------------------------

enabled = Type(bool, default = True)
concurrency = Type(int, default = max(1, os.cpu_count() - 1))
# Settings for caching
cache = Type(bool, default = True)
cache_dir = Type(str, default = ".cache/plugin/social")
# Settings for social cards
# Settings for logging
log = Type(bool, default = True)
log_level = _LogLevel(default = "warn")
# Settings for cards
cards = Type(bool, default = True)
cards_dir = Type(str, default = "assets/images/social")
cards_layout_dir = Type(str, default = "layouts")
cards_layout = Type(str, default = "default")
cards_layout_options = Type(dict, default = {})
cards_include = ListOfItems(Type(str), default = [])
cards_exclude = ListOfItems(Type(str), default = [])
# Settings for debugging
debug = Type(bool, default = False)
debug_on_build = Type(bool, default = False)
debug_grid = Type(bool, default = True)
debug_grid_step = Type(int, default = 32)
debug_color = Type(str, default = "grey")
# Deprecated settings
cards_color = Deprecated(
option_type = Type(dict, default = {}),
message =
"Deprecated, use 'cards_layout_options.background_color' "
"and 'cards_layout_options.color' with 'default' layout"
)
)
cards_font = Deprecated(
option_type = Type(str),
message = "Deprecated, use 'cards_layout_options.font_family'"
)

@@ -21,19 +21,10 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

# -----------------------------------------------------------------------------
# Disclaimer
# -----------------------------------------------------------------------------
# Please note: this version of the social plugin is not actively development
# anymore. Instead, Material for MkDocs Insiders ships a complete rewrite of
# the plugin which is much more powerful and addresses all shortcomings of
# this implementation. Additionally, the new social plugin allows to create
# entirely custom social cards. You can probably imagine, that this was a lot
# of work to pull off. If you run into problems, or want to have additional
# functionality, please consider sponsoring the project. You can then use the
# new version of the plugin immediately.
# -----------------------------------------------------------------------------
from __future__ import annotations
import concurrent.futures
import functools
import html
import json
import logging
import os
import pickle
import posixpath

@@ -43,17 +34,31 @@ import re

import sys
import yaml
from collections import defaultdict
from hashlib import md5
from concurrent.futures import Future
from concurrent.futures.thread import ThreadPoolExecutor
from copy import copy
from fnmatch import fnmatch
from hashlib import sha1
from html import unescape
from io import BytesIO
from mkdocs.commands.build import DuplicateFilter
from jinja2 import Environment
from jinja2.meta import find_undeclared_variables
from mkdocs.config.base import Config
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.exceptions import PluginError
from mkdocs.plugins import BasePlugin
from mkdocs.plugins import BasePlugin, event_priority
from mkdocs.structure.files import File, InclusionLevel
from mkdocs.structure.pages import Page
from mkdocs.utils import write_file
from shutil import copyfile
from statistics import stdev
from threading import Lock
from yaml import SafeLoader
from .config import SocialConfig
from .layout import Layer, Layout, Line, get_offset, get_size
from .templates import x_filter
try:
from PIL import Image, ImageDraw, ImageFont
from PIL import Image, ImageColor, ImageDraw, ImageFont
from PIL.Image import Image as _Image
except ImportError as e:

@@ -65,3 +70,2 @@ import_errors = {repr(e)}

cairosvg_error: str = ""
try:

@@ -74,3 +78,2 @@ from cairosvg import svg2png

# -----------------------------------------------------------------------------

@@ -82,47 +85,87 @@ # Classes

class SocialPlugin(BasePlugin[SocialConfig]):
supports_multiple_instances = True
def __init__(self):
self._executor = concurrent.futures.ThreadPoolExecutor(4)
# Manifest
manifest: dict[str, str] = {}
# Retrieve configuration
# Initialize plugin
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Initialize incremental builds
self.is_serve = False
# Determine whether we're serving the site, and thus doing an incremental
# build, and initialize two thread pools for card generation, because it's
# split into two stages: rendering of layers and composition. We use two
# thread pools, one for each stage, as we need to make sure that all layers
# of a card are rendered before we compose the card itself. At the same time
# we want to off-load as much as possible onto worker threads, as card
# generation is a problem that can be perfectly solved in parallel. Thus,
# we leverage the file system to cache the generated images, so we don't
# re-generate the exact same images again and again, making successive
# builds of large sites much faster.
def on_startup(self, *, command, dirty):
self.is_serve = command == "serve"
# Initialize thread pool for cards
self.card_pool = ThreadPoolExecutor(self.config.concurrency)
self.card_pool_jobs: dict[str, Future] = {}
# Initialize thread pool for card layers
self.card_layer_pool = ThreadPoolExecutor(self.config.concurrency)
self.card_layer_pool_jobs: dict[str, Future] = {}
# Resolve and load manifest and initialize environment
def on_config(self, config):
self.color = colors.get("indigo")
if not self.config.enabled:
self.config.cards = False
if not self.config.cards:
return
# Check dependencies
if import_errors:
raise PluginError(
"Required dependencies of \"social\" plugin not found:\n"
+ str("\n".join(map(lambda x: "- " + x, import_errors)))
+ "\n\n--> Install with: pip install \"mkdocs-material[imaging]\""
# Resolve cache directory (once) - this is necessary, so the cache is
# always relative to the configuration file, and thus project, and not
# relative to the current working directory, or it would not work with
# the projects plugin.
path = os.path.abspath(self.config.cache_dir)
if path != self.config.cache_dir:
self.config.cache_dir = os.path.join(
os.path.dirname(config.config_file_path),
os.path.normpath(self.config.cache_dir)
)
if cairosvg_error:
raise PluginError(
"\"cairosvg\" Python module is installed, but it crashed with:\n"
+ cairosvg_error
+ "\n\n--> Check out the troubleshooting guide: https://t.ly/MfX6u"
)
# Ensure cache directory exists
os.makedirs(self.config.cache_dir, exist_ok = True)
# Move color options
if self.config.cards_color:
# Initialize manifest
self.manifest_file = os.path.join(
self.config.cache_dir, "manifest.json"
)
# Move background color to new option
value = self.config.cards_color.get("fill")
if value:
self.config.cards_layout_options["background_color"] = value
# Load manifest if it exists and the cache should be used
if os.path.isfile(self.manifest_file) and self.config.cache:
try:
with open(self.manifest_file) as f:
self.manifest = json.load(f)
except:
pass
# Move color to new option
value = self.config.cards_color.get("text")
if value:
self.config.cards_layout_options["color"] = value
# Initialize lock for synchronizing downloading of fonts
self.lock = Lock()
# Move font family to new option
if self.config.cards_font:
value = self.config.cards_font
self.config.cards_layout_options["font_family"] = value
# Initialize card layouts and variables
self.card_layouts: dict[str, Layout] = {}
self.card_variables: dict[str, list[list[str]]] = {}
# Initialize card environment
self.card_env = Environment()
self.card_env.filters["x"] = x_filter
# Always print a warning when debug mode is active
if self.config.debug:
log.warning("Debug mode is enabled for \"social\" plugin.")
# By default, debug mode is disabled when the documentation is
# built, but not when it is served, for a better user experience
if not self.is_serve and not self.config.debug_on_build:
self.config.debug = False
# Check if site URL is defined

@@ -135,343 +178,654 @@ if not config.site_url:

# Ensure presence of cache directory
self.cache = self.config.cache_dir
if not os.path.isdir(self.cache):
os.makedirs(self.cache)
# Ensure card layouts are not copied to the site directory
def on_files(self, files, *, config):
if not self.config.enabled:
return
# Retrieve palette from theme configuration
theme = config.theme
if "palette" in theme:
palette = theme["palette"]
# We must exclude all files related to layouts from here on, so MkDocs
# doesn't copy them to the site directory when the project is built
for file in files:
# Find first palette that includes primary color definition
if isinstance(palette, list):
for p in palette:
if "primary" in p and p["primary"]:
palette = p
break
# As of MkDocs 1.6, abs_src_path is optional for generated files,
# so we need to exlude them - see https://t.ly/zRYj7
if not file.abs_src_path:
continue
# Set colors according to palette
if "primary" in palette and palette["primary"]:
primary = palette["primary"].replace(" ", "-")
self.color = colors.get(primary, self.color)
# Exclude files from layout directory
if file.abs_src_path.startswith(_templates_dirpath()):
file.inclusion = InclusionLevel.EXCLUDED
# Retrieve color overrides
options = self.config.cards_layout_options
self.color = {
"fill": options.get("background_color", self.color["fill"]),
"text": options.get("color", self.color["text"])
}
# Generate card as soon as metadata is available (run latest) - run this
# after all other plugins, so they can alter the card configuration
@event_priority(-100)
def on_page_markdown(self, markdown, *, page, config, files):
if not self.config.enabled:
return
# Retrieve logo and font
self._resized_logo_promise = self._executor.submit(self._load_resized_logo, config)
self.font = self._load_font(config)
# Skip if cards should not be generated
if self._is_excluded(page):
return
self._image_promises = []
# Resolve card layout - we also preload the layout here, so we're not
# triggering multiple concurrent loads in the worker threads
name = self._config("cards_layout", page)
self._resolve_layout(name, config)
# Create social cards
def on_page_content(self, html, page, config, files):
if not self.config.cards:
# Spawn concurrent job to generate card for page and add future to
# job dictionary, as it returns the file we need to copy later
self.card_pool_jobs[page.file.src_uri] = self.card_pool.submit(
self._generate, name, page, config
)
# Generate card metadata (run earlier) - don't run this too late, as we
# want plugins like the minify plugin to pick up the HTML we inject
@event_priority(50)
def on_post_page(self, output, *, page, config):
if not self.config.enabled:
return
# Resolve image directory
directory = self.config.cards_dir
file, _ = os.path.splitext(page.file.src_path)
# Skip if cards should not be generated
if self._is_excluded(page):
return
# Resolve path of image
path = "{}.png".format(os.path.join(
config.site_dir,
directory,
file
))
# Reconcile concurrent jobs - we need to wait for the card job to finish
# before we can copy the generated files to the output directory. If an
# exception occurred in one of the jobs, we either log it as configured
# by the user, or raise it, so the build fails.
future = self.card_pool_jobs[page.file.src_uri]
if future.exception():
e = future.exception()
if self.config.log and isinstance(e, PluginError):
log.log(self.config.log_level, e)
return
# Resolve path of image directory
directory = os.path.dirname(path)
if not os.path.isdir(directory):
os.makedirs(directory)
# Otherwise throw error
raise e
else:
file: File = future.result()
file.copy_file()
# Compute site name
site_name = config.site_name
# Resolve card layout
name = self._config("cards_layout", page)
layout, _ = self._resolve_layout(name, config)
# Compute page title and description
title = page.meta.get("title", page.title)
description = config.site_description or ""
if "description" in page.meta:
description = page.meta["description"]
# Stop if no tags are present or site URL is not set
if not layout.tags or not config.site_url:
return
# Check type of meta title - see https://t.ly/m1Us
if not isinstance(title, str):
log.error(
f"Page meta title of page '{page.file.src_uri}' must be a "
f"string, but is of type \"{type(title)}\"."
)
sys.exit(1)
# Resolve image dimensions and curate image metadata
width, height = get_size(layout)
image = {
"url": posixpath.join(config.site_url, file.url),
"type": "image/png",
"width": width,
"height": height
}
# Check type of meta description - see https://t.ly/m1Us
if not isinstance(description, str):
log.error(
f"Page meta description of '{page.file.src_uri}' must be a "
f"string, but is of type \"{type(description)}\"."
)
sys.exit(1)
# Find offset of closing head tag, so we can insert meta tags before
# it - a bit hacky, but much faster than regular expressions
at = output.find("</head>")
return "\n".join([
output[:at],
"\n".join([
f"<meta property=\"{property}\" content=\"{content}\" />"
for property, content in _replace(
layout.tags, self.card_env, config,
page = page, image = image,
layout = self._config("cards_layout_options", page),
).items() if content
]),
output[at:]
])
# Generate social card if not in cache
hash = md5("".join([
site_name,
str(title),
description
]).encode("utf-8"))
file = os.path.join(self.cache, f"{hash.hexdigest()}.png")
self._image_promises.append(self._executor.submit(
self._cache_image,
cache_path = file, dest_path = path,
render_function = lambda: self._render_card(site_name, title, description)
))
# Save manifest after build
def on_post_build(self, *, config):
if not self.config.enabled:
return
# Inject meta tags into page
meta = page.meta.get("meta", [])
page.meta["meta"] = meta + self._generate_meta(page, config)
# Save manifest if cache should be used
if self.config.cache:
with open(self.manifest_file, "w") as f:
f.write(json.dumps(self.manifest, indent = 2, sort_keys = True))
def on_post_build(self, config):
if not self.config.cards:
# Add custom layout directory to watched files
def on_serve(self, server, *, config, builder):
path = os.path.abspath(self.config.cards_layout_dir)
if os.path.isdir(path):
server.watch(path, recursive = True)
# Reconcile jobs (run latest) - all other plugins do not depend on the
# generated cards, so we can run this after all of them
@event_priority(-100)
def on_shutdown(self):
if not self.config.enabled:
return
# Check for exceptions
for promise in self._image_promises:
promise.result()
# Shutdown thread pools - if we're on Python 3.9 and above, cancel all
# pending futures that have not yet been scheduled
for pool in [self.card_layer_pool, self.card_pool]:
if sys.version_info >= (3, 9):
pool.shutdown(cancel_futures = True)
else:
pool.shutdown()
# Save manifest if cache should be used
if self.manifest and self.config.cache:
with open(self.manifest_file, "w") as f:
f.write(json.dumps(self.manifest, indent = 2, sort_keys = True))
# -------------------------------------------------------------------------
# Render image to cache (if not present), then copy from cache to site
def _cache_image(self, cache_path, dest_path, render_function):
if not os.path.isfile(cache_path):
image = render_function()
image.save(cache_path)
# Check if the given page is excluded - giving the author the option to
# include and exclude specific pages is important, as it allows to control
# which pages should generate social cards, and which shouldn't. Different
# cards can be built by using multiple instances of the plugin.
def _is_excluded(self, page: Page):
path = page.file.src_path
# Copy file from cache
copyfile(cache_path, dest_path)
# Check if card generation is disabled for the given page
if not self._config("cards", page):
return True
@functools.lru_cache(maxsize=None)
def _get_font(self, kind, size):
return ImageFont.truetype(self.font[kind], size)
# Check if page matches one of the inclusion patterns
if self.config.cards_include:
for pattern in self.config.cards_include:
if fnmatch(page.file.src_uri, pattern):
return False
# Render social card
def _render_card(self, site_name, title, description):
# Render background and logo
image = self._render_card_background((1200, 630), self.color["fill"])
image.alpha_composite(
self._resized_logo_promise.result(),
(1200 - 228, 64 - 4)
)
# Page is not included
log.debug(f"Excluding page '{path}' due to inclusion patterns")
return True
# Render site name
font = self._get_font("Bold", 36)
image.alpha_composite(
self._render_text((826, 48), font, site_name, 1, 20),
(64 + 4, 64)
)
# Check if page matches one of the exclusion patterns
for pattern in self.config.cards_exclude:
if fnmatch(page.file.src_uri, pattern):
log.debug(f"Excluding page '{path}' due to exclusion patterns")
return True
# Render page title
font = self._get_font("Bold", 92)
image.alpha_composite(
self._render_text((826, 328), font, title, 3, 30),
(64, 160)
)
# Page is not excluded
return False
# Render page description
font = self._get_font("Regular", 28)
image.alpha_composite(
self._render_text((826, 80), font, description, 2, 14),
(64 + 4, 512)
# -------------------------------------------------------------------------
# Generate card for the given page - generation of cards does not depend on
# anything else than the page content (incl. metadata) and configuration,
# which is why it is an embarrassingly parallel problem and can be solved
# by delegating the generation of each card to a thread pool
def _generate(self, name: str, page: Page, config: MkDocsConfig):
layout, variables = self._resolve_layout(name, config)
# Each card can consist of multiple layers, many of which are likely
# the same across cards (like background or logo layers). Some of the
# input values to generate a card may be dependent on author-provided
# data, e.g., the site description or card title that is sourced from
# front matter. Additionally, layouts may allow to define arbitrary
# text boxes with author-provided metadata like tags or categories.
# Thus, we generate a hash for each card, which is based on the layers
# and the values of all variables that are used to generate the card.
layers: dict[str, Layer] = {}
for layer, templates in zip(layout.layers, variables):
fingerprints = [self.config, layer]
# Compute fingerprints for each layer
for template in templates:
template = _compile(template, self.card_env)
fingerprints.append(template.render(
config = config, page = page,
layout = self._config("cards_layout_options", page)
))
# Compute digest of fingerprints
layers[_digest(fingerprints)] = layer
# Compute digest of all fingerprints - we use this value to check if
# the exact same card was already generated and cached
hash = _digest([layout, *list(layers)])
# Determine part of path we need to replace - this depends on whether
# we're using directory URLs and if the page is an index page or not
suffix = ".html"
if config.use_directory_urls and not page.is_index:
suffix = "/index.html"
# Compute path to card, which is sourced from the cache directory, and
# generate file to register it with MkDocs as soon as it was generated
path = page.file.dest_uri.replace(suffix, ".png")
file = self._path_to_file(path, config)
# Check if file hash changed, so we need to re-generate the card - if
# the hash didn't change, we can just return the existing file
prev = self.manifest.get(file.url, "")
if hash == prev and os.path.isfile(file.abs_src_path):
return file
# Check if the required dependencies for rendering are available, which
# is, at the absolute minimum, the 'pillow' package, and raise an error
# to the caller, so he can decide what to do with the error. The caller
# can treat this as a warning or an error to abort the build.
if import_errors:
# docs = os.path.relpath(config.docs_dir)
# path = os.path.relpath(page.file.abs_src_path, docs)
# raise PluginError(
# f"Couldn't render card for '{path}' in '{docs}': install "
# f"required dependencies – pip install 'mkdocs-material[imaging]'"
# )
# @todo improve formatting of error handling
raise PluginError(
"Required dependencies of \"social\" plugin not found:\n"
+ str("\n".join(map(lambda x: "- " + x, import_errors)))
+ "\n\n"
+ "--> Install with: pip install \"mkdocs-material[imaging]\""
)
if cairosvg_error:
# @todo improve formatting of error handling
raise PluginError(
"\"cairosvg\" Python module is installed, but it crashed with:\n"
+ cairosvg_error
+ "\n\n"
+ "--> Check out the troubleshooting guide: https://t.ly/MfX6u"
)
# Spawn concurrent jobs to render layers - we only need to render layers
# that we haven't already dispatched, reducing work by deduplication
for h, layer in layers.items():
sentinel = Future()
# We need to use a hack here to avoid locking the thread pool while
# we check if the layer was already dispatched. If we don't do this,
# layers might be dispatched multiple times. The trick is to use a
# sentinel value to check if the layer was already dispatched.
if sentinel == self.card_layer_pool_jobs.setdefault(h, sentinel):
self.card_layer_pool_jobs[h] = self.card_layer_pool.submit(
self._render, layer, page, config
)
# Reconcile concurrent jobs to render layers and compose card - since
# layers are rendered in parallel, we can compose the card as soon as
# all layers have been rendered. For this, we await each future to
# resolve with the image of the rendered layer.
image = Image.new(mode = "RGBA", size = get_size(layout))
for h, layer in layers.items():
image.alpha_composite(
self.card_layer_pool_jobs[h].result(),
get_offset(layer, image)
)
# If debug mode is enabled, render overlay
if self.config.debug:
image = self._render_overlay(layout, image)
# Save composed image to cache - the caller must copy the image from
# the cache, so we don't need to worry about concurrent access
os.makedirs(os.path.dirname(file.abs_src_path), exist_ok = True)
image.save(file.abs_src_path)
# Update manifest by associating file with hash
self.manifest[file.url] = hash
# Return file for generated card
return file
# Render layer - this is the core of the plugin, which renders a single
# layer of a card. Order is: background, icon, and typography.
def _render(self, layer: Layer, page: Page, config: MkDocsConfig):
image = Image.new(mode = "RGBA", size = get_size(layer))
layer = _replace(
layer, self.card_env, config,
page = page, layout = self._config("cards_layout_options", page)
)
# Return social card image
# Render background, icon, and typography
image = self._render_background(layer, image)
image = self._render_icon(layer, image, config)
image = self._render_typography(layer, image)
# Return image with layer
return image
# Render social card background
def _render_card_background(self, size, fill):
return Image.new(mode = "RGBA", size = size, color = fill)
# Render layer background
def _render_background(self, layer: Layer, input: _Image):
background = layer.background
@functools.lru_cache(maxsize=None)
def _tmp_context(self):
image = Image.new(mode = "RGBA", size = (50, 50))
return ImageDraw.Draw(image)
# If given, load background image and resize it proportionally to cover
# the entire area while retaining the aspect ratio of the input image
if background.image:
if not os.path.isfile(background.image):
raise PluginError(f"Couldn't find image '{background.image}'")
@functools.lru_cache(maxsize=None)
def _text_bounding_box(self, text, font):
return self._tmp_context().textbbox((0, 0), text, font = font)
# Open file and convert SVGs to PNGs
with open(background.image, "rb") as f:
data = f.read()
if background.image.endswith(".svg"):
data = svg2png(data, output_width = input.width)
# Render social card text
def _render_text(self, size, font, text, lmax, spacing = 0):
width = size[0]
lines, words = [], []
# Resize image to cover entire area
image = Image.open(BytesIO(data)).convert("RGBA")
input.alpha_composite(_resize_cover(image, input))
# Remove remnant HTML tags and convert HTML entities
text = re.sub(r"(<[^>]+>)", "", text)
text = unescape(text)
# If given, fill background color - this is done after the image is
# loaded to allow for transparent tints. How awesome is that?
if background.color:
color = background.color
if color == "transparent":
return input
# Retrieve y-offset of textbox to correct for spacing
yoffset = 0
# Create image filled with background color
image = Image.new(mode = "RGBA", size = input.size, color = color)
input.alpha_composite(image)
# Create drawing context and split text into lines
for word in text.split(" "):
combine = " ".join(words + [word])
textbox = self._text_bounding_box(combine, font = font)
yoffset = textbox[1]
if not words or textbox[2] <= width:
words.append(word)
# Return image with background
return input
# Render layer icon
def _render_icon(self, layer: Layer, input: _Image, config: MkDocsConfig):
icon = layer.icon
if not icon.value:
return input
# Resolve icon by searching all configured theme directories and apply
# the fill color before rendering, if given. Note that the fill color
# must be converted to rgba() function syntax, or opacity will not work
# correctly. This way, we don't need to use the fill-opacity property.
data = self._resolve_icon(icon.value, config)
if icon.color:
(r, g, b, *a) = ImageColor.getrgb(icon.color)
opacity = a[0] / 255 if a else 1
# Compute and replace fill color
fill = f"rgba({r}, {g}, {b}, {opacity})"
data = data.replace("<svg", f"<svg fill=\"{fill}\"")
# Rasterize vector image given by icon to match the size of the
# input image, resize it and render it on top of the input image
image = Image.open(BytesIO(
svg2png(data.encode("utf-8"), output_width = input.width)
))
input.alpha_composite(_resize_contain(image.convert("RGBA"), input))
# Return image with icon
return input
# Render layer typography
def _render_typography(self, layer: Layer, input: _Image):
typography = layer.typography
if not typography.content:
return input
# Retrieve font family and font style
family = typography.font.family
variant = typography.font.variant
style = typography.font.style
# Resolve and load font and compute metrics
path = self._resolve_font(family, style, variant)
current, spacing = _metrics(path, typography.line, input)
font = ImageFont.truetype(path, current)
# Create image and initialize drawing context
image = Image.new(mode = "RGBA", size = input.size)
context = ImageDraw.Draw(image)
# Compute length of whitespace and ellipsis - in the next step, we will
# distribute the words across the lines we have available, which means
# we need to compute the length of each word and intersperse it with
# whitespace. Note that lengths of words are perfectly additive, so we
# can compute the length of a line by adding the lengths of all words
# and the whitespace between them.
space = context.textlength(" ", font = font)
ellipsis = context.textlength("...", font = font)
# Initialize lists to hold the lengths of words and indexes of lines.
# Tracking line indexes allows us to improve splitting using heuristics.
lengths: list[int] = []
indexes, current = [0], 0
# Split words at whitespace, and successively add words to the current
# line. For every other than the first word, account for the whitespace
# between words. If the next word would exceed the width of the input
# image, and thus overflow the line, start a new one.
words = re.split(r"\s+", unescape(typography.content))
for word in words:
length = context.textlength(word, font = font)
lengths.append(length)
# Start new line if current line overflows
whitespace = space if current else 0
if current + whitespace + length > input.width:
indexes.append(len(lengths) - 1)
current = length
# Add word to current line
else:
lines.append(words)
words = [word]
current += whitespace + length
# Join words for each line and create image
lines.append(words)
lines = [" ".join(line) for line in lines]
image = Image.new(mode = "RGBA", size = size)
# Add terminating index, if not already present
if len(lengths) != indexes[-1]:
indexes.append(len(lengths))
# Create drawing context and split text into lines
context = ImageDraw.Draw(image)
# If the number of lines exceeds the maximum amount we are able to
# render, either shrink or truncate the text and add an ellipsis
amount = typography.line.amount
if amount < len(indexes) - 1:
# If overflow mode is set to 'shrink', decrease the font size and
# try to render the typography again to see if it fits
overflow = typography.overflow
if overflow == "shrink":
typography.line.amount += 1
# Render layer with new typography metrics by calling this
# function recursively and returning immediately from it
return self._render_typography(layer, input)
# Determine last and penultimate line indexes
indexes = indexes[:amount + 1]
p, q = indexes[-2:]
# Compute the length of the last line, and check whether we can add
# the ellipsis after the last word. If not, replace the last word.
current = sum(lengths[p:q]) + (q - p) * space
if current + ellipsis < input.width:
q += 1
# Update line indexes and replace word with ellipsis
indexes[-1] = q
words[q - 1] = "..."
# If there are exactly two lines, check if we can improve splitting by
# moving the last word of the first line to the last line
elif len(indexes) == 3:
p, q, r = indexes[-3:]
# Create two configurations of lines, one with the last word of the
# first line moved to the last line, and one without the change
a = [len(" ".join(l)) for l in [words[p:q], words[q:r]]]
b = [len(" ".join(l)) for l in [words[p:q - 1], words[q - 1:r]]]
# Compute standard deviation of line lengths before and after the
# change, and if the standard deviation decreases, move the word
if stdev(b) < stdev(a):
indexes[-2] -= 1
# Compute anchor and deduce alignment, as well as offset. The anchor
# is computed as a string of two characters, where the first character
# denotes the horizontal alignment and the second character denotes
# the vertical alignment.
anchor = _anchor(typography.align)
# Compute horizontal alignment
if anchor[0] == "l": align, x = "left", 0
elif anchor[0] == "m": align, x = "center", input.width >> 1
else: align, x = "right", input.width >> 0
# Compute vertical alignment
if anchor[1] == "a": y = 0
elif anchor[1] == "m": y = input.height >> 1
else: y = input.height >> 0
# Join words with whitespace and lines with line breaks
text = "\n".join([
" ".join(words[p:q])
for p, q in zip(indexes, indexes[1:])
])
# Draw text onto image
context.text(
(0, spacing / 2 - yoffset), "\n".join(lines[:lmax]),
font = font, fill = self.color["text"], spacing = spacing - yoffset
(x, y), text,
font = font,
anchor = anchor,
spacing = spacing,
fill = typography.color,
align = align
)
# Return text image
return image
# Return image with typography
input.alpha_composite(image)
return input
# -------------------------------------------------------------------------
# Render overlay for debugging
def _render_overlay(self, layout: Layout, input: _Image):
path = self._resolve_font("Roboto", "Regular")
font = ImageFont.truetype(path, 12)
# Generate meta tags
def _generate_meta(self, page, config):
directory = self.config.cards_dir
file, _ = os.path.splitext(page.file.src_uri)
# Create image and initialize drawing context
image = Image.new(mode = "RGBA", size = input.size)
context = ImageDraw.Draw(image)
# Compute page title
if page.is_homepage:
title = config.site_name
else:
page_title = page.meta.get("title", page.title)
title = f"{page_title} - {config.site_name}"
# Draw overlay grid
fill = self.config.debug_color
if self.config.debug_grid:
step = self.config.debug_grid_step
for i in range(0, input.width, step):
for j in range(0, input.height, step):
context.ellipse(
((i - 1, j - 1), (i + 1, j + 1)),
fill = fill
)
# Compute page description
description = config.site_description
if "description" in page.meta:
description = page.meta["description"]
# Compute luminosity of debug color and use it to determine the color
# of the text that will be drawn on top of the debug color
(r, g, b, *_) = ImageColor.getrgb(fill)
color = "black" if r * 0.299 + g * 0.587 + b * 0.114 > 150 else "white"
# Resolve image URL
url = "{}.png".format(posixpath.join(
config.site_url or ".",
directory,
file
))
# Draw overlay outline for each layer
for i, layer in enumerate(layout.layers):
x, y = get_offset(layer, image)
w, h = get_size(layer)
# Ensure forward slashes
url = url.replace(os.path.sep, "/")
# Draw overlay outline
context.rectangle(outline = fill, xy = (x, y,
min(x + w, input.width - 1),
min(y + h, input.height - 1)
))
# Return meta tags
return [
# Assemble text and compute its width and height - we only use the
# coordinates denoting the width and height of the text, as we need
# to compute the coordinates of the text box manually in order to
# have the rectangle align perfectly with the outline
text = f"{i} – {x}, {y}"
(_, _, x1, y1) = context.textbbox((x, y), text, font = font)
# Meta tags for Open Graph
{ "property": "og:type", "content": "website" },
{ "property": "og:title", "content": title },
{ "property": "og:description", "content": description },
{ "property": "og:image", "content": url },
{ "property": "og:image:type", "content": "image/png" },
{ "property": "og:image:width", "content": "1200" },
{ "property": "og:image:height", "content": "630" },
{ "property": "og:url", "content": page.canonical_url },
# Draw text on a small rectangle in the top left corner of the
# layer denoting the number of the layer and its offset
context.rectangle(fill = fill, xy = (x, y, x1 + 8, y1 + 4))
context.text((x + 4, y + 2), text, font = font, fill = color)
# Meta tags for Twitter
{ "name": "twitter:card", "content": "summary_large_image" },
# { "name": "twitter:site", "content": user },
# { "name": "twitter:creator", "content": user },
{ "name": "twitter:title", "content": title },
{ "name": "twitter:description", "content": description },
{ "name": "twitter:image", "content": url }
]
# Return image with overlay
input.alpha_composite(image)
return input
def _load_resized_logo(self, config, width = 144):
logo = self._load_logo(config)
height = int(width * logo.height / logo.width)
return logo.resize((width, height))
# -------------------------------------------------------------------------
# Retrieve logo image or icon
def _load_logo(self, config):
theme = config.theme
# Resolve layout - authors can specify a custom directory for layouts in
# the configuration, which is checked prior to the layout directory shipped
# with this plugin. If the layout cannot be resolved in any of the known
# directories, the plugin must abort with an error.
def _resolve_layout(self, name: str, config: MkDocsConfig):
name, _ = os.path.splitext(name)
if name in self.card_layouts:
return self.card_layouts[name], self.card_variables[name]
# Handle images (precedence over icons)
if "logo" in theme:
_, extension = os.path.splitext(theme["logo"])
# If the author specified a custom directory, try to resolve the layout
# from this directory first, otherwise fall back to the default
for base in [
os.path.relpath(self.config.cards_layout_dir),
_templates_dirpath()
]:
path = os.path.join(base, f"{name}.yml")
path = os.path.normpath(path)
path = os.path.join(config.docs_dir, theme["logo"])
# Skip if layout does not exist and try next directory
if not os.path.isfile(path):
continue
# Allow users to put the logo inside their custom_dir (theme["logo"] case)
if theme.custom_dir:
custom_dir_logo = os.path.join(theme.custom_dir, theme["logo"])
if os.path.exists(custom_dir_logo):
path = custom_dir_logo
# Open file and parse as YAML
with open(path, encoding = "utf-8-sig") as f:
layout: Layout = Layout(config_file_path = path)
try:
layout.load_dict(yaml.load(f, SafeLoader) or {})
# Load SVG and convert to PNG
if extension == ".svg":
return self._load_logo_svg(path)
# The layout could not be loaded because of a syntax error,
# which we display to the author with a nice error message
except Exception as e:
path = os.path.relpath(path, base)
raise PluginError(
f"Error reading layout file '{path}' in '{base}':\n"
f"{e}"
)
# Load PNG, JPEG, etc.
return Image.open(path).convert("RGBA")
# Validate layout and abort if errors occurred
errors, warnings = layout.validate()
for _, w in warnings:
log.warning(w)
for _, e in errors:
path = os.path.relpath(path, base)
raise PluginError(
f"Error reading layout file '{path}' in '{base}':\n"
f"{e}"
)
# Handle icons
icon = theme.get("icon") or {}
if "logo" in icon and icon["logo"]:
logo = icon["logo"]
else:
logo = "material/library"
# Store layout and variables
self.card_layouts[name] = layout
self.card_variables[name] = []
# Resolve path of package
base = os.path.abspath(os.path.join(
os.path.dirname(__file__),
"../.."
))
# Extract variables for each layer from layout
for layer in layout.layers:
variables = _extract(layer, self.card_env, config)
self.card_variables[name].append(variables)
path = f"{base}/templates/.icons/{logo}.svg"
# Set default values for for layer size, if not given
for key, value in layer.size.items():
if value == 0:
layer.size[key] = layout.size[key]
# Allow users to put the logo inside their custom_dir (theme["icon"]["logo"] case)
if theme.custom_dir:
custom_dir_logo = os.path.join(theme.custom_dir, ".icons", f"{logo}.svg")
if os.path.exists(custom_dir_logo):
path = custom_dir_logo
# Abort, since we're done
break
# Load icon data and fill with color
return self._load_logo_svg(path, self.color["text"])
# Abort if the layout could not be resolved
if name not in self.card_layouts:
raise PluginError(f"Couldn't find layout '{name}'")
# Load SVG file and convert to PNG
def _load_logo_svg(self, path, fill = None):
file = BytesIO()
data = open(path).read()
# Return layout and variables
return self.card_layouts[name], self.card_variables[name]
# Fill with color, if given
if fill:
data = data.replace("<svg", f"<svg fill=\"{fill}\"")
# Resolve icon with given name - this function searches for the icon in all
# known theme directories, including custom directories specified by the
# author, which allows for using custom icons in cards. If the icon cannot
# be resolved, the plugin must abort with an error.
def _resolve_icon(self, name: str, config: MkDocsConfig):
for base in config.theme.dirs:
path = os.path.join(base, ".icons", f"{name}.svg")
path = os.path.normpath(path)
# Convert to PNG and return image
svg2png(bytestring = data.encode("utf-8"), write_to = file, scale = 10)
return Image.open(file)
# Skip if icon does not exist and try next directory
if not os.path.isfile(path):
continue
# Retrieve font either from the card layout option or from the Material
# font defintion. If no font is defined for Material or font is False
# then choose a default.
def _load_font(self, config):
name = self.config.cards_layout_options.get("font_family")
if not name:
material_name = config.theme.get("font", False)
if material_name is False:
name = "Roboto"
else:
name = material_name.get("text", "Roboto")
# Open and return icon
with open(path, encoding = "utf-8") as f:
return f.read()
# Resolve relevant fonts
font = {}
for style in ["Regular", "Bold"]:
font[style] = self._resolve_font(name, style)
# Abort if the icon could not be resolved
raise PluginError(f"Couldn't find icon '{name}'")
# Return available font weights with fallback
return defaultdict(lambda: font["Regular"], font)
# Resolve font family with specific style - if we haven't already done it,

@@ -481,9 +835,20 @@ # the font family is first downloaded from Google Fonts and the styles are

# must abort with an error.
def _resolve_font(self, family: str, style: str):
def _resolve_font(self, family: str, style: str, variant = ""):
path = os.path.join(self.config.cache_dir, "fonts", family)
# Fetch font family, if it hasn't been fetched yet
# Fetch font family, if it hasn't been fetched yet - we use a lock to
# synchronize access, so the font is not downloaded multiple times, but
# all other threads wait for the font being available. This is also why
# we need the double path check, which makes sure that we only use the
# lock when we actually need to download a font that doesn't exist. If
# we already downloaded it, we don't want to block at all.
if not os.path.isdir(path):
self._fetch_font_from_google_fonts(family)
with self.lock:
if not os.path.isdir(path):
self._fetch_font_from_google_fonts(family)
# Assemble fully qualified style - see https://t.ly/soDF0
if variant:
style = f"{variant} {style}"
# Check for availability of font style

@@ -517,2 +882,4 @@ list = sorted(os.listdir(path))

# -------------------------------------------------------------------------
# Fetch font family from Google Fonts

@@ -543,16 +910,221 @@ def _fetch_font_from_google_fonts(self, family: str):

# Extract font family name and style using the content in the
# response via ByteIO to avoid writing a temp file. Done to fix
# problems with passing a NamedTemporaryFile to
# ImageFont.truetype() on Windows, see https://t.ly/LiF_k
with BytesIO(res.content) as fontdata:
font = ImageFont.truetype(fontdata)
name, style = font.getname()
name = " ".join([name.replace(family, ""), style]).strip()
target = os.path.join(path, family, f"{name}.ttf")
# Construct image font for analysis by directly reading the
# contents from the response without priorily writing to a
# temporary file (like we did before), as this might lead to
# problems on Windows machines, see https://t.ly/LiF_k
with BytesIO(res.content) as f:
font = ImageFont.truetype(f)
# write file to cache
# Extract font family name and style
name, style = font.getname()
name = " ".join([name.replace(family, ""), style]).strip()
# Write file to cache directory
target = os.path.join(path, family, f"{name}.ttf")
write_file(res.content, target)
# -------------------------------------------------------------------------
# Retrieve configuration value - each page can override certain parts of
# the site configuration, depending on the type and structure of the value
def _config(self, name: str, page: Page):
meta = page.meta.get("social", {})
# Primitive values: choose page- over site-level configuration
if isinstance(self.config[name], (bool, str, int, float)):
return meta.get(name, self.config[name])
# Dictionary values: merge site- with page-level configuration
if isinstance(self.config[name], (dict)):
return { **self.config[name], **meta.get(name, {}) }
# Create a file for the given path
def _path_to_file(self, path: str, config: MkDocsConfig):
assert path.endswith(".png")
return File(
posixpath.join(self.config.cards_dir, path),
self.config.cache_dir,
config.site_dir,
False
)
# -----------------------------------------------------------------------------
# Helper functions
# -----------------------------------------------------------------------------
# Compute a stable hash from an object - since we're doing compositing, we can
# leverage caching to omit re-generating layers when their parameters stay the
# same. Additionally, we can identify identical layers between images, e.g.,
# background, logos, or avatars, but also unchanged text. Note that we need to
# convert the data to a string prior to hashing, because configuration objects
# are inherently unstable, always resulting in new hashes.
def _digest(data: object):
return sha1(pickle.dumps(str(data))).hexdigest()
# -----------------------------------------------------------------------------
# Extract all variables recursively
def _extract(data: any, env: Environment, config: MkDocsConfig):
# Traverse configuration or dictionary
if isinstance(data, (Config, dict)):
return [
variable for value in data.values()
for variable in _extract(value, env, config)
]
# Traverse list
elif isinstance(data, list):
return [
variable for value in data
for variable in _extract(value, env, config)
]
# Retrieve variables from string
elif isinstance(data, str):
if find_undeclared_variables(env.parse(data)):
return [data]
# Return nothing
return []
# Replace all variables recursively and return a copy of the given data
def _replace(data: any, env: Environment, config: MkDocsConfig, **kwargs):
# Traverse configuration or dictionary
if isinstance(data, (Config, dict)):
data = copy(data)
for key, value in data.items():
data[key] = _replace(value, env, config, **kwargs)
# Traverse list
elif isinstance(data, list):
return [
_replace(value, env, config, **kwargs)
for value in data
]
# Retrieve variables from string
elif isinstance(data, str):
return _compile(data, env).render(
config = config, **kwargs
) or None
# Return data
return data
# Compile template and cache it indefinitely
@functools.lru_cache(maxsize = None)
def _compile(data: str, env: Environment):
return env.from_string(html.unescape(data))
# Compute absolute path to internal templates directory,
# we need to do it this way to assure compatibility with Python 3.8,
# and also to allow users to install their Python site-packages
# to a different mount root than their documentation - see https://t.ly/GMeYP
def _templates_dirpath():
return os.path.join(os.path.dirname(os.path.abspath(__file__)), "templates")
# -----------------------------------------------------------------------------
# Resize image to match the size of the reference image and align it to the
# center of the reference image so that it is fully covered
def _resize_cover(image: _Image, ref: _Image):
ratio = max(
ref.width / image.width,
ref.height / image.height
)
# Compute aspect ratios of both images and choose the larger one, then
# resize the image so that it covers the entire reference image
image = image.resize((
int(image.width * ratio),
int(image.height * ratio)
))
# Align image to the center of the reference image - we also need to crop
# the image if it's larger than the given reference image
return image.crop((
image.width - ref.width >> 1,
image.height - ref.height >> 1,
image.width + ref.width >> 1,
image.height + ref.height >> 1
))
# Resize image to match the size of the reference image and align it to the
# center of the reference image so that it is fully contained
def _resize_contain(image: _Image, ref: _Image):
ratio = min(
ref.width / image.width,
ref.height / image.height
)
# Resize image according to minimum ratio
image = image.resize((
int(image.width * ratio),
int(image.height * ratio)
))
# Create a blank image and paste the resized image into it
blank = Image.new(mode = "RGBA", size = ref.size)
blank.paste(image, (
ref.width - image.width >> 1,
ref.height - image.height >> 1
))
# Return resized image
return blank
# -----------------------------------------------------------------------------
# Resolve font metrics for given truetype font - this function computes the
# font size and spacing between lines based on the number of lines and height.
# In order to omit rounding errors, we compute the ascender and descender based
# on a font size of 1,000.
def _metrics(path: str, line: Line, ref: _Image):
font = ImageFont.truetype(path, 1000)
ascender, descender = font.getmetrics()
# It would be too complex to let the author define the font size, since this
# would involve a lot of fiddling to find the right value. Instead, we let
# the author define the number of lines and the line height, and we compute
# the font size from that. This is much more intuitive. As a basis, we use
# the ascender as the actual line height and also add the descender to
# account for the last line. It's no secret that correctly handling font
# metrics is super tricky - see https://bit.ly/31u9bh6
extent = line.amount * ascender + 1 * descender
# Now, we still need to account for spacing between lines, which is why we
# take the number of lines - 1, and multiply that with the line height we
# computed from the ascender. We add this to the extent we computed before,
# which we use as a basis for the final font size.
extent += (line.amount - 1) * (line.height - 1) * ascender
size = (1000 * ref.height) / extent
# From this, we can compute the spacing between lines, and we're done. We
# then return both, the font size and spacing between lines.
spacing = (line.height - 1) * ascender * size / 1000
return int(size), spacing
# Compute anchor, determining the alignment of text relative to the given
# coordinates, with the default being "top left" - see https://bit.ly/3NEfr07
def _anchor(data: str):
axis = re.split(r"\s+", data)
# Determine anchor on x-axis
if "start" in axis: anchor = "l"
elif "end" in axis: anchor = "r"
elif "center" in axis: anchor = "m"
else: anchor = "l"
# Determine anchor on y-axis
if "top" in axis: anchor += "a"
elif "bottom" in axis: anchor += "d"
elif "center" in axis: anchor += "m"
else: anchor += "a"
# Return anchor
return anchor
# -----------------------------------------------------------------------------
# Data

@@ -562,28 +1134,2 @@ # -----------------------------------------------------------------------------

# Set up logging
log = logging.getLogger("mkdocs")
log.addFilter(DuplicateFilter())
# Color palette
colors = {
"red": { "fill": "#ef5552", "text": "#ffffff" },
"pink": { "fill": "#e92063", "text": "#ffffff" },
"purple": { "fill": "#ab47bd", "text": "#ffffff" },
"deep-purple": { "fill": "#7e56c2", "text": "#ffffff" },
"indigo": { "fill": "#4051b5", "text": "#ffffff" },
"blue": { "fill": "#2094f3", "text": "#ffffff" },
"light-blue": { "fill": "#02a6f2", "text": "#ffffff" },
"cyan": { "fill": "#00bdd6", "text": "#ffffff" },
"teal": { "fill": "#009485", "text": "#ffffff" },
"green": { "fill": "#4cae4f", "text": "#ffffff" },
"light-green": { "fill": "#8bc34b", "text": "#ffffff" },
"lime": { "fill": "#cbdc38", "text": "#000000" },
"yellow": { "fill": "#ffec3d", "text": "#000000" },
"amber": { "fill": "#ffc105", "text": "#000000" },
"orange": { "fill": "#ffa724", "text": "#000000" },
"deep-orange": { "fill": "#ff6e42", "text": "#ffffff" },
"brown": { "fill": "#795649", "text": "#ffffff" },
"grey": { "fill": "#757575", "text": "#ffffff" },
"blue-grey": { "fill": "#546d78", "text": "#ffffff" },
"black": { "fill": "#000000", "text": "#ffffff" },
"white": { "fill": "#ffffff", "text": "#000000" }
}
log = logging.getLogger("mkdocs.material.social")

@@ -49,2 +49,4 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

tags_slugify_format = Type(str, default = "tag:{slug}")
tags_hierarchy = Type(bool, default = False)
tags_hierarchy_separator = Type(str, default = "/")
tags_sort_by = Type(Callable, default = tag_name)

@@ -65,3 +67,16 @@ tags_sort_reverse = Type(bool, default = False)

listings_layout = Type(str, default = "default")
listings_toc = Type(bool, default = True)
# Settings for shadow tags
shadow = Type(bool, default = False)
shadow_on_serve = Type(bool, default = True)
shadow_tags = TagSet()
shadow_tags_prefix = Type(str, default = "")
shadow_tags_suffix = Type(str, default = "")
# Settings for export
export = Type(bool, default = True)
export_file = Type(str, default = "tags.json")
export_only = Type(bool, default = False)
# Deprecated settings

@@ -72,5 +87,5 @@ tags_compare = Deprecated(moved_to = "tags_sort_by")

tags_pages_compare_reverse = Deprecated(moved_to = "listings_sort_reverse")
tags_file = Deprecated(
option_type = Type(str),
message = "This setting is not required anymore"
tags_file = Deprecated(option_type = Type(str))
tags_extra_files = Deprecated(
option_type = DictOfItems(ListOfItems(Type(str)), default = {})
)

@@ -39,2 +39,3 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

from .structure.mapping.manager import MappingManager
from .structure.mapping.storage import MappingStorage

@@ -48,2 +49,7 @@ # -----------------------------------------------------------------------------

A tags plugin.
This plugin collects tags from the front matter of pages, and builds a tag
structure from them. The tag structure can be used to render listings on
pages, or to just create a site-wide tags index and export all tags and
mappings to a JSON file for consumption in another project.
"""

@@ -128,2 +134,13 @@

# If the author only wants to extract and export mappings, we allow to
# disable the rendering of all tags and listings with a single setting
if self.config.export_only:
self.config.tags = False
self.config.listings = False
# By default, shadow tags are rendered when the documentation is served,
# but not when it is built, for a better user experience
if self.is_serve and self.config.shadow_on_serve:
self.config.shadow = True
@event_priority(-50)

@@ -157,2 +174,6 @@ def on_page_markdown(

# Handle deprecation of `tags_extra_files` setting
if self.config.tags_extra_files:
markdown = self._handle_deprecated_tags_extra_files(page, markdown)
# Collect tags from page

@@ -193,2 +214,11 @@ try:

# Export mappings to file, if enabled
if self.config.export:
path = os.path.join(config.site_dir, self.config.export_file)
path = os.path.normpath(path)
# Serialize mappings and save to file
storage = MappingStorage(self.config)
storage.save(path, self.mappings)
def on_page_context(

@@ -251,2 +281,34 @@ self, context: TemplateContext, *, page: Page, **kwargs

def _handle_deprecated_tags_extra_files(
self, page: Page, markdown: str
) -> str:
"""
Handle deprecation of `tags_extra_files` setting.
Arguments:
page: The page.
"""
directive = self.config.listings_directive
if page.file.src_uri not in self.config.tags_extra_files:
return markdown
# Compute tags to render on page
tags = self.config.tags_extra_files[page.file.src_uri]
if tags:
directive += f" {{ include: [{', '.join(tags)}] }}"
# Try to find the legacy tags marker and replace with directive
if "[TAGS]" in markdown:
markdown = markdown.replace(
"[TAGS]", f"<!-- {directive} -->"
)
# Try to find the directive and add it if not present
pattern = r"<!--\s+{directive}".format(directive = re.escape(directive))
if not re.search(pattern, markdown):
markdown += f"\n<!-- {directive} -->"
# Return markdown
return markdown
# -----------------------------------------------------------------------------

@@ -253,0 +315,0 @@ # Data

@@ -195,2 +195,7 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

Mappings are only added to listings, if the listing features tags that
are also featured in the mapping. The caller can decide whether hidden
tags should be rendered or not, e.g., automatically set by the plugin
when shadow tags are disabled.
Arguments:

@@ -197,0 +202,0 @@ mapping: The mapping.

@@ -47,2 +47,10 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

shadow = Optional(Type(bool))
"""
Whether to include shadow tags.
This setting allows to override the global setting for shadow tags. If this
setting is not specified, the global `shadow` setting is used.
"""
layout = Optional(Type(str))

@@ -56,2 +64,10 @@ """

toc = Optional(Type(bool))
"""
Whether to populate the table of contents with anchor links to tags.
This setting allows to override the global setting for the layout. If this
setting is not specified, the global `listings_toc` setting is used.
"""
include = TagSet()

@@ -58,0 +74,0 @@ """

@@ -246,5 +246,5 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

# Add mappings to listing
# Add mappings to listing, passing shadow tags configuration
for mapping in mappings:
listing.add(mapping)
listing.add(mapping, hidden = listing.config.shadow)

@@ -380,2 +380,6 @@ # Sort listings and tags - we can only do this after all mappings have

# Inherit shadow tags configuration, unless explicitly set
if not isinstance(config.shadow, bool):
config.shadow = self.config.shadow
# Inherit layout configuration, unless explicitly set

@@ -385,2 +389,6 @@ if not isinstance(config.layout, str):

# Inherit table of contents configuration, unless explicitly set
if not isinstance(config.toc, bool):
config.toc = self.config.listings_toc
# Return listing configuration

@@ -395,2 +403,7 @@ return config

If the tag hierarchy setting is enabled, the tag is expanded into a
hierarchy of tags, all of which are then slugified and joined with the
configured separator. Otherwise, the tag is slugified directly. This is
necessary to keep the tag hierarchy in the slug.
Arguments:

@@ -402,7 +415,14 @@ tag: The tag.

"""
slugify = self.config.tags_slugify
tags = [tag.name]
# Compute tag hierarchy, if configured
hierarchy = self.config.tags_hierarchy_separator
if self.config.tags_hierarchy:
tags = tag.name.split(hierarchy)
# Slugify tag hierarchy and join with separator
separator = self.config.tags_slugify_separator
return self.config.tags_slugify_format.format(
slug = self.config.tags_slugify(
tag.name,
self.config.tags_slugify_separator
)
slug = hierarchy.join(slugify(name, separator) for name in tags)
)

@@ -409,0 +429,0 @@

@@ -84,3 +84,6 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

children = [anchors[tag] for tag in anchors if not tag.parent]
host.children[at:at + 1] = children
if listing.config.toc:
host.children[at:at + 1] = children
else:
host.children.pop(at)

@@ -87,0 +90,0 @@ # Return mapping of tags to anchor links

@@ -37,2 +37,7 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

Listing trees are a tree structure that represent the hierarchy of tags
and mappings. Each tree node is a tag, and each tag can have multiple
mappings. Additionally, each tree can have subtrees, which are typically
called nested tags.
This is an internal data structure that is used to render listings. It is

@@ -39,0 +44,0 @@ also the immediate structure that is passed to the template.

@@ -26,2 +26,3 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

from material.plugins.tags.structure.mapping import Mapping
from material.plugins.tags.structure.tag import Tag
from material.plugins.tags.structure.tag.options import TagSet

@@ -129,3 +130,3 @@ from mkdocs.structure.pages import Page

for tag in self.format.validate(page.meta[tags]):
mapping.tags.add(tag)
mapping.tags.add(self._configure(tag))

@@ -148,2 +149,86 @@ # Return mapping

# -------------------------------------------------------------------------
def _configure(self, tag: Tag) -> Tag:
"""
Configure tag.
This method is called by the mapping manager to configure a tag for the
the tag structure. Depending on the configuration, the tag is expanded
into a hierarchy of tags, and can be marked as hidden if it is a shadow
tag, hiding it from mappings and listings when rendering.
Arguments:
tag: The tag.
Returns:
The configured tag.
"""
if self.config.tags_hierarchy:
return self._configure_hierarchy(tag)
else:
return self._configure_shadow(tag, tag.name)
def _configure_hierarchy(self, tag: Tag) -> Tag:
"""
Configure hierarchical tag.
Note that shadow tags that occur as part of a tag hierarchy propagate
their hidden state to all of their children.
Arguments:
tag: The tag.
Returns:
The configured tag.
"""
separator = self.config.tags_hierarchy_separator
root, *rest = tag.name.split(separator)
# Create tag root and hierarchy
tag = self._configure_shadow(Tag(root), root)
for name in rest:
tag = self._configure_shadow(Tag(
separator.join([tag.name, name]),
parent = tag, hidden = tag.hidden
), name)
# Return tag
return tag
def _configure_shadow(self, tag: Tag, name: str) -> Tag:
"""
Configure shadow tag.
Regardless of the configuration, tags are always marked as hidden if
they're classified as shadow tags, e.g., if their name matches the
configured shadow prefix or suffix, or if they're part of the list of
shadow tags. Whether they're displayed is decided before rendering.
The tag name must be passed separately, as it may be different from the
tag's name, e.g., when creating a tag hierarchy. In this case, the name
represents the part that was added to the tag, essentially the suffix.
The name is checked for shadow prefixes and suffixes.
Arguments:
tag: The tag.
name: The tag name.
Returns:
The configured tag.
"""
if not tag.hidden:
tag.hidden = tag in self.config.shadow_tags
# Check if tag matches shadow prefix, if defined
if not tag.hidden and self.config.shadow_tags_prefix:
tag.hidden = name.startswith(self.config.shadow_tags_prefix)
# Check if tag matches shadow suffix, if defined
if not tag.hidden and self.config.shadow_tags_suffix:
tag.hidden = name.endswith(self.config.shadow_tags_suffix)
# Return tag
return tag
# -----------------------------------------------------------------------------

@@ -150,0 +235,0 @@ # Functions

@@ -34,2 +34,31 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

A tag.
Tags can be used to categorize pages and group them into a tag structure. A
tag is a simple string, which can be split into a hierarchy of tags by using
the character or string as defined in the `hierarchy_separator` setting in
`mkdocs.yml`. Each parent tag contains their child tags.
Example:
```yaml
tags:
- foo/bar
- foo/baz
- qux
```
The tag structure for the above example would look like this:
```
.
├─ foo
│ ├─ bar
│ └─ baz
└─ qux
```
Note that this class does not split the tag name into a hierarchy of tags
by itself, but rather provides a simple interface to iterate over the tag
and its parents. Splitting is left to the caller, in order to allow for
changing the separator in `mkdocs.yml`.
"""

@@ -36,0 +65,0 @@

@@ -30,2 +30,7 @@ {#-

{% endif %}
{% if config.extra.alternate is iterable %}
{% for alt in config.extra.alternate %}
<link rel="alternate" href="{{ alt.link | url }}" hreflang="{{ alt.lang | d(lang.t('language')) }}">
{% endfor %}
{% endif %}
{% if "rss" in config.plugins %}

@@ -36,3 +41,3 @@ <link rel="alternate" type="application/rss+xml" title="{{ lang.t('rss.created') }}" href="{{ 'feed_rss_created.xml' | url }}">

<link rel="icon" href="{{ config.theme.favicon | url }}">
<meta name="generator" content="mkdocs-{{ mkdocs_version }}, mkdocs-material-9.6.23">
<meta name="generator" content="mkdocs-{{ mkdocs_version }}, mkdocs-material-9.7.0">
{% endblock %}

@@ -49,6 +54,6 @@ {% block htmltitle %}

{% block styles %}
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.84d31ad4.min.css' | url }}">
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.618322db.min.css' | url }}">
{% if config.theme.palette %}
{% set palette = config.theme.palette %}
<link rel="stylesheet" href="{{ 'assets/stylesheets/palette.06af60db.min.css' | url }}">
<link rel="stylesheet" href="{{ 'assets/stylesheets/palette.ab4e12ef.min.css' | url }}">
{% endif %}

@@ -81,7 +86,2 @@ {% include "partials/icons.html" %}

{% endblock %}
{% if page.meta and page.meta.meta %}
{% for tag in page.meta.meta %}
<meta {% for key, value in tag | items %} {{ key }}="{{value}}" {% endfor %}>
{% endfor %}
{% endif %}
{% block extrahead %}{% endblock %}

@@ -186,2 +186,5 @@ </head>

<div class="md-content" data-md-component="content">
{% if "navigation.path" in features %}
{% include "partials/path.html" %}
{% endif %}
<article class="md-content__inner md-typeset">

@@ -223,2 +226,3 @@ {% block content %}

{% set _ = namespace() %}
{% set _.annotate = config.extra.annotate %}
{% set _.tags = config.extra.tags %}

@@ -247,3 +251,4 @@ {%- if config.extra.version -%}

},
"search": "assets/javascripts/workers/search.973d3a69.min.js" | url,
"search": "assets/javascripts/workers/search.7a47a382.min.js" | url,
"annotate": _.annotate or none,
"tags": _.tags or none,

@@ -255,3 +260,3 @@ "version": _.version or none

{% block scripts %}
<script src="{{ 'assets/javascripts/bundle.f55a23d4.min.js' | url }}"></script>
<script src="{{ 'assets/javascripts/bundle.e71a0d61.min.js' | url }}"></script>
{% for script in config.extra_javascript %}

@@ -258,0 +263,0 @@ {{ script | script_tag }}

@@ -11,2 +11,3 @@ {#-

"blog.archive": "Archiv",
"blog.authors": "Autoren",
"blog.categories": "Kategorien",

@@ -13,0 +14,0 @@ "blog.categories.in": "in",

@@ -12,2 +12,3 @@ {#-

"blog.archive": "Archive",
"blog.authors": "Authors",
"blog.categories": "Categories",

@@ -14,0 +15,0 @@ "blog.categories.in": "in",

@@ -13,2 +13,11 @@ {#-

{% endmacro %}
{% macro render_title(nav_item) %}
{% if nav_item.typeset %}
<span class="md-typeset">
{{ nav_item.typeset.title }}
</span>
{% else %}
{{ nav_item.title }}
{% endif %}
{% endmacro %}
{% macro render_content(nav_item, ref) %}

@@ -20,3 +29,3 @@ {% set ref = ref or nav_item %}

<span class="md-ellipsis">
{{ ref.title }}
{{ render_title(ref) }}
{% if nav_item.meta and nav_item.meta.subtitle %}

@@ -27,2 +36,5 @@ <br>

</span>
{% if nav_item.meta and nav_item.encrypted %}
{{ render_status(nav_item, "encrypted") }}
{% endif %}
{% if nav_item.meta and nav_item.meta.status %}

@@ -119,3 +131,3 @@ {{ render_status(nav_item, nav_item.meta.status) }}

<span class="md-nav__icon md-icon"></span>
{{ nav_item.title }}
{{ render_title(nav_item) }}
</label>

@@ -122,0 +134,0 @@ <ul class="md-nav__list" data-md-scrollfix>

@@ -44,2 +44,5 @@ {#-

{% endif %}
{% if post.config.pin %}
<span class="md-pin"></span>
{% endif %}
</ul>

@@ -62,3 +65,6 @@ {% if post.config.draft %}

{% endif %}
{% if post.config.pin %}
<hr>
{% endif %}
</div>
</article>

@@ -11,2 +11,5 @@ {#-

{% set class = "md-tag" %}
{% if tag.hidden %}
{% set class = class ~ " md-tag-shadow" %}
{% endif %}
{% if config.extra.tags %}

@@ -13,0 +16,0 @@ {% set class = class ~ " md-tag-icon" %}

@@ -7,3 +7,9 @@ {#-

<span class="md-ellipsis">
{{ toc_item.title }}
{% if toc_item.typeset %}
<span class="md-typeset">
{{ toc_item.typeset.title }}
</span>
{% else %}
{{ toc_item.title }}
{% endif %}
</span>

@@ -10,0 +16,0 @@ </a>

{
"name": "mkdocs-material",
"version": "9.6.23",
"version": "9.7.0",
"description": "Documentation that simply works",

@@ -5,0 +5,0 @@ "keywords": [

+14
-18
Metadata-Version: 2.4
Name: mkdocs-material
Version: 9.6.23
Version: 9.7.0
Summary: Documentation that simply works

@@ -22,13 +22,13 @@ Project-URL: Homepage, https://squidfunk.github.io/mkdocs-material/

Requires-Python: >=3.8
Requires-Dist: babel~=2.10
Requires-Dist: backrefs~=5.7.post1
Requires-Dist: colorama~=0.4
Requires-Dist: jinja2~=3.1
Requires-Dist: markdown~=3.2
Requires-Dist: mkdocs-material-extensions~=1.3
Requires-Dist: mkdocs~=1.6
Requires-Dist: paginate~=0.5
Requires-Dist: pygments~=2.16
Requires-Dist: pymdown-extensions~=10.2
Requires-Dist: requests~=2.26
Requires-Dist: babel>=2.10
Requires-Dist: backrefs>=5.7.post1
Requires-Dist: colorama>=0.4
Requires-Dist: jinja2>=3.1
Requires-Dist: markdown>=3.2
Requires-Dist: mkdocs-material-extensions>=1.3
Requires-Dist: mkdocs>=1.6
Requires-Dist: paginate>=0.5
Requires-Dist: pygments>=2.16
Requires-Dist: pymdown-extensions>=10.2
Requires-Dist: requests>=2.26
Provides-Extra: git

@@ -76,6 +76,2 @@ Requires-Dist: mkdocs-git-committers-plugin-2<3,>=1.1; extra == 'git'

/></a>
<a href="https://github.com/sponsors/squidfunk"><img
src="https://img.shields.io/github/sponsors/squidfunk"
alt="Sponsors"
/></a>
</p>

@@ -217,4 +213,4 @@

/></a>
<a href="https://maxar.com/" target=_blank><img
src="https://raw.githubusercontent.com/squidfunk/mkdocs-material/master/.github/assets/sponsors/sponsor-maxar.png" height="58"
<a href="https://vantor.com/" target=_blank><img
src="https://raw.githubusercontent.com/squidfunk/mkdocs-material/master/.github/assets/sponsors/sponsor-vantor.png" height="58"
/></a>

@@ -221,0 +217,0 @@ <a href="https://www.equipmentshare.com/" target=_blank><img

@@ -75,3 +75,2 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

Issues = "https://github.com/squidfunk/mkdocs-material/issues"
Funding = "https://github.com/sponsors/squidfunk"

@@ -84,6 +83,9 @@ [project.entry-points."mkdocs.plugins"]

"material/offline" = "material.plugins.offline.plugin:OfflinePlugin"
"material/optimize" = "material.plugins.optimize.plugin:OptimizePlugin"
"material/privacy" = "material.plugins.privacy.plugin:PrivacyPlugin"
"material/projects" = "material.plugins.projects.plugin:ProjectsPlugin"
"material/search" = "material.plugins.search.plugin:SearchPlugin"
"material/social" = "material.plugins.social.plugin:SocialPlugin"
"material/tags" = "material.plugins.tags.plugin:TagsPlugin"
"material/typeset" = "material.plugins.typeset.plugin:TypesetPlugin"

@@ -90,0 +92,0 @@ [project.entry-points."mkdocs.themes"]

@@ -31,6 +31,2 @@ <p align="center">

/></a>
<a href="https://github.com/sponsors/squidfunk"><img
src="https://img.shields.io/github/sponsors/squidfunk"
alt="Sponsors"
/></a>
</p>

@@ -172,4 +168,4 @@

/></a>
<a href="https://maxar.com/" target=_blank><img
src="https://raw.githubusercontent.com/squidfunk/mkdocs-material/master/.github/assets/sponsors/sponsor-maxar.png" height="58"
<a href="https://vantor.com/" target=_blank><img
src="https://raw.githubusercontent.com/squidfunk/mkdocs-material/master/.github/assets/sponsors/sponsor-vantor.png" height="58"
/></a>

@@ -176,0 +172,0 @@ <a href="https://www.equipmentshare.com/" target=_blank><img

@@ -22,15 +22,15 @@ # Copyright (c) 2016-2025 Martin Donath <martin.donath@squidfunk.com>

# Requirements for core
jinja2~=3.1
markdown~=3.2
mkdocs~=1.6
mkdocs-material-extensions~=1.3
pygments~=2.16
pymdown-extensions~=10.2
jinja2>=3.1
markdown>=3.2
mkdocs>=1.6
mkdocs-material-extensions>=1.3
pygments>=2.16
pymdown-extensions>=10.2
# Requirements for plugins
babel~=2.10
colorama~=0.4
paginate~=0.5
backrefs~=5.7.post1
requests~=2.26
babel>=2.10
colorama>=0.4
paginate>=0.5
backrefs>=5.7.post1
requests>=2.26

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

"use strict";(()=>{var xe=Object.create;var U=Object.defineProperty,ve=Object.defineProperties,Se=Object.getOwnPropertyDescriptor,Te=Object.getOwnPropertyDescriptors,Qe=Object.getOwnPropertyNames,J=Object.getOwnPropertySymbols,Ee=Object.getPrototypeOf,Z=Object.prototype.hasOwnProperty,be=Object.prototype.propertyIsEnumerable;var K=Math.pow,X=(t,e,r)=>e in t?U(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,A=(t,e)=>{for(var r in e||(e={}))Z.call(e,r)&&X(t,r,e[r]);if(J)for(var r of J(e))be.call(e,r)&&X(t,r,e[r]);return t},G=(t,e)=>ve(t,Te(e));var Le=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var we=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Qe(e))!Z.call(t,i)&&i!==r&&U(t,i,{get:()=>e[i],enumerable:!(n=Se(e,i))||n.enumerable});return t};var Pe=(t,e,r)=>(r=t!=null?xe(Ee(t)):{},we(e||!t||!t.__esModule?U(r,"default",{value:t,enumerable:!0}):r,t));var B=(t,e,r)=>new Promise((n,i)=>{var s=u=>{try{a(r.next(u))}catch(c){i(c)}},o=u=>{try{a(r.throw(u))}catch(c){i(c)}},a=u=>u.done?n(u.value):Promise.resolve(u.value).then(s,o);a((r=r.apply(t,e)).next())});var re=Le((ee,te)=>{/**
* lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9
* Copyright (C) 2020 Oliver Nightingale
* @license MIT
*/(function(){var t=function(e){var r=new t.Builder;return r.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),r.searchPipeline.add(t.stemmer),e.call(r,r),r.build()};t.version="2.3.9";/*!
* lunr.utils
* Copyright (C) 2020 Oliver Nightingale
*/t.utils={},t.utils.warn=(function(e){return function(r){e.console&&console.warn&&console.warn(r)}})(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var r=Object.create(null),n=Object.keys(e),i=0;i<n.length;i++){var s=n[i],o=e[s];if(Array.isArray(o)){r[s]=o.slice();continue}if(typeof o=="string"||typeof o=="number"||typeof o=="boolean"){r[s]=o;continue}throw new TypeError("clone is not deep and does not support nested objects")}return r},t.FieldRef=function(e,r,n){this.docRef=e,this.fieldName=r,this._stringValue=n},t.FieldRef.joiner="/",t.FieldRef.fromString=function(e){var r=e.indexOf(t.FieldRef.joiner);if(r===-1)throw"malformed field ref string";var n=e.slice(0,r),i=e.slice(r+1);return new t.FieldRef(i,n,e)},t.FieldRef.prototype.toString=function(){return this._stringValue==null&&(this._stringValue=this.fieldName+t.FieldRef.joiner+this.docRef),this._stringValue};/*!
* lunr.Set
* Copyright (C) 2020 Oliver Nightingale
*/t.Set=function(e){if(this.elements=Object.create(null),e){this.length=e.length;for(var r=0;r<this.length;r++)this.elements[e[r]]=!0}else this.length=0},t.Set.complete={intersect:function(e){return e},union:function(){return this},contains:function(){return!0}},t.Set.empty={intersect:function(){return this},union:function(e){return e},contains:function(){return!1}},t.Set.prototype.contains=function(e){return!!this.elements[e]},t.Set.prototype.intersect=function(e){var r,n,i,s=[];if(e===t.Set.complete)return this;if(e===t.Set.empty)return e;this.length<e.length?(r=this,n=e):(r=e,n=this),i=Object.keys(r.elements);for(var o=0;o<i.length;o++){var a=i[o];a in n.elements&&s.push(a)}return new t.Set(s)},t.Set.prototype.union=function(e){return e===t.Set.complete?t.Set.complete:e===t.Set.empty?this:new t.Set(Object.keys(this.elements).concat(Object.keys(e.elements)))},t.idf=function(e,r){var n=0;for(var i in e)i!="_index"&&(n+=Object.keys(e[i]).length);var s=(r-n+.5)/(n+.5);return Math.log(1+Math.abs(s))},t.Token=function(e,r){this.str=e||"",this.metadata=r||{}},t.Token.prototype.toString=function(){return this.str},t.Token.prototype.update=function(e){return this.str=e(this.str,this.metadata),this},t.Token.prototype.clone=function(e){return e=e||function(r){return r},new t.Token(e(this.str,this.metadata),this.metadata)};/*!
* lunr.tokenizer
* Copyright (C) 2020 Oliver Nightingale
*/t.tokenizer=function(e,r){if(e==null||e==null)return[];if(Array.isArray(e))return e.map(function(g){return new t.Token(t.utils.asString(g).toLowerCase(),t.utils.clone(r))});for(var n=e.toString().toLowerCase(),i=n.length,s=[],o=0,a=0;o<=i;o++){var u=n.charAt(o),c=o-a;if(u.match(t.tokenizer.separator)||o==i){if(c>0){var f=t.utils.clone(r)||{};f.position=[a,c],f.index=s.length,s.push(new t.Token(n.slice(a,o),f))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;/*!
* lunr.Pipeline
* Copyright (C) 2020 Oliver Nightingale
*/t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,r){r in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+r),e.label=r,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var r=e.label&&e.label in this.registeredFunctions;r||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index.
`,e)},t.Pipeline.load=function(e){var r=new t.Pipeline;return e.forEach(function(n){var i=t.Pipeline.registeredFunctions[n];if(i)r.add(i);else throw new Error("Cannot load unregistered function: "+n)}),r},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(r){t.Pipeline.warnIfFunctionNotRegistered(r),this._stack.push(r)},this)},t.Pipeline.prototype.after=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");n=n+1,this._stack.splice(n,0,r)},t.Pipeline.prototype.before=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");this._stack.splice(n,0,r)},t.Pipeline.prototype.remove=function(e){var r=this._stack.indexOf(e);r!=-1&&this._stack.splice(r,1)},t.Pipeline.prototype.run=function(e){for(var r=this._stack.length,n=0;n<r;n++){for(var i=this._stack[n],s=[],o=0;o<e.length;o++){var a=i(e[o],o,e);if(!(a==null||a===""))if(Array.isArray(a))for(var u=0;u<a.length;u++)s.push(a[u]);else s.push(a)}e=s}return e},t.Pipeline.prototype.runString=function(e,r){var n=new t.Token(e,r);return this.run([n]).map(function(i){return i.toString()})},t.Pipeline.prototype.reset=function(){this._stack=[]},t.Pipeline.prototype.toJSON=function(){return this._stack.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})};/*!
* lunr.Vector
* Copyright (C) 2020 Oliver Nightingale
*/t.Vector=function(e){this._magnitude=0,this.elements=e||[]},t.Vector.prototype.positionForIndex=function(e){if(this.elements.length==0)return 0;for(var r=0,n=this.elements.length/2,i=n-r,s=Math.floor(i/2),o=this.elements[s*2];i>1&&(o<e&&(r=s),o>e&&(n=s),o!=e);)i=n-r,s=r+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(o<e)return(s+1)*2},t.Vector.prototype.insert=function(e,r){this.upsert(e,r,function(){throw"duplicate index"})},t.Vector.prototype.upsert=function(e,r,n){this._magnitude=0;var i=this.positionForIndex(e);this.elements[i]==e?this.elements[i+1]=n(this.elements[i+1],r):this.elements.splice(i,0,e,r)},t.Vector.prototype.magnitude=function(){if(this._magnitude)return this._magnitude;for(var e=0,r=this.elements.length,n=1;n<r;n+=2){var i=this.elements[n];e+=i*i}return this._magnitude=Math.sqrt(e)},t.Vector.prototype.dot=function(e){for(var r=0,n=this.elements,i=e.elements,s=n.length,o=i.length,a=0,u=0,c=0,f=0;c<s&&f<o;)a=n[c],u=i[f],a<u?c+=2:a>u?f+=2:a==u&&(r+=n[c+1]*i[f+1],c+=2,f+=2);return r},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),r=1,n=0;r<this.elements.length;r+=2,n++)e[n]=this.elements[r];return e},t.Vector.prototype.toJSON=function(){return this.elements};/*!
* lunr.stemmer
* Copyright (C) 2020 Oliver Nightingale
* Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt
*/t.stemmer=(function(){var e={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},r={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""},n="[^aeiou]",i="[aeiouy]",s=n+"[^aeiouy]*",o=i+"[aeiou]*",a="^("+s+")?"+o+s,u="^("+s+")?"+o+s+"("+o+")?$",c="^("+s+")?"+o+s+o+s,f="^("+s+")?"+i,g=new RegExp(a),l=new RegExp(c),m=new RegExp(u),x=new RegExp(f),v=/^(.+?)(ss|i)es$/,d=/^(.+?)([^s])s$/,y=/^(.+?)eed$/,b=/^(.+?)(ed|ing)$/,E=/.$/,w=/(at|bl|iz)$/,R=new RegExp("([^aeiouylsz])\\1$"),j=new RegExp("^"+s+i+"[^aeiouwxy]$"),_=/^(.+?[^aeiou])y$/,D=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,N=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,C=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,V=/^(.+?)(s|t)(ion)$/,P=/^(.+?)e$/,z=/ll$/,$=new RegExp("^"+s+i+"[^aeiouwxy]$"),M=function(h){var S,k,L,p,T,O,F;if(h.length<3)return h;if(L=h.substr(0,1),L=="y"&&(h=L.toUpperCase()+h.substr(1)),p=v,T=d,p.test(h)?h=h.replace(p,"$1$2"):T.test(h)&&(h=h.replace(T,"$1$2")),p=y,T=b,p.test(h)){var Q=p.exec(h);p=g,p.test(Q[1])&&(p=E,h=h.replace(p,""))}else if(T.test(h)){var Q=T.exec(h);S=Q[1],T=x,T.test(S)&&(h=S,T=w,O=R,F=j,T.test(h)?h=h+"e":O.test(h)?(p=E,h=h.replace(p,"")):F.test(h)&&(h=h+"e"))}if(p=_,p.test(h)){var Q=p.exec(h);S=Q[1],h=S+"i"}if(p=D,p.test(h)){var Q=p.exec(h);S=Q[1],k=Q[2],p=g,p.test(S)&&(h=S+e[k])}if(p=N,p.test(h)){var Q=p.exec(h);S=Q[1],k=Q[2],p=g,p.test(S)&&(h=S+r[k])}if(p=C,T=V,p.test(h)){var Q=p.exec(h);S=Q[1],p=l,p.test(S)&&(h=S)}else if(T.test(h)){var Q=T.exec(h);S=Q[1]+Q[2],T=l,T.test(S)&&(h=S)}if(p=P,p.test(h)){var Q=p.exec(h);S=Q[1],p=l,T=m,O=$,(p.test(S)||T.test(S)&&!O.test(S))&&(h=S)}return p=z,T=l,p.test(h)&&T.test(h)&&(p=E,h=h.replace(p,"")),L=="y"&&(h=L.toLowerCase()+h.substr(1)),h};return function(I){return I.update(M)}})(),t.Pipeline.registerFunction(t.stemmer,"stemmer");/*!
* lunr.stopWordFilter
* Copyright (C) 2020 Oliver Nightingale
*/t.generateStopWordFilter=function(e){var r=e.reduce(function(n,i){return n[i]=i,n},{});return function(n){if(n&&r[n.toString()]!==n.toString())return n}},t.stopWordFilter=t.generateStopWordFilter(["a","able","about","across","after","all","almost","also","am","among","an","and","any","are","as","at","be","because","been","but","by","can","cannot","could","dear","did","do","does","either","else","ever","every","for","from","get","got","had","has","have","he","her","hers","him","his","how","however","i","if","in","into","is","it","its","just","least","let","like","likely","may","me","might","most","must","my","neither","no","nor","not","of","off","often","on","only","or","other","our","own","rather","said","say","says","she","should","since","so","some","than","that","the","their","them","then","there","these","they","this","tis","to","too","twas","us","wants","was","we","were","what","when","where","which","while","who","whom","why","will","with","would","yet","you","your"]),t.Pipeline.registerFunction(t.stopWordFilter,"stopWordFilter");/*!
* lunr.trimmer
* Copyright (C) 2020 Oliver Nightingale
*/t.trimmer=function(e){return e.update(function(r){return r.replace(/^\W+/,"").replace(/\W+$/,"")})},t.Pipeline.registerFunction(t.trimmer,"trimmer");/*!
* lunr.TokenSet
* Copyright (C) 2020 Oliver Nightingale
*/t.TokenSet=function(){this.final=!1,this.edges={},this.id=t.TokenSet._nextId,t.TokenSet._nextId+=1},t.TokenSet._nextId=1,t.TokenSet.fromArray=function(e){for(var r=new t.TokenSet.Builder,n=0,i=e.length;n<i;n++)r.insert(e[n]);return r.finish(),r.root},t.TokenSet.fromClause=function(e){return"editDistance"in e?t.TokenSet.fromFuzzyString(e.term,e.editDistance):t.TokenSet.fromString(e.term)},t.TokenSet.fromFuzzyString=function(e,r){for(var n=new t.TokenSet,i=[{node:n,editsRemaining:r,str:e}];i.length;){var s=i.pop();if(s.str.length>0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}if(s.str.length==0&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var c=s.node.edges["*"];else{var c=new t.TokenSet;s.node.edges["*"]=c}s.str.length==1&&(c.final=!0),i.push({node:c,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var f=s.str.charAt(0),g=s.str.charAt(1),l;g in s.node.edges?l=s.node.edges[g]:(l=new t.TokenSet,s.node.edges[g]=l),s.str.length==1&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:f+s.str.slice(2)})}}}return n},t.TokenSet.fromString=function(e){for(var r=new t.TokenSet,n=r,i=0,s=e.length;i<s;i++){var o=e[i],a=i==s-1;if(o=="*")r.edges[o]=r,r.final=a;else{var u=new t.TokenSet;u.final=a,r.edges[o]=u,r=u}}return n},t.TokenSet.prototype.toArray=function(){for(var e=[],r=[{prefix:"",node:this}];r.length;){var n=r.pop(),i=Object.keys(n.node.edges),s=i.length;n.node.final&&(n.prefix.charAt(0),e.push(n.prefix));for(var o=0;o<s;o++){var a=i[o];r.push({prefix:n.prefix.concat(a),node:n.node.edges[a]})}}return e},t.TokenSet.prototype.toString=function(){if(this._str)return this._str;for(var e=this.final?"1":"0",r=Object.keys(this.edges).sort(),n=r.length,i=0;i<n;i++){var s=r[i],o=this.edges[s];e=e+s+o.id}return e},t.TokenSet.prototype.intersect=function(e){for(var r=new t.TokenSet,n=void 0,i=[{qNode:e,output:r,node:this}];i.length;){n=i.pop();for(var s=Object.keys(n.qNode.edges),o=s.length,a=Object.keys(n.node.edges),u=a.length,c=0;c<o;c++)for(var f=s[c],g=0;g<u;g++){var l=a[g];if(l==f||f=="*"){var m=n.node.edges[l],x=n.qNode.edges[f],v=m.final&&x.final,d=void 0;l in n.output.edges?(d=n.output.edges[l],d.final=d.final||v):(d=new t.TokenSet,d.final=v,n.output.edges[l]=d),i.push({qNode:x,output:d,node:m})}}}return r},t.TokenSet.Builder=function(){this.previousWord="",this.root=new t.TokenSet,this.uncheckedNodes=[],this.minimizedNodes={}},t.TokenSet.Builder.prototype.insert=function(e){var r,n=0;if(e<this.previousWord)throw new Error("Out of order word insertion");for(var i=0;i<e.length&&i<this.previousWord.length&&e[i]==this.previousWord[i];i++)n++;this.minimize(n),this.uncheckedNodes.length==0?r=this.root:r=this.uncheckedNodes[this.uncheckedNodes.length-1].child;for(var i=n;i<e.length;i++){var s=new t.TokenSet,o=e[i];r.edges[o]=s,this.uncheckedNodes.push({parent:r,char:o,child:s}),r=s}r.final=!0,this.previousWord=e},t.TokenSet.Builder.prototype.finish=function(){this.minimize(0)},t.TokenSet.Builder.prototype.minimize=function(e){for(var r=this.uncheckedNodes.length-1;r>=e;r--){var n=this.uncheckedNodes[r],i=n.child.toString();i in this.minimizedNodes?n.parent.edges[n.char]=this.minimizedNodes[i]:(n.child._str=i,this.minimizedNodes[i]=n.child),this.uncheckedNodes.pop()}};/*!
* lunr.Index
* Copyright (C) 2020 Oliver Nightingale
*/t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(r){var n=new t.QueryParser(e,r);n.parse()})},t.Index.prototype.query=function(e){for(var r=new t.Query(this.fields),n=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),u=0;u<this.fields.length;u++)i[this.fields[u]]=new t.Vector;e.call(r,r);for(var u=0;u<r.clauses.length;u++){var c=r.clauses[u],f=null,g=t.Set.empty;c.usePipeline?f=this.pipeline.runString(c.term,{fields:c.fields}):f=[c.term];for(var l=0;l<f.length;l++){var m=f[l];c.term=m;var x=t.TokenSet.fromClause(c),v=this.tokenSet.intersect(x).toArray();if(v.length===0&&c.presence===t.Query.presence.REQUIRED){for(var d=0;d<c.fields.length;d++){var y=c.fields[d];o[y]=t.Set.empty}break}for(var b=0;b<v.length;b++)for(var E=v[b],w=this.invertedIndex[E],R=w._index,d=0;d<c.fields.length;d++){var y=c.fields[d],j=w[y],_=Object.keys(j),D=E+"/"+y,N=new t.Set(_);if(c.presence==t.Query.presence.REQUIRED&&(g=g.union(N),o[y]===void 0&&(o[y]=t.Set.complete)),c.presence==t.Query.presence.PROHIBITED){a[y]===void 0&&(a[y]=t.Set.empty),a[y]=a[y].union(N);continue}if(i[y].upsert(R,c.boost,function(ye,me){return ye+me}),!s[D]){for(var C=0;C<_.length;C++){var V=_[C],P=new t.FieldRef(V,y),z=j[V],$;($=n[P])===void 0?n[P]=new t.MatchData(E,y,z):$.add(E,y,z)}s[D]=!0}}}if(c.presence===t.Query.presence.REQUIRED)for(var d=0;d<c.fields.length;d++){var y=c.fields[d];o[y]=o[y].intersect(g)}}for(var M=t.Set.complete,I=t.Set.empty,u=0;u<this.fields.length;u++){var y=this.fields[u];o[y]&&(M=M.intersect(o[y])),a[y]&&(I=I.union(a[y]))}var h=Object.keys(n),S=[],k=Object.create(null);if(r.isNegated()){h=Object.keys(this.fieldVectors);for(var u=0;u<h.length;u++){var P=h[u],L=t.FieldRef.fromString(P);n[P]=new t.MatchData}}for(var u=0;u<h.length;u++){var L=t.FieldRef.fromString(h[u]),p=L.docRef;if(M.contains(p)&&!I.contains(p)){var T=this.fieldVectors[L],O=i[L.fieldName].similarity(T),F;if((F=k[p])!==void 0)F.score+=O,F.matchData.combine(n[L]);else{var Q={ref:p,score:O,matchData:n[L]};k[p]=Q,S.push(Q)}}}return S.sort(function(pe,ge){return ge.score-pe.score})},t.Index.prototype.toJSON=function(){var e=Object.keys(this.invertedIndex).sort().map(function(n){return[n,this.invertedIndex[n]]},this),r=Object.keys(this.fieldVectors).map(function(n){return[n,this.fieldVectors[n].toJSON()]},this);return{version:t.version,fields:this.fields,fieldVectors:r,invertedIndex:e,pipeline:this.pipeline.toJSON()}},t.Index.load=function(e){var r={},n={},i=e.fieldVectors,s=Object.create(null),o=e.invertedIndex,a=new t.TokenSet.Builder,u=t.Pipeline.load(e.pipeline);e.version!=t.version&&t.utils.warn("Version mismatch when loading serialised index. Current version of lunr '"+t.version+"' does not match serialized index '"+e.version+"'");for(var c=0;c<i.length;c++){var f=i[c],g=f[0],l=f[1];n[g]=new t.Vector(l)}for(var c=0;c<o.length;c++){var f=o[c],m=f[0],x=f[1];a.insert(m),s[m]=x}return a.finish(),r.fields=e.fields,r.fieldVectors=n,r.invertedIndex=s,r.tokenSet=a.root,r.pipeline=u,new t.Index(r)};/*!
* lunr.Builder
* Copyright (C) 2020 Oliver Nightingale
*/t.Builder=function(){this._ref="id",this._fields=Object.create(null),this._documents=Object.create(null),this.invertedIndex=Object.create(null),this.fieldTermFrequencies={},this.fieldLengths={},this.tokenizer=t.tokenizer,this.pipeline=new t.Pipeline,this.searchPipeline=new t.Pipeline,this.documentCount=0,this._b=.75,this._k1=1.2,this.termIndex=0,this.metadataWhitelist=[]},t.Builder.prototype.ref=function(e){this._ref=e},t.Builder.prototype.field=function(e,r){if(/\//.test(e))throw new RangeError("Field '"+e+"' contains illegal character '/'");this._fields[e]=r||{}},t.Builder.prototype.b=function(e){e<0?this._b=0:e>1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,r){var n=e[this._ref],i=Object.keys(this._fields);this._documents[n]=r||{},this.documentCount+=1;for(var s=0;s<i.length;s++){var o=i[s],a=this._fields[o].extractor,u=a?a(e):e[o],c=this.tokenizer(u,{fields:[o]}),f=this.pipeline.run(c),g=new t.FieldRef(n,o),l=Object.create(null);this.fieldTermFrequencies[g]=l,this.fieldLengths[g]=0,this.fieldLengths[g]+=f.length;for(var m=0;m<f.length;m++){var x=f[m];if(l[x]==null&&(l[x]=0),l[x]+=1,this.invertedIndex[x]==null){var v=Object.create(null);v._index=this.termIndex,this.termIndex+=1;for(var d=0;d<i.length;d++)v[i[d]]=Object.create(null);this.invertedIndex[x]=v}this.invertedIndex[x][o][n]==null&&(this.invertedIndex[x][o][n]=Object.create(null));for(var y=0;y<this.metadataWhitelist.length;y++){var b=this.metadataWhitelist[y],E=x.metadata[b];this.invertedIndex[x][o][n][b]==null&&(this.invertedIndex[x][o][n][b]=[]),this.invertedIndex[x][o][n][b].push(E)}}}},t.Builder.prototype.calculateAverageFieldLengths=function(){for(var e=Object.keys(this.fieldLengths),r=e.length,n={},i={},s=0;s<r;s++){var o=t.FieldRef.fromString(e[s]),a=o.fieldName;i[a]||(i[a]=0),i[a]+=1,n[a]||(n[a]=0),n[a]+=this.fieldLengths[o]}for(var u=Object.keys(this._fields),s=0;s<u.length;s++){var c=u[s];n[c]=n[c]/i[c]}this.averageFieldLength=n},t.Builder.prototype.createFieldVectors=function(){for(var e={},r=Object.keys(this.fieldTermFrequencies),n=r.length,i=Object.create(null),s=0;s<n;s++){for(var o=t.FieldRef.fromString(r[s]),a=o.fieldName,u=this.fieldLengths[o],c=new t.Vector,f=this.fieldTermFrequencies[o],g=Object.keys(f),l=g.length,m=this._fields[a].boost||1,x=this._documents[o.docRef].boost||1,v=0;v<l;v++){var d=g[v],y=f[d],b=this.invertedIndex[d]._index,E,w,R;i[d]===void 0?(E=t.idf(this.invertedIndex[d],this.documentCount),i[d]=E):E=i[d],w=E*((this._k1+1)*y)/(this._k1*(1-this._b+this._b*(u/this.averageFieldLength[a]))+y),w*=m,w*=x,R=Math.round(w*1e3)/1e3,c.insert(b,R)}e[o]=c}this.fieldVectors=e},t.Builder.prototype.createTokenSet=function(){this.tokenSet=t.TokenSet.fromArray(Object.keys(this.invertedIndex).sort())},t.Builder.prototype.build=function(){return this.calculateAverageFieldLengths(),this.createFieldVectors(),this.createTokenSet(),new t.Index({invertedIndex:this.invertedIndex,fieldVectors:this.fieldVectors,tokenSet:this.tokenSet,fields:Object.keys(this._fields),pipeline:this.searchPipeline})},t.Builder.prototype.use=function(e){var r=Array.prototype.slice.call(arguments,1);r.unshift(this),e.apply(this,r)},t.MatchData=function(e,r,n){for(var i=Object.create(null),s=Object.keys(n||{}),o=0;o<s.length;o++){var a=s[o];i[a]=n[a].slice()}this.metadata=Object.create(null),e!==void 0&&(this.metadata[e]=Object.create(null),this.metadata[e][r]=i)},t.MatchData.prototype.combine=function(e){for(var r=Object.keys(e.metadata),n=0;n<r.length;n++){var i=r[n],s=Object.keys(e.metadata[i]);this.metadata[i]==null&&(this.metadata[i]=Object.create(null));for(var o=0;o<s.length;o++){var a=s[o],u=Object.keys(e.metadata[i][a]);this.metadata[i][a]==null&&(this.metadata[i][a]=Object.create(null));for(var c=0;c<u.length;c++){var f=u[c];this.metadata[i][a][f]==null?this.metadata[i][a][f]=e.metadata[i][a][f]:this.metadata[i][a][f]=this.metadata[i][a][f].concat(e.metadata[i][a][f])}}}},t.MatchData.prototype.add=function(e,r,n){if(!(e in this.metadata)){this.metadata[e]=Object.create(null),this.metadata[e][r]=n;return}if(!(r in this.metadata[e])){this.metadata[e][r]=n;return}for(var i=Object.keys(n),s=0;s<i.length;s++){var o=i[s];o in this.metadata[e][r]?this.metadata[e][r][o]=this.metadata[e][r][o].concat(n[o]):this.metadata[e][r][o]=n[o]}},t.Query=function(e){this.clauses=[],this.allFields=e},t.Query.wildcard=new String("*"),t.Query.wildcard.NONE=0,t.Query.wildcard.LEADING=1,t.Query.wildcard.TRAILING=2,t.Query.presence={OPTIONAL:1,REQUIRED:2,PROHIBITED:3},t.Query.prototype.clause=function(e){return"fields"in e||(e.fields=this.allFields),"boost"in e||(e.boost=1),"usePipeline"in e||(e.usePipeline=!0),"wildcard"in e||(e.wildcard=t.Query.wildcard.NONE),e.wildcard&t.Query.wildcard.LEADING&&e.term.charAt(0)!=t.Query.wildcard&&(e.term="*"+e.term),e.wildcard&t.Query.wildcard.TRAILING&&e.term.slice(-1)!=t.Query.wildcard&&(e.term=""+e.term+"*"),"presence"in e||(e.presence=t.Query.presence.OPTIONAL),this.clauses.push(e),this},t.Query.prototype.isNegated=function(){for(var e=0;e<this.clauses.length;e++)if(this.clauses[e].presence!=t.Query.presence.PROHIBITED)return!1;return!0},t.Query.prototype.term=function(e,r){if(Array.isArray(e))return e.forEach(function(i){this.term(i,t.utils.clone(r))},this),this;var n=r||{};return n.term=e.toString(),this.clause(n),this},t.QueryParseError=function(e,r,n){this.name="QueryParseError",this.message=e,this.start=r,this.end=n},t.QueryParseError.prototype=new Error,t.QueryLexer=function(e){this.lexemes=[],this.str=e,this.length=e.length,this.pos=0,this.start=0,this.escapeCharPositions=[]},t.QueryLexer.prototype.run=function(){for(var e=t.QueryLexer.lexText;e;)e=e(this)},t.QueryLexer.prototype.sliceString=function(){for(var e=[],r=this.start,n=this.pos,i=0;i<this.escapeCharPositions.length;i++)n=this.escapeCharPositions[i],e.push(this.str.slice(r,n)),r=n+1;return e.push(this.str.slice(r,this.pos)),this.escapeCharPositions.length=0,e.join("")},t.QueryLexer.prototype.emit=function(e){this.lexemes.push({type:e,str:this.sliceString(),start:this.start,end:this.pos}),this.start=this.pos},t.QueryLexer.prototype.escapeCharacter=function(){this.escapeCharPositions.push(this.pos-1),this.pos+=1},t.QueryLexer.prototype.next=function(){if(this.pos>=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,r;do e=this.next(),r=e.charCodeAt(0);while(r>47&&r<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos<this.length},t.QueryLexer.EOS="EOS",t.QueryLexer.FIELD="FIELD",t.QueryLexer.TERM="TERM",t.QueryLexer.EDIT_DISTANCE="EDIT_DISTANCE",t.QueryLexer.BOOST="BOOST",t.QueryLexer.PRESENCE="PRESENCE",t.QueryLexer.lexField=function(e){return e.backup(),e.emit(t.QueryLexer.FIELD),e.ignore(),t.QueryLexer.lexText},t.QueryLexer.lexTerm=function(e){if(e.width()>1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var r=e.next();if(r==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(r.charCodeAt(0)==92){e.escapeCharacter();continue}if(r==":")return t.QueryLexer.lexField;if(r=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(r=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(r=="+"&&e.width()===1||r=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(r.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,r){this.lexer=new t.QueryLexer(e),this.query=r,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var r=e.peekLexeme();if(r!=null)switch(r.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expected either a field or a term, found "+r.type;throw r.str.length>=1&&(n+=" with value '"+r.str+"'"),new t.QueryParseError(n,r.start,r.end)}},t.QueryParser.parsePresence=function(e){var r=e.consumeLexeme();if(r!=null){switch(r.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var n="unrecognised presence operator'"+r.str+"'";throw new t.QueryParseError(n,r.start,r.end)}var i=e.peekLexeme();if(i==null){var n="expecting term or field, found nothing";throw new t.QueryParseError(n,r.start,r.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(n,i.start,i.end)}}},t.QueryParser.parseField=function(e){var r=e.consumeLexeme();if(r!=null){if(e.query.allFields.indexOf(r.str)==-1){var n=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+r.str+"', possible fields: "+n;throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.fields=[r.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,r.start,r.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var r=e.consumeLexeme();if(r!=null){e.currentClause.term=r.str.toLowerCase(),r.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var n=e.peekLexeme();if(n==null){e.nextClause();return}switch(n.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+n.type+"'";throw new t.QueryParseError(i,n.start,n.end)}}},t.QueryParser.parseEditDistance=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="edit distance must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.editDistance=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="boost must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.boost=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},(function(e,r){typeof define=="function"&&define.amd?define(r):typeof ee=="object"?te.exports=r():e.lunr=r()})(this,function(){return t})})()});var Y=Pe(re());function ne(t,e=document){let r=ke(t,e);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${t}" to be present`);return r}function ke(t,e=document){return e.querySelector(t)||void 0}Object.entries||(Object.entries=function(t){let e=[];for(let r of Object.keys(t))e.push([r,t[r]]);return e});Object.values||(Object.values=function(t){let e=[];for(let r of Object.keys(t))e.push(t[r]);return e});typeof Element!="undefined"&&(Element.prototype.scrollTo||(Element.prototype.scrollTo=function(t,e){typeof t=="object"?(this.scrollLeft=t.left,this.scrollTop=t.top):(this.scrollLeft=t,this.scrollTop=e)}),Element.prototype.replaceWith||(Element.prototype.replaceWith=function(...t){let e=this.parentNode;if(e){t.length===0&&e.removeChild(this);for(let r=t.length-1;r>=0;r--){let n=t[r];typeof n=="string"?n=document.createTextNode(n):n.parentNode&&n.parentNode.removeChild(n),r?e.insertBefore(this.previousSibling,n):e.replaceChild(n,this)}}}));function ie(t){let e=new Map;for(let r of t){let[n]=r.location.split("#"),i=e.get(n);typeof i=="undefined"?e.set(n,r):(e.set(r.location,r),r.parent=i)}return e}function W(t,e,r){var s;e=new RegExp(e,"g");let n,i=0;do{n=e.exec(t);let o=(s=n==null?void 0:n.index)!=null?s:t.length;if(i<o&&r(i,o),n){let[a]=n;i=n.index+a.length,a.length===0&&(e.lastIndex=n.index+1)}}while(n)}function se(t,e){let r=0,n=0,i=0;for(let s=0;i<t.length;i++)t.charAt(i)==="<"&&i>n?e(r,1,n,n=i):t.charAt(i)===">"&&(t.charAt(n+1)==="/"?--s===0&&e(r++,2,n,i+1):t.charAt(i-1)!=="/"&&s++===0&&e(r,0,n,i+1),n=i+1);i>n&&e(r,1,n,i)}function oe(t,e,r,n=!1){return q([t],e,r,n).pop()}function q(t,e,r,n=!1){let i=[0];for(let s=1;s<e.length;s++){let o=e[s-1],a=e[s],u=o[o.length-1]>>>2&1023,c=a[0]>>>12;i.push(+(u>c)+i[i.length-1])}return t.map((s,o)=>{let a=0,u=new Map;for(let f of r.sort((g,l)=>g-l)){let g=f&1048575,l=f>>>20;if(i[l]!==o)continue;let m=u.get(l);typeof m=="undefined"&&u.set(l,m=[]),m.push(g)}if(u.size===0)return s;let c=[];for(let[f,g]of u){let l=e[f],m=l[0]>>>12,x=l[l.length-1]>>>12,v=l[l.length-1]>>>2&1023;n&&m>a&&c.push(s.slice(a,m));let d=s.slice(m,x+v);for(let y of g.sort((b,E)=>E-b)){let b=(l[y]>>>12)-m,E=(l[y]>>>2&1023)+b;d=[d.slice(0,b),"<mark>",d.slice(b,E),"</mark>",d.slice(E)].join("")}if(a=x+v,c.push(d)===2)break}return n&&a<s.length&&c.push(s.slice(a)),c.join("")})}function ae(t){let e=[];if(typeof t=="undefined")return e;let r=Array.isArray(t)?t:[t];for(let n=0;n<r.length;n++){let i=lunr.tokenizer.table,s=i.length;se(r[n],(o,a,u,c)=>{var f;switch(i[f=o+=s]||(i[f]=[]),a){case 0:case 2:i[o].push(u<<12|c-u<<2|a);break;case 1:let g=r[n].slice(u,c);W(g,lunr.tokenizer.separator,(l,m)=>{if(typeof lunr.segmenter!="undefined"){let x=g.slice(l,m);if(/^[MHIK]$/.test(lunr.segmenter.ctype_(x))){let v=lunr.segmenter.segment(x);for(let d=0,y=0;d<v.length;d++)i[o]||(i[o]=[]),i[o].push(u+l+y<<12|v[d].length<<2|a),e.push(new lunr.Token(v[d].toLowerCase(),{position:o<<20|i[o].length-1})),y+=v[d].length;return}}i[o].push(u+l<<12|m-l<<2|a),e.push(new lunr.Token(g.slice(l,m).toLowerCase(),{position:o<<20|i[o].length-1}))})}})}return e}function ue(t,e=r=>r){return t.trim().split(/"([^"]+)"/g).map((r,n)=>n&1?r.replace(/^\b|^(?![^\x00-\x7F]|$)|\s+/g," +"):r).join("").replace(/"|(?:^|\s+)[*+\-:^~]+(?=\s+|$)/g,"").split(/\s+/g).reduce((r,n)=>{let i=e(n);return[...r,...Array.isArray(i)?i:[i]]},[]).map(r=>/([~^]$)/.test(r)?`${r}1`:r).map(r=>/(^[+-]|[~^]\d+$)/.test(r)?r:`${r}*`).join(" ")}function ce(t){return ue(t,e=>{let r=[],n=new lunr.QueryLexer(e);n.run();for(let{type:i,str:s,start:o,end:a}of n.lexemes)switch(i){case"FIELD":["title","text","tags"].includes(s)||(e=[e.slice(0,a)," ",e.slice(a+1)].join(""));break;case"TERM":W(s,lunr.tokenizer.separator,(...u)=>{r.push([e.slice(0,o),s.slice(...u),e.slice(a)].join(""))})}return r})}function le(t){let e=new lunr.Query(["title","text","tags"]);new lunr.QueryParser(t,e).parse();for(let n of e.clauses)n.usePipeline=!0,n.term.startsWith("*")&&(n.wildcard=lunr.Query.wildcard.LEADING,n.term=n.term.slice(1)),n.term.endsWith("*")&&(n.wildcard=lunr.Query.wildcard.TRAILING,n.term=n.term.slice(0,-1));return e.clauses}function he(t,e){var i;let r=new Set(t),n={};for(let s=0;s<e.length;s++)for(let o of r)e[s].startsWith(o.term)&&(n[o.term]=!0,r.delete(o));for(let s of r)(i=lunr.stopWordFilter)!=null&&i.call(lunr,s.term)&&(n[s.term]=!1);return n}function fe(t,e){let r=new Set,n=new Uint16Array(t.length);for(let s=0;s<t.length;s++)for(let o=s+1;o<t.length;o++)t.slice(s,o)in e&&(n[s]=o-s);let i=[0];for(let s=i.length;s>0;){let o=i[--s];for(let u=1;u<n[o];u++)n[o+u]>n[o]-u&&(r.add(t.slice(o,o+u)),i[s++]=o+u);let a=o+n[o];n[a]&&a<t.length-1&&(i[s++]=a),r.add(t.slice(o,a))}return r.has("")?new Set([t]):r}function Oe(t){return e=>r=>{if(typeof r[e]=="undefined")return;let n=[r.location,e].join(":");return t.set(n,lunr.tokenizer.table=[]),r[e]}}function Re(t,e){let[r,n]=[new Set(t),new Set(e)];return[...new Set([...r].filter(i=>!n.has(i)))]}var H=class{constructor({config:e,docs:r,options:n}){let i=Oe(this.table=new Map);this.map=ie(r),this.options=n,this.index=lunr(function(){this.metadataWhitelist=["position"],this.b(0),e.lang.length===1&&e.lang[0]!=="en"?this.use(lunr[e.lang[0]]):e.lang.length>1&&this.use(lunr.multiLanguage(...e.lang)),this.tokenizer=ae,lunr.tokenizer.separator=new RegExp(e.separator),lunr.segmenter="TinySegmenter"in lunr?new lunr.TinySegmenter:void 0;let s=Re(["trimmer","stopWordFilter","stemmer"],e.pipeline);for(let o of e.lang.map(a=>a==="en"?lunr:lunr[a]))for(let a of s)this.pipeline.remove(o[a]),this.searchPipeline.remove(o[a]);this.ref("location"),this.field("title",{boost:1e3,extractor:i("title")}),this.field("text",{boost:1,extractor:i("text")}),this.field("tags",{boost:1e6,extractor:i("tags")});for(let o of r)this.add(o,{boost:o.boost})})}search(e){if(e=e.replace(new RegExp("\\p{sc=Han}+","gu"),s=>[...fe(s,this.index.invertedIndex)].join("* ")),e=ce(e),!e)return{items:[]};let r=le(e).filter(s=>s.presence!==lunr.Query.presence.PROHIBITED),n=this.index.search(e).reduce((s,{ref:o,score:a,matchData:u})=>{let c=this.map.get(o);if(typeof c!="undefined"){c=A({},c),c.tags&&(c.tags=[...c.tags]);let f=he(r,Object.keys(u.metadata));for(let l of this.index.fields){if(typeof c[l]=="undefined")continue;let m=[];for(let d of Object.values(u.metadata))typeof d[l]!="undefined"&&m.push(...d[l].position);if(!m.length)continue;let x=this.table.get([c.location,l].join(":")),v=Array.isArray(c[l])?q:oe;c[l]=v(c[l],x,m,l!=="text")}let g=+!c.parent+Object.values(f).filter(l=>l).length/Object.keys(f).length;s.push(G(A({},c),{score:a*(1+K(g,2)),terms:f}))}return s},[]).sort((s,o)=>o.score-s.score).reduce((s,o)=>{let a=this.map.get(o.location);if(typeof a!="undefined"){let u=a.parent?a.parent.location:a.location;s.set(u,[...s.get(u)||[],o])}return s},new Map);for(let[s,o]of n)if(!o.find(a=>a.location===s)){let a=this.map.get(s);o.push(G(A({},a),{score:0,terms:{}}))}let i;if(this.options.suggest){let s=this.index.query(o=>{for(let a of r)o.term(a.term,{fields:["title"],presence:lunr.Query.presence.REQUIRED,wildcard:lunr.Query.wildcard.TRAILING})});i=s.length?Object.keys(s[0].matchData.metadata):[]}return A({items:[...n.values()]},typeof i!="undefined"&&{suggest:i})}};var de;function Ie(t){return B(this,null,function*(){let e="../lunr";if(typeof parent!="undefined"&&"IFrameWorker"in parent){let n=ne("script[src]"),[i]=n.src.split("/worker");e=e.replace("..",i)}let r=[];for(let n of t.lang){switch(n){case"ja":r.push(`${e}/tinyseg.js`);break;case"hi":case"th":r.push(`${e}/wordcut.js`);break}n!=="en"&&r.push(`${e}/min/lunr.${n}.min.js`)}t.lang.length>1&&r.push(`${e}/min/lunr.multi.min.js`),r.length&&(yield importScripts(`${e}/min/lunr.stemmer.support.min.js`,...r))})}function Fe(t){return B(this,null,function*(){switch(t.type){case 0:return yield Ie(t.data.config),de=new H(t.data),{type:1};case 2:let e=t.data;try{return{type:3,data:de.search(e)}}catch(r){return console.warn(`Invalid query: ${e} \u2013 see https://bit.ly/2s3ChXG`),console.warn(r),{type:3,data:{items:[]}}}default:throw new TypeError("Invalid message type")}})}self.lunr=Y.default;Y.default.utils.warn=console.warn;addEventListener("message",t=>B(null,null,function*(){postMessage(yield Fe(t.data))}));})();
//# sourceMappingURL=search.973d3a69.min.js.map

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

{"version":3,"sources":["src/templates/assets/stylesheets/main/components/_meta.scss","../../../../src/templates/assets/stylesheets/main.scss","src/templates/assets/stylesheets/main/_resets.scss","src/templates/assets/stylesheets/main/_colors.scss","src/templates/assets/stylesheets/main/_icons.scss","src/templates/assets/stylesheets/main/_typeset.scss","src/templates/assets/stylesheets/utilities/_break.scss","src/templates/assets/stylesheets/main/components/_author.scss","src/templates/assets/stylesheets/main/components/_banner.scss","src/templates/assets/stylesheets/main/components/_base.scss","src/templates/assets/stylesheets/main/components/_clipboard.scss","src/templates/assets/stylesheets/main/components/_code.scss","src/templates/assets/stylesheets/main/components/_consent.scss","src/templates/assets/stylesheets/main/components/_content.scss","src/templates/assets/stylesheets/main/components/_dialog.scss","src/templates/assets/stylesheets/main/components/_feedback.scss","src/templates/assets/stylesheets/main/components/_footer.scss","src/templates/assets/stylesheets/main/components/_form.scss","src/templates/assets/stylesheets/main/components/_header.scss","node_modules/material-design-color/material-color.scss","src/templates/assets/stylesheets/main/components/_nav.scss","src/templates/assets/stylesheets/main/components/_pagination.scss","src/templates/assets/stylesheets/main/components/_post.scss","src/templates/assets/stylesheets/main/components/_progress.scss","src/templates/assets/stylesheets/main/components/_search.scss","src/templates/assets/stylesheets/main/components/_select.scss","src/templates/assets/stylesheets/main/components/_sidebar.scss","src/templates/assets/stylesheets/main/components/_source.scss","src/templates/assets/stylesheets/main/components/_status.scss","src/templates/assets/stylesheets/main/components/_tabs.scss","src/templates/assets/stylesheets/main/components/_tag.scss","src/templates/assets/stylesheets/main/components/_tooltip.scss","src/templates/assets/stylesheets/main/components/_tooltip2.scss","src/templates/assets/stylesheets/main/components/_top.scss","src/templates/assets/stylesheets/main/components/_version.scss","src/templates/assets/stylesheets/main/extensions/markdown/_admonition.scss","src/templates/assets/stylesheets/main/extensions/markdown/_footnotes.scss","src/templates/assets/stylesheets/main/extensions/markdown/_toc.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_arithmatex.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_critic.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_details.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_emoji.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_highlight.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_keys.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_tabbed.scss","src/templates/assets/stylesheets/main/extensions/pymdownx/_tasklist.scss","src/templates/assets/stylesheets/main/integrations/_giscus.scss","src/templates/assets/stylesheets/main/integrations/_mermaid.scss","src/templates/assets/stylesheets/main/modifiers/_grid.scss","src/templates/assets/stylesheets/main/modifiers/_inline.scss"],"names":[],"mappings":"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,CAAA,8ClC64GN,CkCz4GI,kFACE,alC24GN,CkCh6GE,4DACE,oBlCm6GJ,CkCh6GI,sFACE,gClCk6GN,CkC75GE,oEACE,0BlCg6GJ,CkC75GI,kFACE,wBAlBG,CAmBH,qDAAA,CAAA,6ClC+5GN,CkC35GI,gFACE,alC65GN,CkCl7GE,4DACE,oBlCq7GJ,CkCl7GI,sFACE,gClCo7GN,CkC/6GE,oEACE,0BlCk7GJ,CkC/6GI,kFACE,wBAlBG,CAmBH,qDAAA,CAAA,6ClCi7GN,CkC76GI,gFACE,alC+6GN,CkCp8GE,0DACE,oBlCu8GJ,CkCp8GI,oFACE,gClCs8GN,CkCj8GE,kEACE,0BlCo8GJ,CkCj8GI,gFACE,wBAlBG,CAmBH,oDAAA,CAAA,4ClCm8GN,CkC/7GI,8EACE,alCi8GN,CkCt9GE,oDACE,oBlCy9GJ,CkCt9GI,8EACE,gClCw9GN,CkCn9GE,4DACE,0BlCs9GJ,CkCn9GI,0EACE,wBAlBG,CAmBH,iDAAA,CAAA,yClCq9GN,CkCj9GI,wEACE,alCm9GN,CkCx+GE,4DACE,oBlC2+GJ,CkCx+GI,sFACE,gClC0+GN,CkCr+GE,oEACE,0BlCw+GJ,CkCr+GI,kFACE,wBAlBG,CAmBH,qDAAA,CAAA,6ClCu+GN,CkCn+GI,gFACE,alCq+GN,CkC1/GE,wDACE,oBlC6/GJ,CkC1/GI,kFACE,gClC4/GN,CkCv/GE,gEACE,0BlC0/GJ,CkCv/GI,8EACE,wBAlBG,CAmBH,mDAAA,CAAA,2ClCy/GN,CkCr/GI,4EACE,alCu/GN,CmC3pHA,MACE,qMnC8pHF,CmCrpHE,sBAEE,uCAAA,CADA,gBnCypHJ,CmCrpHI,mCACE,anCupHN,CmCxpHI,mCACE,cnCupHN,CmCnpHM,4BACE,sBnCqpHR,CmClpHQ,mCACE,gCnCopHV,CmChpHQ,2DACE,SAAA,CAEA,uBAAA,CADA,enCmpHV,CmC9oHQ,yGACE,SAAA,CACA,uBnCgpHV,CmC5oHQ,yCACE,YnC8oHV,CmCvoHE,0BACE,eAAA,CACA,enCyoHJ,CmCtoHI,+BACE,oBnCwoHN,CmCnoHE,gDACE,YnCqoHJ,CmCjoHE,8BAIE,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","file":"main.css"}
@media screen{[data-md-color-scheme=slate]{--md-default-fg-color:hsla(var(--md-hue),15%,90%,0.82);--md-default-fg-color--light:hsla(var(--md-hue),15%,90%,0.56);--md-default-fg-color--lighter:hsla(var(--md-hue),15%,90%,0.32);--md-default-fg-color--lightest:hsla(var(--md-hue),15%,90%,0.12);--md-default-bg-color:hsla(var(--md-hue),15%,14%,1);--md-default-bg-color--light:hsla(var(--md-hue),15%,14%,0.54);--md-default-bg-color--lighter:hsla(var(--md-hue),15%,14%,0.26);--md-default-bg-color--lightest:hsla(var(--md-hue),15%,14%,0.07);--md-code-fg-color:hsla(var(--md-hue),18%,86%,0.82);--md-code-bg-color:hsla(var(--md-hue),15%,18%,1);--md-code-hl-color:#2977ff;--md-code-hl-color--light:#2977ff1a;--md-code-hl-number-color:#e6695b;--md-code-hl-special-color:#f06090;--md-code-hl-function-color:#c973d9;--md-code-hl-constant-color:#9383e2;--md-code-hl-keyword-color:#6791e0;--md-code-hl-string-color:#2fb170;--md-code-hl-name-color:var(--md-code-fg-color);--md-code-hl-operator-color:var(--md-default-fg-color--light);--md-code-hl-punctuation-color:var(--md-default-fg-color--light);--md-code-hl-comment-color:var(--md-default-fg-color--light);--md-code-hl-generic-color:var(--md-default-fg-color--light);--md-code-hl-variable-color:var(--md-default-fg-color--light);--md-typeset-color:var(--md-default-fg-color);--md-typeset-a-color:var(--md-primary-fg-color);--md-typeset-kbd-color:hsla(var(--md-hue),15%,90%,0.12);--md-typeset-kbd-accent-color:hsla(var(--md-hue),15%,90%,0.2);--md-typeset-kbd-border-color:hsla(var(--md-hue),15%,14%,1);--md-typeset-mark-color:#4287ff4d;--md-typeset-table-color:hsla(var(--md-hue),15%,95%,0.12);--md-typeset-table-color--light:hsla(var(--md-hue),15%,95%,0.035);--md-admonition-fg-color:var(--md-default-fg-color);--md-admonition-bg-color:var(--md-default-bg-color);--md-footer-bg-color:hsla(var(--md-hue),15%,10%,0.87);--md-footer-bg-color--dark:hsla(var(--md-hue),15%,8%,1);--md-shadow-z1:0 0.2rem 0.5rem #0000000d,0 0 0.05rem #0000001a;--md-shadow-z2:0 0.2rem 0.5rem #00000040,0 0 0.05rem #00000040;--md-shadow-z3:0 0.2rem 0.5rem #0006,0 0 0.05rem #00000059;color-scheme:dark}[data-md-color-scheme=slate] img[src$="#gh-light-mode-only"],[data-md-color-scheme=slate] img[src$="#only-light"]{display:none}[data-md-color-scheme=slate][data-md-color-primary=pink]{--md-typeset-a-color:#ed5487}[data-md-color-scheme=slate][data-md-color-primary=purple]{--md-typeset-a-color:#c46fd3}[data-md-color-scheme=slate][data-md-color-primary=deep-purple]{--md-typeset-a-color:#a47bea}[data-md-color-scheme=slate][data-md-color-primary=indigo]{--md-typeset-a-color:#5488e8}[data-md-color-scheme=slate][data-md-color-primary=teal]{--md-typeset-a-color:#00ccb8}[data-md-color-scheme=slate][data-md-color-primary=green]{--md-typeset-a-color:#71c174}[data-md-color-scheme=slate][data-md-color-primary=deep-orange]{--md-typeset-a-color:#ff764d}[data-md-color-scheme=slate][data-md-color-primary=brown]{--md-typeset-a-color:#c1775c}[data-md-color-scheme=slate][data-md-color-primary=black],[data-md-color-scheme=slate][data-md-color-primary=blue-grey],[data-md-color-scheme=slate][data-md-color-primary=grey],[data-md-color-scheme=slate][data-md-color-primary=white]{--md-typeset-a-color:#5e8bde}[data-md-color-switching] *,[data-md-color-switching] :after,[data-md-color-switching] :before{transition-duration:0ms!important}}[data-md-color-accent=red]{--md-accent-fg-color:#ff1947;--md-accent-fg-color--transparent:#ff19471a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=pink]{--md-accent-fg-color:#f50056;--md-accent-fg-color--transparent:#f500561a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=purple]{--md-accent-fg-color:#df41fb;--md-accent-fg-color--transparent:#df41fb1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=deep-purple]{--md-accent-fg-color:#7c4dff;--md-accent-fg-color--transparent:#7c4dff1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=indigo]{--md-accent-fg-color:#526cfe;--md-accent-fg-color--transparent:#526cfe1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=blue]{--md-accent-fg-color:#4287ff;--md-accent-fg-color--transparent:#4287ff1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=light-blue]{--md-accent-fg-color:#0091eb;--md-accent-fg-color--transparent:#0091eb1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=cyan]{--md-accent-fg-color:#00bad6;--md-accent-fg-color--transparent:#00bad61a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=teal]{--md-accent-fg-color:#00bda4;--md-accent-fg-color--transparent:#00bda41a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=green]{--md-accent-fg-color:#00c753;--md-accent-fg-color--transparent:#00c7531a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=light-green]{--md-accent-fg-color:#63de17;--md-accent-fg-color--transparent:#63de171a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-accent=lime]{--md-accent-fg-color:#b0eb00;--md-accent-fg-color--transparent:#b0eb001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=yellow]{--md-accent-fg-color:#ffd500;--md-accent-fg-color--transparent:#ffd5001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=amber]{--md-accent-fg-color:#fa0;--md-accent-fg-color--transparent:#ffaa001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=orange]{--md-accent-fg-color:#ff9100;--md-accent-fg-color--transparent:#ff91001a;--md-accent-bg-color:#000000de;--md-accent-bg-color--light:#0000008a}[data-md-color-accent=deep-orange]{--md-accent-fg-color:#ff6e42;--md-accent-fg-color--transparent:#ff6e421a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-primary=red]{--md-primary-fg-color:#ef5552;--md-primary-fg-color--light:#e57171;--md-primary-fg-color--dark:#e53734;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=pink]{--md-primary-fg-color:#e92063;--md-primary-fg-color--light:#ec417a;--md-primary-fg-color--dark:#c3185d;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=purple]{--md-primary-fg-color:#ab47bd;--md-primary-fg-color--light:#bb69c9;--md-primary-fg-color--dark:#8c24a8;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=deep-purple]{--md-primary-fg-color:#7e56c2;--md-primary-fg-color--light:#9574cd;--md-primary-fg-color--dark:#673ab6;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=indigo]{--md-primary-fg-color:#4051b5;--md-primary-fg-color--light:#5d6cc0;--md-primary-fg-color--dark:#303fa1;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=blue]{--md-primary-fg-color:#2094f3;--md-primary-fg-color--light:#42a5f5;--md-primary-fg-color--dark:#1975d2;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=light-blue]{--md-primary-fg-color:#02a6f2;--md-primary-fg-color--light:#28b5f6;--md-primary-fg-color--dark:#0287cf;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=cyan]{--md-primary-fg-color:#00bdd6;--md-primary-fg-color--light:#25c5da;--md-primary-fg-color--dark:#0097a8;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=teal]{--md-primary-fg-color:#009485;--md-primary-fg-color--light:#26a699;--md-primary-fg-color--dark:#007a6c;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=green]{--md-primary-fg-color:#4cae4f;--md-primary-fg-color--light:#68bb6c;--md-primary-fg-color--dark:#398e3d;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=light-green]{--md-primary-fg-color:#8bc34b;--md-primary-fg-color--light:#9ccc66;--md-primary-fg-color--dark:#689f38;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=lime]{--md-primary-fg-color:#cbdc38;--md-primary-fg-color--light:#d3e156;--md-primary-fg-color--dark:#b0b52c;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=yellow]{--md-primary-fg-color:#ffec3d;--md-primary-fg-color--light:#ffee57;--md-primary-fg-color--dark:#fbc02d;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=amber]{--md-primary-fg-color:#ffc105;--md-primary-fg-color--light:#ffc929;--md-primary-fg-color--dark:#ffa200;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=orange]{--md-primary-fg-color:#ffa724;--md-primary-fg-color--light:#ffa724;--md-primary-fg-color--dark:#fa8900;--md-primary-bg-color:#000000de;--md-primary-bg-color--light:#0000008a}[data-md-color-primary=deep-orange]{--md-primary-fg-color:#ff6e42;--md-primary-fg-color--light:#ff8a66;--md-primary-fg-color--dark:#f4511f;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=brown]{--md-primary-fg-color:#795649;--md-primary-fg-color--light:#8d6e62;--md-primary-fg-color--dark:#5d4037;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3}[data-md-color-primary=grey]{--md-primary-fg-color:#757575;--md-primary-fg-color--light:#9e9e9e;--md-primary-fg-color--dark:#616161;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3;--md-typeset-a-color:#4051b5}[data-md-color-primary=blue-grey]{--md-primary-fg-color:#546d78;--md-primary-fg-color--light:#607c8a;--md-primary-fg-color--dark:#455a63;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3;--md-typeset-a-color:#4051b5}[data-md-color-primary=light-green]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#72ad2e}[data-md-color-primary=lime]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#8b990a}[data-md-color-primary=yellow]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#b8a500}[data-md-color-primary=amber]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#d19d00}[data-md-color-primary=orange]:not([data-md-color-scheme=slate]){--md-typeset-a-color:#e68a00}[data-md-color-primary=white]{--md-primary-fg-color:hsla(var(--md-hue),0%,100%,1);--md-primary-fg-color--light:hsla(var(--md-hue),0%,100%,0.7);--md-primary-fg-color--dark:hsla(var(--md-hue),0%,0%,0.07);--md-primary-bg-color:hsla(var(--md-hue),0%,0%,0.87);--md-primary-bg-color--light:hsla(var(--md-hue),0%,0%,0.54);--md-typeset-a-color:#4051b5}[data-md-color-primary=white] .md-button{color:var(--md-typeset-a-color)}[data-md-color-primary=white] .md-button--primary{background-color:var(--md-typeset-a-color);border-color:var(--md-typeset-a-color);color:hsla(var(--md-hue),0%,100%,1)}@media screen and (min-width:60em){[data-md-color-primary=white] .md-search__form{background-color:hsla(var(--md-hue),0%,0%,.07)}[data-md-color-primary=white] .md-search__form:hover{background-color:hsla(var(--md-hue),0%,0%,.32)}[data-md-color-primary=white] .md-search__input+.md-search__icon{color:hsla(var(--md-hue),0%,0%,.87)}}@media screen and (min-width:76.25em){[data-md-color-primary=white] .md-tabs{border-bottom:.05rem solid #00000012}}[data-md-color-primary=black]{--md-primary-fg-color:hsla(var(--md-hue),15%,9%,1);--md-primary-fg-color--light:hsla(var(--md-hue),15%,9%,0.54);--md-primary-fg-color--dark:hsla(var(--md-hue),15%,9%,1);--md-primary-bg-color:hsla(var(--md-hue),15%,100%,1);--md-primary-bg-color--light:hsla(var(--md-hue),15%,100%,0.7);--md-typeset-a-color:#4051b5}[data-md-color-primary=black] .md-button{color:var(--md-typeset-a-color)}[data-md-color-primary=black] .md-button--primary{background-color:var(--md-typeset-a-color);border-color:var(--md-typeset-a-color);color:hsla(var(--md-hue),0%,100%,1)}[data-md-color-primary=black] .md-header{background-color:hsla(var(--md-hue),15%,9%,1)}@media screen and (max-width:59.984375em){[data-md-color-primary=black] .md-nav__source{background-color:hsla(var(--md-hue),15%,11%,.87)}}@media screen and (max-width:76.234375em){html [data-md-color-primary=black] .md-nav--primary .md-nav__title[for=__drawer]{background-color:hsla(var(--md-hue),15%,9%,1)}}@media screen and (min-width:76.25em){[data-md-color-primary=black] .md-tabs{background-color:hsla(var(--md-hue),15%,9%,1)}}
{"version":3,"sources":["src/templates/assets/stylesheets/palette/_scheme.scss","../../../../src/templates/assets/stylesheets/palette.scss","src/templates/assets/stylesheets/palette/_accent.scss","src/templates/assets/stylesheets/palette/_primary.scss","src/templates/assets/stylesheets/utilities/_break.scss"],"names":[],"mappings":"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","file":"palette.css"}