|
3 | 3 | Utilities to execute code blocks in Markdown files. |
4 | 4 | """ |
5 | 5 |
|
6 | | -# https://facelessuser.github.io/pymdown-extensions/extensions/superfences/#custom-fences |
7 | | -# https://squidfunk.github.io/mkdocs-material/setup/extensions/python-markdown-extensions/#snippets |
8 | | - |
9 | | -from __future__ import annotations |
10 | | - |
11 | | -import os |
12 | | -import re |
13 | | -from typing import TYPE_CHECKING, Any |
14 | | - |
15 | | -if TYPE_CHECKING: |
16 | | - from markdown import Markdown |
17 | | - |
18 | | -from markdown_exec.formatters.base import default_tabs |
19 | | -from markdown_exec.formatters.bash import _format_bash |
20 | | -from markdown_exec.formatters.console import _format_console |
21 | | -from markdown_exec.formatters.markdown import _format_markdown |
22 | | -from markdown_exec.formatters.pycon import _format_pycon |
23 | | -from markdown_exec.formatters.pyodide import _format_pyodide |
24 | | -from markdown_exec.formatters.python import _format_python |
25 | | -from markdown_exec.formatters.sh import _format_sh |
26 | | -from markdown_exec.formatters.tree import _format_tree |
27 | | - |
28 | | -__all__: list[str] = ["formatter", "validator"] |
29 | | - |
30 | | -MARKDOWN_EXEC_AUTO = [lang.strip() for lang in os.getenv("MARKDOWN_EXEC_AUTO", "").split(",")] |
31 | | - |
32 | | -formatters = { |
33 | | - "bash": _format_bash, |
34 | | - "console": _format_console, |
35 | | - "md": _format_markdown, |
36 | | - "markdown": _format_markdown, |
37 | | - "py": _format_python, |
38 | | - "python": _format_python, |
39 | | - "pycon": _format_pycon, |
40 | | - "pyodide": _format_pyodide, |
41 | | - "sh": _format_sh, |
42 | | - "tree": _format_tree, |
43 | | -} |
44 | | - |
45 | | -# negative look behind: matches only if | (pipe) if not preceded by \ (backslash) |
46 | | -_tabs_re = re.compile(r"(?<!\\)\|") |
47 | | - |
48 | | - |
49 | | -def validator( |
50 | | - language: str, |
51 | | - inputs: dict[str, str], |
52 | | - options: dict[str, Any], |
53 | | - attrs: dict[str, Any], # noqa: ARG001 |
54 | | - md: Markdown, # noqa: ARG001 |
55 | | -) -> bool: |
56 | | - """Validate code blocks inputs. |
57 | | -
|
58 | | - Parameters: |
59 | | - language: The code language, like python or bash. |
60 | | - inputs: The code block inputs, to be sorted into options and attrs. |
61 | | - options: The container for options. |
62 | | - attrs: The container for attrs: |
63 | | - md: The Markdown instance. |
64 | | -
|
65 | | - Returns: |
66 | | - Success or not. |
67 | | - """ |
68 | | - exec_value = language in MARKDOWN_EXEC_AUTO or _to_bool(inputs.pop("exec", "no")) |
69 | | - if language not in {"tree", "pyodide"} and not exec_value: |
70 | | - return False |
71 | | - id_value = inputs.pop("id", "") |
72 | | - id_prefix_value = inputs.pop("idprefix", None) |
73 | | - html_value = _to_bool(inputs.pop("html", "no")) |
74 | | - source_value = inputs.pop("source", "") |
75 | | - result_value = inputs.pop("result", "") |
76 | | - returncode_value = int(inputs.pop("returncode", "0")) |
77 | | - session_value = inputs.pop("session", "") |
78 | | - update_toc_value = _to_bool(inputs.pop("updatetoc", "yes")) |
79 | | - tabs_value = inputs.pop("tabs", "|".join(default_tabs)) |
80 | | - tabs = tuple(_tabs_re.split(tabs_value, maxsplit=1)) |
81 | | - workdir_value = inputs.pop("workdir", None) |
82 | | - width_value = int(inputs.pop("width", "0")) |
83 | | - options["id"] = id_value |
84 | | - options["id_prefix"] = id_prefix_value |
85 | | - options["html"] = html_value |
86 | | - options["source"] = source_value |
87 | | - options["result"] = result_value |
88 | | - options["returncode"] = returncode_value |
89 | | - options["session"] = session_value |
90 | | - options["update_toc"] = update_toc_value |
91 | | - options["tabs"] = tabs |
92 | | - options["workdir"] = workdir_value |
93 | | - options["width"] = width_value |
94 | | - options["extra"] = inputs |
95 | | - return True |
96 | | - |
97 | | - |
98 | | -def formatter( |
99 | | - source: str, |
100 | | - language: str, |
101 | | - css_class: str, # noqa: ARG001 |
102 | | - options: dict[str, Any], |
103 | | - md: Markdown, |
104 | | - classes: list[str] | None = None, # noqa: ARG001 |
105 | | - id_value: str = "", # noqa: ARG001 |
106 | | - attrs: dict[str, Any] | None = None, # noqa: ARG001 |
107 | | - **kwargs: Any, # noqa: ARG001 |
108 | | -) -> str: |
109 | | - """Execute code and return HTML. |
110 | | -
|
111 | | - Parameters: |
112 | | - source: The code to execute. |
113 | | - language: The code language, like python or bash. |
114 | | - css_class: The CSS class to add to the HTML element. |
115 | | - options: The container for options. |
116 | | - attrs: The container for attrs: |
117 | | - md: The Markdown instance. |
118 | | - classes: Additional CSS classes. |
119 | | - id_value: An optional HTML id. |
120 | | - attrs: Additional attributes |
121 | | - **kwargs: Additional arguments passed to SuperFences default formatters. |
122 | | -
|
123 | | - Returns: |
124 | | - HTML contents. |
125 | | - """ |
126 | | - fmt = formatters.get(language, lambda source, **kwargs: source) |
127 | | - return fmt(code=source, md=md, **options) # type: ignore[operator] |
128 | | - |
129 | | - |
130 | | -falsy_values = {"", "no", "off", "false", "0"} |
131 | | -truthy_values = {"yes", "on", "true", "1"} |
132 | | - |
133 | | - |
134 | | -def _to_bool(value: str) -> bool: |
135 | | - return value.lower() not in falsy_values |
136 | | - |
137 | | - |
138 | | -def _to_bool_or_value(value: str) -> bool | str: |
139 | | - if value.lower() in falsy_values: |
140 | | - return False |
141 | | - if value.lower() in truthy_values: |
142 | | - return True |
143 | | - return value |
| 6 | +from markdown_exec._internal.formatters.base import ( |
| 7 | + ExecutionError, |
| 8 | + base_format, |
| 9 | + console_width, |
| 10 | + default_tabs, |
| 11 | + working_directory, |
| 12 | +) |
| 13 | +from markdown_exec._internal.logger import get_logger, patch_loggers |
| 14 | +from markdown_exec._internal.main import MARKDOWN_EXEC_AUTO, formatter, formatters, validator |
| 15 | +from markdown_exec._internal.mkdocs_plugin import MarkdownExecPlugin, MarkdownExecPluginConfig |
| 16 | +from markdown_exec._internal.processors import ( |
| 17 | + HeadingReportingTreeprocessor, |
| 18 | + IdPrependingTreeprocessor, |
| 19 | + InsertHeadings, |
| 20 | + RemoveHeadings, |
| 21 | +) |
| 22 | +from markdown_exec._internal.rendering import ( |
| 23 | + MarkdownConfig, |
| 24 | + MarkdownConverter, |
| 25 | + add_source, |
| 26 | + code_block, |
| 27 | + markdown_config, |
| 28 | + tabbed, |
| 29 | +) |
| 30 | + |
| 31 | +__all__ = [ |
| 32 | + "MARKDOWN_EXEC_AUTO", |
| 33 | + "ExecutionError", |
| 34 | + "HeadingReportingTreeprocessor", |
| 35 | + "IdPrependingTreeprocessor", |
| 36 | + "InsertHeadings", |
| 37 | + "MarkdownConfig", |
| 38 | + "MarkdownConverter", |
| 39 | + "MarkdownExecPlugin", |
| 40 | + "MarkdownExecPluginConfig", |
| 41 | + "RemoveHeadings", |
| 42 | + "add_source", |
| 43 | + "base_format", |
| 44 | + "code_block", |
| 45 | + "console_width", |
| 46 | + "default_tabs", |
| 47 | + "formatter", |
| 48 | + "formatters", |
| 49 | + "get_logger", |
| 50 | + "markdown_config", |
| 51 | + "patch_loggers", |
| 52 | + "tabbed", |
| 53 | + "validator", |
| 54 | + "working_directory", |
| 55 | +] |
0 commit comments