aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/docs/src/overrides/hooks
diff options
context:
space:
mode:
author简律纯 <i@jyunko.cn>2023-12-15 10:08:56 +0800
committerGitHub <noreply@github.com>2023-12-15 10:08:56 +0800
commitd697a1774ad8571e9314e3bd85aa141170587d19 (patch)
treecd3c3d84e3288db1f8e574a0b4dfb85e2e40f764 /docs/src/overrides/hooks
parent4943d5eff52a75caaccda6a1d84183032f06be26 (diff)
parent4dafb0f0a81255193f2a44df5d203239325e2236 (diff)
downloadinfini-d697a1774ad8571e9314e3bd85aa141170587d19.tar.gz
infini-d697a1774ad8571e9314e3bd85aa141170587d19.zip
Merge branch 'master' into master
Diffstat (limited to 'docs/src/overrides/hooks')
-rw-r--r--docs/src/overrides/hooks/shortcodes.py283
-rw-r--r--docs/src/overrides/hooks/translations.html32
-rw-r--r--docs/src/overrides/hooks/translations.py193
3 files changed, 508 insertions, 0 deletions
diff --git a/docs/src/overrides/hooks/shortcodes.py b/docs/src/overrides/hooks/shortcodes.py
new file mode 100644
index 00000000..5b02e3cf
--- /dev/null
+++ b/docs/src/overrides/hooks/shortcodes.py
@@ -0,0 +1,283 @@
+# Copyright (c) 2016-2023 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 posixpath
+import re
+
+from mkdocs.config.defaults import MkDocsConfig
+from mkdocs.structure.files import File, Files
+from mkdocs.structure.pages import Page
+from re import Match
+
+# -----------------------------------------------------------------------------
+# Hooks
+# -----------------------------------------------------------------------------
+
+# @todo
+def on_page_markdown(
+ markdown: str, *, page: Page, config: MkDocsConfig, files: Files
+):
+
+ # Replace callback
+ def replace(match: Match):
+ type, args = match.groups()
+ args = args.strip()
+ if type == "version":
+ if args.startswith("insiders-"):
+ return _badge_for_version_insiders(args, page, files)
+ else:
+ return _badge_for_version(args, page, files)
+ elif type == "sponsors": return _badge_for_sponsors(page, files)
+ elif type == "flag": return flag(args, page, files)
+ elif type == "option": return option(args)
+ elif type == "setting": return setting(args)
+ elif type == "feature": return _badge_for_feature(args, page, files)
+ elif type == "plugin": return _badge_for_plugin(args, page, files)
+ elif type == "extension": return _badge_for_extension(args, page, files)
+ elif type == "utility": return _badge_for_utility(args, page, files)
+ elif type == "example": return _badge_for_example(args, page, files)
+ elif type == "default":
+ if args == "none": return _badge_for_default_none(page, files)
+ elif args == "computed": return _badge_for_default_computed(page, files)
+ else: return _badge_for_default(args, page, files)
+
+ # Otherwise, raise an error
+ raise RuntimeError(f"Unknown shortcode: {type}")
+
+ # Find and replace all external asset URLs in current page
+ return re.sub(
+ r"<!-- md:(\w+)(.*?) -->",
+ replace, markdown, flags = re.I | re.M
+ )
+
+# -----------------------------------------------------------------------------
+# Helper functions
+# -----------------------------------------------------------------------------
+
+# Create a flag of a specific type
+def flag(args: str, page: Page, files: Files):
+ type, *_ = args.split(" ", 1)
+ if type == "experimental": return _badge_for_experimental(page, files)
+ elif type == "required": return _badge_for_required(page, files)
+ elif type == "customization": return _badge_for_customization(page, files)
+ elif type == "metadata": return _badge_for_metadata(page, files)
+ elif type == "multiple": return _badge_for_multiple(page, files)
+ raise RuntimeError(f"Unknown type: {type}")
+
+# Create a linkable option
+def option(type: str):
+ _, *_, name = re.split(r"[.:]", type)
+ return f"[`{name}`](#+{type}){{ #+{type} }}\n\n"
+
+# Create a linkable setting - @todo append them to the bottom of the page
+def setting(type: str):
+ _, *_, name = re.split(r"[.*]", type)
+ return f"`{name}` {{ #{type} }}\n\n[{type}]: #{type}\n\n"
+
+# -----------------------------------------------------------------------------
+
+# Resolve path of file relative to given page - the posixpath always includes
+# one additional level of `..` which we need to remove
+def _resolve_path(path: str, page: Page, files: Files):
+ path, anchor, *_ = f"{path}#".split("#")
+ path = _resolve(files.get_file_from_path(path), page)
+ return "#".join([path, anchor]) if anchor else path
+
+# Resolve path of file relative to given page - the posixpath always includes
+# one additional level of `..` which we need to remove
+def _resolve(file: File, page: Page):
+ path = posixpath.relpath(file.src_uri, page.file.src_uri)
+ return posixpath.sep.join(path.split(posixpath.sep)[1:])
+
+# -----------------------------------------------------------------------------
+
+# Create badge
+def _badge(icon: str, text: str = "", type: str = ""):
+ classes = f"mdx-badge mdx-badge--{type}" if type else "mdx-badge"
+ return "".join([
+ f"<span class=\"{classes}\">",
+ *([f"<span class=\"mdx-badge__icon\">{icon}</span>"] if icon else []),
+ *([f"<span class=\"mdx-badge__text\">{text}</span>"] if text else []),
+ f"</span>",
+ ])
+
+# Create sponsors badge
+def _badge_for_sponsors(page: Page, files: Files):
+ icon = "material-heart"
+ href = _resolve_path("insiders/index.md", page, files)
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Sponsors only')",
+ type = "heart"
+ )
+
+# Create badge for version
+def _badge_for_version(text: str, page: Page, files: Files):
+ spec = text
+ path = f"changelog/index.md#{spec}"
+
+ # Return badge
+ icon = "material-tag-outline"
+ href = _resolve_path("conventions.md#version", page, files)
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Minimum version')",
+ text = f"[{text}]({_resolve_path(path, page, files)})" if spec else ""
+ )
+
+# Create badge for version of Insiders
+def _badge_for_version_insiders(text: str, page: Page, files: Files):
+ spec = text.replace("insiders-", "")
+ path = f"insiders/changelog/index.md#{spec}"
+
+ # Return badge
+ icon = "material-tag-heart-outline"
+ href = _resolve_path("conventions.md#version-insiders", page, files)
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Minimum version')",
+ text = f"[{text}]({_resolve_path(path, page, files)})" if spec else ""
+ )
+
+# Create badge for feature
+def _badge_for_feature(text: str, page: Page, files: Files):
+ icon = "material-toggle-switch"
+ href = _resolve_path("conventions.md#feature", page, files)
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Optional feature')",
+ text = text
+ )
+
+# Create badge for plugin
+def _badge_for_plugin(text: str, page: Page, files: Files):
+ icon = "material-floppy"
+ href = _resolve_path("conventions.md#plugin", page, files)
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Plugin')",
+ text = text
+ )
+
+# Create badge for extension
+def _badge_for_extension(text: str, page: Page, files: Files):
+ icon = "material-language-markdown"
+ href = _resolve_path("conventions.md#extension", page, files)
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Markdown extension')",
+ text = text
+ )
+
+# Create badge for utility
+def _badge_for_utility(text: str, page: Page, files: Files):
+ icon = "material-package-variant"
+ href = _resolve_path("conventions.md#utility", page, files)
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Third-party utility')",
+ text = text
+ )
+
+# Create badge for example
+def _badge_for_example(text: str, page: Page, files: Files):
+ return "\n".join([
+ _badge_for_example_download(text, page, files),
+ _badge_for_example_view(text, page, files)
+ ])
+
+# Create badge for example view
+def _badge_for_example_view(text: str, page: Page, files: Files):
+ icon = "material-folder-eye"
+ href = f"https://mkdocs-material.github.io/examples/{text}/"
+ return _badge(
+ icon = f"[:{icon}:]({href} 'View example')",
+ type = "right"
+ )
+
+# Create badge for example download
+def _badge_for_example_download(text: str, page: Page, files: Files):
+ icon = "material-folder-download"
+ href = f"https://mkdocs-material.github.io/examples/{text}.zip"
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Download example')",
+ text = f"[`.zip`]({href})",
+ type = "right"
+ )
+
+# Create badge for default value
+def _badge_for_default(text: str, page: Page, files: Files):
+ icon = "material-water"
+ href = _resolve_path("conventions.md#default", page, files)
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Default value')",
+ text = text
+ )
+
+# Create badge for empty default value
+def _badge_for_default_none(page: Page, files: Files):
+ icon = "material-water-outline"
+ href = _resolve_path("conventions.md#default", page, files)
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Default value is empty')"
+ )
+
+# Create badge for computed default value
+def _badge_for_default_computed(page: Page, files: Files):
+ icon = "material-water-check"
+ href = _resolve_path("conventions.md#default", page, files)
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Default value is computed')"
+ )
+
+# Create badge for metadata property flag
+def _badge_for_metadata(page: Page, files: Files):
+ icon = "material-list-box-outline"
+ href = _resolve_path("conventions.md#metadata", page, files)
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Metadata property')"
+ )
+
+# Create badge for required value flag
+def _badge_for_required(page: Page, files: Files):
+ icon = "material-alert"
+ href = _resolve_path("conventions.md#required", page, files)
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Required value')"
+ )
+
+# Create badge for customization flag
+def _badge_for_customization(page: Page, files: Files):
+ icon = "material-brush-variant"
+ href = _resolve_path("conventions.md#customization", page, files)
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Customization')"
+ )
+
+# Create badge for multiple instance flag
+def _badge_for_multiple(page: Page, files: Files):
+ icon = "material-inbox-multiple"
+ href = _resolve_path("conventions.md#multiple-instances", page, files)
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Multiple instances')"
+ )
+
+# Create badge for experimental flag
+def _badge_for_experimental(page: Page, files: Files):
+ icon = "material-flask-outline"
+ href = _resolve_path("conventions.md#experimental", page, files)
+ return _badge(
+ icon = f"[:{icon}:]({href} 'Experimental')"
+ )
diff --git a/docs/src/overrides/hooks/translations.html b/docs/src/overrides/hooks/translations.html
new file mode 100644
index 00000000..b77fcb4a
--- /dev/null
+++ b/docs/src/overrides/hooks/translations.html
@@ -0,0 +1,32 @@
+{#-
+ This file was automatically generated - do not edit
+-#}
+{% macro render_language(language) %}
+ <div class="mdx-flags__item" markdown>
+ :flag_{{ language.flag }}:{ .lg .middle }
+ <span class="mdx-flags__content">
+ <span>
+ <strong>{{ language.name }}</strong>
+ <code>{{ language.code }}</code>
+ </span>
+ {% if language.miss %}
+ <span>
+ <a href="{{ language.link }}">
+ {{ language.miss | length }} translations missing
+ </a>
+ </span>
+ {% else %}
+ <small>Complete</small>
+ {% endif %}
+ </span>
+ </div>
+{% endmacro %}
+{% macro render(translations, start = 1) %}
+ <div class="mdx-columns mdx-flags" markdown>
+ <ol markdown>
+ {% for language in translations %}
+ <li markdown>{{ render_language(language) }}</li>
+ {% endfor %}
+ </ol>
+ </div>
+{% endmacro %}
diff --git a/docs/src/overrides/hooks/translations.py b/docs/src/overrides/hooks/translations.py
new file mode 100644
index 00000000..661fd18e
--- /dev/null
+++ b/docs/src/overrides/hooks/translations.py
@@ -0,0 +1,193 @@
+# Copyright (c) 2016-2023 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
+import re
+
+from glob import iglob
+from mkdocs.config.defaults import MkDocsConfig
+from mkdocs.structure.pages import Page
+from urllib.parse import urlencode, urlparse
+
+# -----------------------------------------------------------------------------
+# Hooks
+# -----------------------------------------------------------------------------
+
+# Determine missing translations and render language overview in the setup
+# guide, including links to provide missing translations.
+def on_page_markdown(markdown: str, *, page: Page, config: MkDocsConfig, files):
+ issue_url = "https://github.com/squidfunk/mkdocs-material/issues/new"
+ if page.file.src_uri != "setup/changing-the-language.md":
+ return
+
+ # Collect all existing languages
+ names: dict[str, str] = {}
+ known: dict[str, dict[str, str]] = {}
+ for path in iglob("src/templates/partials/languages/*.html"):
+ with open(path, "r", encoding = "utf-8") as f:
+ data = f.read()
+
+ # Extract language code and name
+ name, = re.findall(r"<!-- Translations: (.+) -->", data)
+ code, _ = os.path.splitext(os.path.basename(path))
+
+ # Map names and available translations
+ names[code] = name
+ known[code] = dict(re.findall(
+ r"^ \"([^\"]+)\": \"([^\"]*)\"(?:,|$)?", data,
+ re.MULTILINE
+ ))
+
+ # Remove technical stuff
+ for key in [
+ "direction",
+ "search.config.pipeline",
+ "search.config.lang",
+ "search.config.separator"
+ ]:
+ if key in known[code]:
+ del known[code][key]
+
+ # Traverse all languages and compute missing translations
+ languages = []
+ reference = set(known["en"])
+ for code, name in names.items():
+ miss = reference - set(known[code])
+
+ # Check each translations
+ translations: list[str] = []
+ for key, value in known["en"].items():
+ if key in known[code]:
+ translations.append(
+ f" \"{key}\": \"{known[code][key]}\""
+ )
+ else:
+ translations.append(
+ f" \"{key}\": \"{value} ⬅️\""
+ )
+
+ # Assemble GitHub issue URL
+ link = urlparse(issue_url)
+ link = link._replace(query = urlencode({
+ "template": "04-add-translations.yml",
+ "title": f"Update {name} translations",
+ "translations": "\n".join([
+ "{% macro t(key) %}{{ {",
+ ",\n".join(translations),
+ "}[key] }}{% endmacro %}"
+ ]),
+ "country-flag": f":flag_{countries[code]}:"
+ }))
+
+ # Add translation
+ languages.append({
+ "flag": countries[code],
+ "code": code,
+ "name": name,
+ "link": link.geturl(),
+ "miss": miss
+ })
+
+ # Load template and render translations
+ env = config.theme.get_env()
+ template = env.get_template( "hooks/translations.html")
+ translations = template.module.render(
+ sorted(languages, key = lambda language: language["name"])
+ )
+
+ # Replace translation marker
+ return markdown.replace(
+ "<!-- hooks/translations.py -->", "\n".join(
+ [line.lstrip() for line in translations.split("\n")
+ ]
+ ))
+
+# -----------------------------------------------------------------------------
+# Data
+# -----------------------------------------------------------------------------
+
+# Map ISO 639-1 (languages) to ISO 3166 (countries)
+countries = dict({
+ "af": "za",
+ "ar": "ae",
+ "be": "by",
+ "bg": "bg",
+ "bn": "bd",
+ "ca": "es",
+ "cs": "cz",
+ "da": "dk",
+ "de": "de",
+ "el": "gr",
+ "en": "us",
+ "eo": "eu",
+ "es": "es",
+ "et": "ee",
+ "eu": "es",
+ "fa": "ir",
+ "fi": "fi",
+ "fr": "fr",
+ "gl": "es",
+ "he": "il",
+ "hi": "in",
+ "hr": "hr",
+ "hu": "hu",
+ "hy": "am",
+ "id": "id",
+ "is": "is",
+ "it": "it",
+ "ja": "jp",
+ "ka": "ge",
+ "kn": "in",
+ "ko": "kr",
+ "ku-IQ": "iq",
+ "lb": "lu",
+ "lt": "lt",
+ "lv": "lv",
+ "mk": "mk",
+ "mn": "mn",
+ "ms": "my",
+ "my": "mm",
+ "nb": "no",
+ "nl": "nl",
+ "nn": "no",
+ "pl": "pl",
+ "pt-BR": "br",
+ "pt": "pt",
+ "ro": "ro",
+ "ru": "ru",
+ "sa": "in",
+ "sh": "rs",
+ "si": "lk",
+ "sk": "sk",
+ "sl": "si",
+ "sr": "rs",
+ "sv": "se",
+ "te": "in",
+ "th": "th",
+ "tl": "ph",
+ "tr": "tr",
+ "uk": "ua",
+ "ur": "pk",
+ "uz": "uz",
+ "vi": "vn",
+ "zh": "cn",
+ "zh-Hant": "cn",
+ "zh-TW": "tw"
+})