mystx 源代码

"""mystx - 现代化 Sphinx 文档主题。

This module provides a custom Sphinx theme for creating beautiful, modern documentation.
The theme includes configuration management, styling, and integration with Sphinx.
"""
try:
    from ._version import __version__
except ImportError:  # pragma: no cover - setuptools-scm 生成文件缺失时回退
    try:
        from importlib.metadata import version as _pkg_version
[文档] __version__ = _pkg_version("mystx")
except Exception: # pragma: no cover - 开发环境无安装元数据时的最终回退 __version__ = "0.0.0.dev0" from sphinx.application import Sphinx from sphinx.util import logging from sphinx.util.typing import ExtensionMetadata from . import presets, tasks from .config import config_inited_handler from .configs import ( DEFAULT_BUILD_CONFIG, DEFAULT_EXT_CONFIG, DEFAULT_HTML_CONFIG, DEFAULT_MYST_CONFIG, build_base_config, ) from .extensions import DEFAULT_CONDITIONAL, DEFAULT_OPTIONAL_EXTENSIONS, resolve_extensions from .myst_compat import register_hooks as register_myst_compat_hooks from .presets import build_minimal_myst_config from .themes import DEFAULT_BOOK_THEME_OPTIONS, DEFAULT_THEME_PRIORITY, MySTX, resolve_theme, resolve_theme_options from .utils import deep_merge, has_module __all__ = ["__version__", "deep_merge", "has_module", "MySTX", "config_inited_handler", "setup", "logger", "DEFAULT_MYST_CONFIG", "DEFAULT_BUILD_CONFIG", "DEFAULT_EXT_CONFIG", "DEFAULT_HTML_CONFIG", "build_base_config", "DEFAULT_OPTIONAL_EXTENSIONS", "DEFAULT_CONDITIONAL", "resolve_extensions", "DEFAULT_BOOK_THEME_OPTIONS", "DEFAULT_THEME_PRIORITY", "resolve_theme", "resolve_theme_options", "register_myst_compat_hooks", "presets", "build_minimal_myst_config", "tasks"]
[文档] logger = logging.getLogger(__name__)
def _setup_myst_nb(app: Sphinx) -> None: """注册 myst-nb 的 Jupyter Notebook 支持(可选依赖)。 走 Sphinx 标准幂等入口 ``app.setup_extension``;缺失 myst-nb 时仅记录 日志并跳过,保证纯主题安装下 ``import mystx`` 与主题注册不因此崩溃。 """ if not has_module("myst_nb"): logger.info("未安装 myst-nb,跳过 Jupyter Notebook 支持") return app.setup_extension("myst_nb")
[文档] def setup(app: Sphinx) -> ExtensionMetadata: """Sphinx extension setup.""" configured = set(app.config.extensions) if hasattr(app, "config") else set() loaded = set(getattr(app, "extensions", {}).keys()) # Markdown/Notebook 链加载契约(myst-parser 5.x / myst-nb 1.x): # 两个扩展入口都调用同一个非幂等的 setup_sphinx()(内部对 # registry.transforms 执行 list.remove),且都注册 .md 后缀, # 同时加载必然抛 ValueError/ExtensionError。myst_nb 内部已完成 # myst_parser 的全部配置与 transforms 注册,其 parser 又是超集, # 因此采用互斥策略:nb 在场仅加载 nb,否则加载 parser; # 用户已在 conf 显式声明或提前加载任一者时尊重其选择,不再注入。 markdown_chain = {"myst_parser", "myst_nb"} if not (configured & markdown_chain) and not (loaded & markdown_chain): if has_module("myst_nb"): _setup_myst_nb(app) else: app.setup_extension("myst_parser") logger.warning("myst_parser not found in extensions list; mystx auto-injecting it. Install it explicitly to avoid this warning.") MySTX(app) # 自定义主题设置 # 连接到配置初始化事件 app.connect("config-inited", config_inited_handler) # 注册 myst 兼容性钩子(source-read / doctree-read) register_myst_compat_hooks(app) return { "parallel_read_safe": True, "parallel_write_safe": True, }