Coverage for src/markdown_exec/mkdocs_plugin.py: 0.00%
46 statements
« prev ^ index » next coverage.py v7.2.3, created at 2023-04-18 14:41 +0200
« prev ^ index » next coverage.py v7.2.3, created at 2023-04-18 14:41 +0200
1"""This module contains an optional plugin for MkDocs."""
3from __future__ import annotations
5import logging
6import os
7from pathlib import Path
8from typing import TYPE_CHECKING, Any, MutableMapping
10from mkdocs.config import Config, config_options
11from mkdocs.plugins import BasePlugin
12from mkdocs.utils import write_file
14from markdown_exec import formatter, formatters, validator
15from markdown_exec.logger import patch_loggers
16from markdown_exec.rendering import MarkdownConverter, markdown_config
18if TYPE_CHECKING:
19 from jinja2 import Environment
20 from mkdocs.structure.files import Files
22try:
23 __import__("pygments_ansi_color")
24except ImportError:
25 ansi_ok = False
26else:
27 ansi_ok = True
30class _LoggerAdapter(logging.LoggerAdapter):
31 def __init__(self, prefix: str, logger: logging.Logger) -> None:
32 super().__init__(logger, {})
33 self.prefix = prefix
35 def process(self, msg: str, kwargs: MutableMapping[str, Any]) -> tuple[str, MutableMapping[str, Any]]:
36 return f"{self.prefix}: {msg}", kwargs
39def _get_logger(name: str) -> _LoggerAdapter:
40 logger = logging.getLogger(f"mkdocs.plugins.{name}")
41 return _LoggerAdapter(name.split(".", 1)[0], logger)
44patch_loggers(_get_logger)
47class MarkdownExecPlugin(BasePlugin):
48 """MkDocs plugin to easily enable custom fences for code blocks execution."""
50 config_scheme = (("languages", config_options.Type(list, default=list(formatters.keys()))),)
52 def on_config(self, config: Config, **kwargs: Any) -> Config: # noqa: ARG002
53 """Configure the plugin.
55 Hook for the [`on_config` event](https://www.mkdocs.org/user-guide/plugins/#on_config).
56 In this hook, we add custom fences for all the supported languages.
58 We also save the Markdown extensions configuration
59 into [`markdown_config`][markdown_exec.rendering.markdown_config].
61 Arguments:
62 config: The MkDocs config object.
63 **kwargs: Additional arguments passed by MkDocs.
65 Returns:
66 The modified config.
67 """
68 self.languages = self.config["languages"]
69 mdx_configs = config.setdefault("mdx_configs", {})
70 superfences = mdx_configs.setdefault("pymdownx.superfences", {})
71 custom_fences = superfences.setdefault("custom_fences", [])
72 for language in self.languages:
73 custom_fences.append(
74 {
75 "name": language,
76 "class": language,
77 "validator": validator,
78 "format": formatter,
79 },
80 )
81 markdown_config.save(config["markdown_extensions"], config["mdx_configs"])
82 return config
84 def on_env(self, env: Environment, *, config: Config, files: Files) -> Environment | None: # noqa: ARG002,D102
85 css_filename = "assets/_markdown_exec_ansi.css"
86 css_content = Path(__file__).parent.joinpath("ansi.css").read_text()
87 write_file(css_content.encode("utf-8"), os.path.join(config["site_dir"], css_filename))
88 config["extra_css"].insert(0, css_filename)
89 return env
91 def on_post_build(self, *, config: Config) -> None: # noqa: ARG002,D102
92 MarkdownConverter.counter = 0
93 markdown_config.reset()