mirror of
https://github.com/TheBinaryNinja/tvapp2.git
synced 2026-06-04 06:25:41 -04:00
docs: integrate mkdocs into repository
This commit is contained in:
817
docs/material/overrides/hooks/shortcodes.py
Normal file
817
docs/material/overrides/hooks/shortcodes.py
Normal file
@@ -0,0 +1,817 @@
|
||||
# #
|
||||
# Copyright (c) 2025 Aetherinox
|
||||
#
|
||||
# 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.
|
||||
# #
|
||||
|
||||
# #
|
||||
# <!-- md:command `-s, --start` -->
|
||||
# <!-- md:backers -->
|
||||
# <!-- md:flag metadata -->
|
||||
# <!-- md:default `false` -->
|
||||
# <!-- md:default none -->
|
||||
# <!-- md:default computed -->
|
||||
# <!-- md:flag required -->
|
||||
# <!-- md:flag customization -->
|
||||
# <!-- md:flag experimental -->
|
||||
# <!-- md:flag multiple -->
|
||||
# <!-- md:example my-example-file -->
|
||||
# <!-- md:3rdparty -->
|
||||
# <!-- md:3rdparty [mike] -->
|
||||
# <!-- md:option social.icon -->
|
||||
# <!-- md:setting config.reeee -->
|
||||
# <!-- md:feature -->
|
||||
# #
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
# #
|
||||
# Import
|
||||
# #
|
||||
|
||||
import posixpath
|
||||
import re
|
||||
import inspect
|
||||
|
||||
# #
|
||||
# From
|
||||
# #
|
||||
|
||||
from mkdocs.config.defaults import MkDocsConfig
|
||||
from mkdocs.structure.files import File, Files
|
||||
from mkdocs.structure.pages import Page
|
||||
from re import Match
|
||||
|
||||
# #
|
||||
# ASCII Colors
|
||||
# #
|
||||
|
||||
class clr():
|
||||
BLACK = '\033[30m'
|
||||
RED = '\033[31m'
|
||||
GREEN = '\033[32m'
|
||||
YELLOW = '\033[33m'
|
||||
BLUE = '\033[34m'
|
||||
MAGENTA = '\033[35m'
|
||||
CYAN = '\033[36m'
|
||||
WHITE = '\033[37m'
|
||||
UNDERLINE = '\033[4m'
|
||||
RESET = '\033[0m'
|
||||
GREY = '\033[90m'
|
||||
|
||||
# #
|
||||
# Pages
|
||||
#
|
||||
# these must be configured to a valid page path; otherwise the script will error
|
||||
# #
|
||||
|
||||
PAGE_CHANGELOG ="about/changelog.md"
|
||||
PAGE_BACKERS = "about/backers.md"
|
||||
PAGE_CONVENTIONS = "about/conventions.md"
|
||||
|
||||
# #
|
||||
# Hooks > on_page_markdown
|
||||
# #
|
||||
|
||||
def on_page_markdown(markdown: str, *, page: Page, config: MkDocsConfig, files: Files):
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Loading Page: ' + clr.YELLOW + str(page) + clr.WHITE )
|
||||
|
||||
# Replace callback
|
||||
def replace(match: Match):
|
||||
type, args = match.groups()
|
||||
args = args.strip()
|
||||
|
||||
if type == "version":
|
||||
if args.startswith( "beta-" ):
|
||||
return Version_Beta(args, page, files)
|
||||
elif args.startswith( "stable-" ):
|
||||
return Version_Stable( args, page, files )
|
||||
else:
|
||||
return Version( args, page, files )
|
||||
|
||||
elif type == "backers": return Badge_Backers(page, files)
|
||||
elif type == "control": return Create_Control(args, page, files)
|
||||
elif type == "flag": return Create_Flag(args, page, files)
|
||||
elif type == "option": return Create_Option(args)
|
||||
elif type == "setting": return Create_Setting(args)
|
||||
elif type == "command": return Badge_Command(args, page, files)
|
||||
elif type == "feature": return Badge_Feature(args, page, files)
|
||||
elif type == "plugin": return Badge_Plugin(args, page, files)
|
||||
elif type == "extension": return Badge_Extension(args, page, files)
|
||||
elif type == "3rdparty": return Badge_3rdparty(args, page, files)
|
||||
elif type == "example": return Badge_Example(args, page, files)
|
||||
elif type == "default":
|
||||
if args == "none": return Badge_DefaultValue_None(page, files)
|
||||
elif args == "computed": return Badge_DefaultValue_Computed(page, files)
|
||||
else: return Badge_DefaultValue_Custom(args, page, files)
|
||||
|
||||
# Otherwise, raise an error
|
||||
raise RuntimeError( f"Error in shortcodes.yp - Specified an 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
|
||||
)
|
||||
|
||||
# #
|
||||
# Create > Flag
|
||||
# #
|
||||
|
||||
def Create_Flag(args: str, page: Page, files: Files):
|
||||
type, *_ = args.split(" ", 1)
|
||||
if type == "experimental": return Badge_Flag_Experimental(page, files)
|
||||
elif type == "required": return Badge_Flag_Required(page, files)
|
||||
elif type == "customization": return Badge_Flag_Customization(page, files)
|
||||
elif type == "metadata": return Badge_Flag_Metadata(page, files)
|
||||
elif type == "multiple": return Badge_Flag_Multiple_Instances(page, files)
|
||||
elif type == "setting": return Badge_Flag_Setting(page, files)
|
||||
raise RuntimeError(f"Unknown type: {type}")
|
||||
|
||||
# #
|
||||
# Create > Controls
|
||||
# #
|
||||
|
||||
def Create_Control( args: str, page: Page, files: Files ):
|
||||
type, *_ = args.split( " ", 2 )
|
||||
if type == "toggle": return icon_control_toggle( page, files )
|
||||
elif type == "toggle_on": return icon_control_toggle_on( page, files )
|
||||
elif type == "toggle_off": return icon_control_toggle_off( page, files )
|
||||
elif type == "textbox": return icon_control_textbox( page, files )
|
||||
elif type == "dropdown": return icon_control_dropdown( page, files )
|
||||
elif type == "button": return icon_control_button( page, files )
|
||||
elif type == "slider": return icon_control_slider( page, files )
|
||||
elif type == "color": return icon_control_color( args, page, files )
|
||||
else: return icon_control_default( page, files )
|
||||
|
||||
raise RuntimeError(f"Unknown type: {type}")
|
||||
|
||||
# #
|
||||
# Create > Option
|
||||
# #
|
||||
|
||||
def Create_Option(type: str):
|
||||
_, *_, name = re.split(r"[.:]", type)
|
||||
return f"[`{name}`](#+{type}){{ #+{type} }}\n\n"
|
||||
|
||||
# #
|
||||
# Create > Setting
|
||||
# #
|
||||
|
||||
def Create_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 Create_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>",
|
||||
])
|
||||
|
||||
# #
|
||||
# Badge > Color Palette
|
||||
# #
|
||||
|
||||
def Badge_ColorPalette(icon: str, text: str = "", type: str = ""):
|
||||
args = type.split( " " )
|
||||
|
||||
bg1_clr = "#000000"
|
||||
bg2_clr = "#000000"
|
||||
bg1_dis = "none"
|
||||
bg2_dis = "none"
|
||||
|
||||
if len( args ) > 1:
|
||||
bg1_clr = args[ 1 ]
|
||||
bg1_dis = "inline-block"
|
||||
|
||||
if len( args ) > 2:
|
||||
bg2_clr = args[ 2 ]
|
||||
bg2_dis = "inline-block"
|
||||
|
||||
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 style=\"display: {bg1_dis};\" class=\"color-container\"><span class=\"color-box\" style=\"background-color:{bg1_clr};\"> </span></span>",
|
||||
f"<span style=\"display: {bg2_dis};\" class=\"color-container\"><span class=\"color-box\" style=\"background-color:{bg2_clr};\"> </span></span></span>",
|
||||
])
|
||||
|
||||
# #
|
||||
# Badge > Sponsor / Backers
|
||||
#
|
||||
# In order for the sponsor / backers badge to work, you must have a backers page created in your mkdocs.
|
||||
# add a new file; usually about/backers.md
|
||||
# create a new entry in your mkdocs.yml to add the page to your navigation
|
||||
#
|
||||
# use the following tag in your md files:
|
||||
# <!-- md:sponsors --> __Sponsors only__ – this plugin is currently reserved to [our awesome sponsors].
|
||||
# <!-- md:sponsors -->
|
||||
# #
|
||||
|
||||
def Badge_Backers(page: Page, files: Files):
|
||||
icon = "material-heart"
|
||||
href = _resolve_path(PAGE_BACKERS, page, files)
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Backers only')",
|
||||
type = "heart"
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Version
|
||||
#
|
||||
# In order for the version badge to work, you must have a corresponding version entry in your changelog.md.
|
||||
# if not, you will receive the console error `'NoneType' object has no attribute 'src_uri'`
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:version stable-1.6.1 -->
|
||||
# #
|
||||
|
||||
def Version( text: str, page: Page, files: Files ):
|
||||
spec = text
|
||||
path = f"{PAGE_CHANGELOG}#{spec}"
|
||||
|
||||
# Return badge
|
||||
icon = "aetherx-axs-box"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#version", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Mkdocs Release')",
|
||||
text = f"[{text}]({_resolve_path(path, page, files)})" if spec else ""
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Version > Stable
|
||||
# #
|
||||
|
||||
def Version_Stable( text: str, page: Page, files: Files ):
|
||||
spec = text.replace( "stable-", "" )
|
||||
path = f"{PAGE_CHANGELOG}#{spec}"
|
||||
|
||||
# Return badge
|
||||
icon = "aetherx-axs-tag"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#version-beta", page, files )
|
||||
output = ""
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
# spec not empty
|
||||
if spec:
|
||||
output = f"Requires version {spec}"
|
||||
else:
|
||||
output = f"Stable Release"
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} '{output}' )",
|
||||
text = f"[{spec}]({_resolve_path(path, page, files)})" if spec else ""
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Version > Beta
|
||||
# #
|
||||
|
||||
def Version_Beta( text: str, page: Page, files: Files ):
|
||||
spec = text.replace( "beta-", "" )
|
||||
path = f"{PAGE_CHANGELOG}#{spec}"
|
||||
|
||||
# Return badge
|
||||
icon = "aetherx-axs-b"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#version-beta", page, files )
|
||||
output = ""
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
# spec not empty
|
||||
if spec:
|
||||
output = f"Requires version {spec}"
|
||||
else:
|
||||
output = f"Beta Release"
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} '{output}' )",
|
||||
text = f"[{text}]({_resolve_path(path, page, files)})" if spec else ""
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Feature
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:feature -->
|
||||
# #
|
||||
|
||||
def Badge_Feature(text: str, page: Page, files: Files):
|
||||
icon = "material-toggle-switch"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#feature", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Optional feature')",
|
||||
text = text
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Feature
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:plugin -->
|
||||
# <!-- md:plugin [glightbox] -->
|
||||
# <!-- md:plugin [typeset] – built-in -->
|
||||
# #
|
||||
|
||||
def Badge_Plugin(text: str, page: Page, files: Files):
|
||||
icon = "material-floppy"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#plugin", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Plugin')",
|
||||
text = text
|
||||
)
|
||||
|
||||
# #
|
||||
# Create badge for extension
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:extension [admonition][Admonition] -->
|
||||
# #
|
||||
|
||||
def Badge_Extension(text: str, page: Page, files: Files):
|
||||
icon = "material-language-markdown"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#extension", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Markdown extension')",
|
||||
text = text
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Third Party Plugin / Utility
|
||||
#
|
||||
# This symbol denotes that the item described is classified as something that changes the overall functionality of the plugin.
|
||||
#
|
||||
# use the following tag in your md files:
|
||||
# <!-- md:3rdparty -->
|
||||
# <!-- md:3rdparty [mike] -->
|
||||
# #
|
||||
|
||||
def Badge_3rdparty(text: str, page: Page, files: Files):
|
||||
icon = "material-package-variant"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#3rdparty", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Third-party utility')",
|
||||
text = text
|
||||
)
|
||||
|
||||
# #
|
||||
# Create Download Example > View
|
||||
#
|
||||
# Creates a badge which allows a user to download a file.
|
||||
#
|
||||
# The badge will have three sections:
|
||||
# - View Example
|
||||
# - Download Example
|
||||
# - .zip text
|
||||
#
|
||||
# If you supply the code below with a title of `my-example-file`, the links generated will be:
|
||||
# - [View Example] https://github.com/TheBinaryNinja/tvapp2/my-example-file/
|
||||
# - [Download Example] https://github.com/TheBinaryNinja/tvapp2/my-example-file.zip
|
||||
# - [Zip] https://github.com/TheBinaryNinja/tvapp2/my-example-file.zip
|
||||
#
|
||||
# use the following tag in your md files:
|
||||
# <!-- md:example my-example-file -->
|
||||
# #
|
||||
|
||||
def Badge_Example(text: str, page: Page, files: Files):
|
||||
return "\n".join([
|
||||
Badge_Example_Download_Zip(text, page, files),
|
||||
Badge_Example_View(text, page, files)
|
||||
])
|
||||
|
||||
def Badge_Example_View(text: str, page: Page, files: Files):
|
||||
icon = "material-folder-eye"
|
||||
href = f"https://github.com/TheBinaryNinja/tvapp2/{text}/"
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'View example')",
|
||||
type = "right"
|
||||
)
|
||||
|
||||
def Badge_Example_Download_Zip(text: str, page: Page, files: Files):
|
||||
icon = "material-folder-download"
|
||||
href = f"https://github.com/TheBinaryNinja/tvapp2/{text}.zip"
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Download example')",
|
||||
text = f"[`.zip`]({href})",
|
||||
type = "right"
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Command
|
||||
#
|
||||
# Used when specifying a command in an app
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:command `-s, --start` -->
|
||||
# #
|
||||
|
||||
def Badge_Command(text: str, page: Page, files: Files):
|
||||
icon = "material-console-line"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#command", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Terminal / Console Command')",
|
||||
text = text
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Default Value > Custom
|
||||
#
|
||||
# This defines what the default value for a setting is.
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:default `false` -->
|
||||
# <!-- md:default `my settings value` -->
|
||||
# <!-- md:default computed -->
|
||||
# <!-- md:default none -->
|
||||
# #
|
||||
|
||||
def Badge_DefaultValue_Custom(text: str, page: Page, files: Files):
|
||||
icon = "material-water"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#default", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Default value')",
|
||||
text = text
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Default Value > None / Empty
|
||||
#
|
||||
# This defines what the default value for a setting is.
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:default `false` -->
|
||||
# <!-- md:default `my settings value` -->
|
||||
# <!-- md:default computed -->
|
||||
# <!-- md:default none -->
|
||||
# #
|
||||
|
||||
def Badge_DefaultValue_None(page: Page, files: Files):
|
||||
icon = "material-water-outline"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#default", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Default value is empty')"
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Default Value > Computed
|
||||
#
|
||||
# This defines what the default value for a setting is.
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:default `false` -->
|
||||
# <!-- md:default `my settings value` -->
|
||||
# <!-- md:default computed -->
|
||||
# <!-- md:default none -->
|
||||
# #
|
||||
|
||||
def Badge_DefaultValue_Computed(page: Page, files: Files):
|
||||
icon = "material-water-check"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#default", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Default value is computed')"
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Flag > Metadata Property
|
||||
#
|
||||
# This symbol denotes that the item described is a metadata property, which can
|
||||
# be used in Markdown documents as part of the front matter definition.
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:flag metadata -->
|
||||
# #
|
||||
|
||||
def Badge_Flag_Metadata(page: Page, files: Files):
|
||||
icon = "material-list-box-outline"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#metadata", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Metadata property')"
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Flag > Required
|
||||
#
|
||||
# Specifies that a value is required.
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:flag required -->
|
||||
# <!-- md:flag required --> This option enables the content tabs
|
||||
# #
|
||||
|
||||
def Badge_Flag_Required(page: Page, files: Files):
|
||||
icon = "material-alert"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#required", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Required value')"
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Flag > Customization
|
||||
#
|
||||
# This symbol denotes that the item described is a customization which affects the overall look of the app.
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:flag customization -->
|
||||
# #
|
||||
|
||||
def Badge_Flag_Customization(page: Page, files: Files):
|
||||
icon = "material-brush-variant"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#customization", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Customization')"
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Flag > Experimental
|
||||
#
|
||||
# This symbol denotes that the item described is Experimental
|
||||
#
|
||||
# MUST add an entry in conventions.md
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:flag experimental -->
|
||||
# #
|
||||
|
||||
def Badge_Flag_Experimental(page: Page, files: Files):
|
||||
icon = "material-flask-outline"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#experimental", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Experimental')"
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Flag > Multiple Instances
|
||||
#
|
||||
# This symbol denotes that the plugin supports multiple instances, i.e, that it
|
||||
# can be used multiple times in the `plugins` setting
|
||||
#
|
||||
# MUST add an entry in conventions.md
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:flag multiple -->
|
||||
# #
|
||||
|
||||
def Badge_Flag_Multiple_Instances(page: Page, files: Files):
|
||||
icon = "material-inbox-multiple"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#multiple-instances", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Multiple instances')"
|
||||
)
|
||||
|
||||
# #
|
||||
# Badge > Flag > Setting
|
||||
#
|
||||
# This symbol denotes that the specified item is a customizable setting
|
||||
#
|
||||
# MUST add an entry in conventions.md
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:flag setting -->
|
||||
# #
|
||||
|
||||
def Badge_Flag_Setting(page: Page, files: Files):
|
||||
icon = "material-cog"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#setting", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Configurable Setting')"
|
||||
)
|
||||
|
||||
# #
|
||||
# Icon : Control : Default
|
||||
#
|
||||
# This function is activated if no control type specified
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:control -->
|
||||
# #
|
||||
|
||||
def icon_control_default( page: Page, files: Files ):
|
||||
icon = "aetherx-axs-hand-pointer"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Type: Textbox')"
|
||||
)
|
||||
|
||||
# #
|
||||
# Icon : Control : Textbox
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:control textbox -->
|
||||
# #
|
||||
|
||||
def icon_control_textbox( page: Page, files: Files ):
|
||||
icon = "aetherx-axs-input-text"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Type: Textbox')"
|
||||
)
|
||||
|
||||
# #
|
||||
# Icon : Control : Toggle Switch
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:control toggle -->
|
||||
# <!-- md:control toggle_on --> `Enabled`
|
||||
# <!-- md:control toggle_off --> `Disabled`
|
||||
# #
|
||||
|
||||
def icon_control_toggle( page: Page, files: Files ):
|
||||
icon = "aetherx-axs-toggle-large-on"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Type: Toggle Switch')"
|
||||
)
|
||||
|
||||
def icon_control_toggle_on( page: Page, files: Files ):
|
||||
icon = "aetherx-axd-toggle-on"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Toggle: Enabled')"
|
||||
)
|
||||
|
||||
def icon_control_toggle_off( page: Page, files: Files ):
|
||||
icon = "aetherx-axd-toggle-off"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Toggle: Disabled')"
|
||||
)
|
||||
|
||||
# #
|
||||
# Icon : Control : Dropdown
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:control dropdown -->
|
||||
# #
|
||||
|
||||
def icon_control_dropdown( page: Page, files: Files ):
|
||||
icon = "aetherx-axs-square-caret-down"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files)
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Type: Dropdown')"
|
||||
)
|
||||
|
||||
# #
|
||||
# Icon : Control : Button
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:control button -->
|
||||
# #
|
||||
|
||||
def icon_control_button( page: Page, files: Files ):
|
||||
icon = "material-button-pointer"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Type: Button')"
|
||||
)
|
||||
|
||||
# #
|
||||
# Icon : Control : Slider
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:control slider -->
|
||||
# #
|
||||
|
||||
def icon_control_slider( page: Page, files: Files ):
|
||||
icon = "aetherx-axd-sliders-simple"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Create_Badge(
|
||||
icon = f"[:{icon}:]({href} 'Type: Slider')"
|
||||
)
|
||||
|
||||
# #
|
||||
# Icon : Control : Color
|
||||
#
|
||||
# use the following tag in your md file:
|
||||
# <!-- md:control color #E5E5E5 #121315 -->
|
||||
# #
|
||||
|
||||
def icon_control_color( text: str, page: Page, files: Files ):
|
||||
icon = "aetherx-axs-palette"
|
||||
href = _resolve_path( f"{PAGE_CONVENTIONS}#control", page, files )
|
||||
|
||||
print(clr.MAGENTA + 'VERBOSE - ' + clr.WHITE + ' Running ' + clr.YELLOW + inspect.stack()[0][3] + clr.WHITE + ' for page ' + clr.GREY + str(href) + clr.WHITE )
|
||||
|
||||
return Badge_ColorPalette(
|
||||
icon = f"[:{icon}:]({href} 'Type: Color Wheel')",
|
||||
type = text
|
||||
)
|
||||
32
docs/material/overrides/hooks/translations.html
Normal file
32
docs/material/overrides/hooks/translations.html
Normal file
@@ -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 %}
|
||||
197
docs/material/overrides/hooks/translations.py
Normal file
197
docs/material/overrides/hooks/translations.py
Normal file
@@ -0,0 +1,197 @@
|
||||
# #
|
||||
# Copyright (c) 2025 Aetherinox
|
||||
#
|
||||
# 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 = {
|
||||
"af": "za",
|
||||
"az": "az",
|
||||
"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",
|
||||
"ta": "in",
|
||||
"tl": "ph",
|
||||
"tr": "tr",
|
||||
"uk": "ua",
|
||||
"ur": "pk",
|
||||
"uz": "uz",
|
||||
"vi": "vn",
|
||||
"zh": "cn",
|
||||
"zh-Hant": "cn",
|
||||
"zh-TW": "tw"
|
||||
}
|
||||
Reference in New Issue
Block a user