MDit 0.0.0.dev1__tar.gz → 0.0.0.dev3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/PKG-INFO +12 -9
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/pyproject.toml +12 -10
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/src/MDit.egg-info/PKG-INFO +12 -9
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/src/MDit.egg-info/SOURCES.txt +5 -2
- mdit-0.0.0.dev3/src/MDit.egg-info/requires.txt +23 -0
- mdit-0.0.0.dev3/src/mdit/__init__.py +220 -0
- mdit-0.0.0.dev3/src/mdit/container.py +209 -0
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/src/mdit/data/schema.py +7 -2
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/src/mdit/display.py +13 -0
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/src/mdit/document.py +60 -69
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/src/mdit/element.py +1425 -482
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/src/mdit/generate.py +8 -6
- mdit-0.0.0.dev3/src/mdit/protocol.py +47 -0
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/src/mdit/render.py +33 -45
- mdit-0.0.0.dev3/src/mdit/renderable.py +69 -0
- mdit-0.0.0.dev3/src/mdit/target/__init__.py +315 -0
- mdit-0.0.0.dev3/src/mdit/target/md.py +166 -0
- mdit-0.0.0.dev3/src/mdit/target/rich.py +502 -0
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/src/mdit/template.py +1 -1
- mdit-0.0.0.dev1/src/MDit.egg-info/requires.txt +0 -20
- mdit-0.0.0.dev1/src/mdit/__init__.py +0 -133
- mdit-0.0.0.dev1/src/mdit/container.py +0 -195
- mdit-0.0.0.dev1/src/mdit/protocol.py +0 -90
- mdit-0.0.0.dev1/src/mdit/target.py +0 -202
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/README.md +0 -0
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/setup.cfg +0 -0
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/src/MDit.egg-info/dependency_links.txt +0 -0
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/src/MDit.egg-info/not-zip-safe +0 -0
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/src/MDit.egg-info/top_level.txt +0 -0
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/src/mdit/data/__init__.py +0 -0
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/src/mdit/data/file.py +0 -0
- {mdit-0.0.0.dev1 → mdit-0.0.0.dev3}/src/mdit/parse.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: MDit
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev3
|
|
4
4
|
Requires-Python: >=3.10
|
|
5
5
|
Requires-Dist: sphinx<8
|
|
6
6
|
Requires-Dist: myst-parser<4,>3
|
|
@@ -13,12 +13,15 @@ Requires-Dist: linkify-it-py
|
|
|
13
13
|
Requires-Dist: readme-renderer
|
|
14
14
|
Requires-Dist: cmarkgfm
|
|
15
15
|
Requires-Dist: zundler
|
|
16
|
-
Requires-Dist: PkgData
|
|
17
|
-
Requires-Dist: PySerials
|
|
18
|
-
Requires-Dist: PyLinks
|
|
19
|
-
Requires-Dist: PyBadger
|
|
20
|
-
Requires-Dist: PyColorIt
|
|
21
16
|
Requires-Dist: IPython
|
|
22
|
-
Requires-Dist:
|
|
23
|
-
Requires-Dist:
|
|
24
|
-
Requires-Dist:
|
|
17
|
+
Requires-Dist: jupyterlab_myst
|
|
18
|
+
Requires-Dist: pygments
|
|
19
|
+
Requires-Dist: rich
|
|
20
|
+
Requires-Dist: PkgData==0.0.0.dev3
|
|
21
|
+
Requires-Dist: PySerials==0.0.0.dev7
|
|
22
|
+
Requires-Dist: PyLinks==0.0.0.dev27
|
|
23
|
+
Requires-Dist: PyBadger==0.0.0.dev8
|
|
24
|
+
Requires-Dist: PyColorIt==0.0.0.dev5
|
|
25
|
+
Requires-Dist: ProtocolMan==0.0.0.dev2
|
|
26
|
+
Requires-Dist: HTMP==0.0.0.dev3
|
|
27
|
+
Requires-Dist: ANSI-SGR==0.0.0.dev9
|
|
@@ -17,7 +17,7 @@ namespaces = true
|
|
|
17
17
|
# ----------------------------------------- Project Metadata -------------------------------------
|
|
18
18
|
#
|
|
19
19
|
[project]
|
|
20
|
-
version = "0.0.0.
|
|
20
|
+
version = "0.0.0.dev3"
|
|
21
21
|
name = "MDit"
|
|
22
22
|
requires-python = ">=3.10"
|
|
23
23
|
dependencies = [
|
|
@@ -32,14 +32,16 @@ dependencies = [
|
|
|
32
32
|
"readme-renderer",
|
|
33
33
|
"cmarkgfm",
|
|
34
34
|
"zundler",
|
|
35
|
-
"PkgData",
|
|
36
|
-
"PySerials",
|
|
37
|
-
"PyLinks",
|
|
38
|
-
"PyBadger",
|
|
39
|
-
"PyColorIt",
|
|
40
35
|
"IPython",
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
|
|
36
|
+
"jupyterlab_myst",
|
|
37
|
+
"pygments",
|
|
38
|
+
"rich",
|
|
39
|
+
"PkgData == 0.0.0.dev3",
|
|
40
|
+
"PySerials == 0.0.0.dev7",
|
|
41
|
+
"PyLinks == 0.0.0.dev27",
|
|
42
|
+
"PyBadger == 0.0.0.dev8",
|
|
43
|
+
"PyColorIt == 0.0.0.dev5",
|
|
44
|
+
"ProtocolMan == 0.0.0.dev2",
|
|
45
|
+
"HTMP == 0.0.0.dev3",
|
|
46
|
+
"ANSI-SGR == 0.0.0.dev9",
|
|
45
47
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: MDit
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev3
|
|
4
4
|
Requires-Python: >=3.10
|
|
5
5
|
Requires-Dist: sphinx<8
|
|
6
6
|
Requires-Dist: myst-parser<4,>3
|
|
@@ -13,12 +13,15 @@ Requires-Dist: linkify-it-py
|
|
|
13
13
|
Requires-Dist: readme-renderer
|
|
14
14
|
Requires-Dist: cmarkgfm
|
|
15
15
|
Requires-Dist: zundler
|
|
16
|
-
Requires-Dist: PkgData
|
|
17
|
-
Requires-Dist: PySerials
|
|
18
|
-
Requires-Dist: PyLinks
|
|
19
|
-
Requires-Dist: PyBadger
|
|
20
|
-
Requires-Dist: PyColorIt
|
|
21
16
|
Requires-Dist: IPython
|
|
22
|
-
Requires-Dist:
|
|
23
|
-
Requires-Dist:
|
|
24
|
-
Requires-Dist:
|
|
17
|
+
Requires-Dist: jupyterlab_myst
|
|
18
|
+
Requires-Dist: pygments
|
|
19
|
+
Requires-Dist: rich
|
|
20
|
+
Requires-Dist: PkgData==0.0.0.dev3
|
|
21
|
+
Requires-Dist: PySerials==0.0.0.dev7
|
|
22
|
+
Requires-Dist: PyLinks==0.0.0.dev27
|
|
23
|
+
Requires-Dist: PyBadger==0.0.0.dev8
|
|
24
|
+
Requires-Dist: PyColorIt==0.0.0.dev5
|
|
25
|
+
Requires-Dist: ProtocolMan==0.0.0.dev2
|
|
26
|
+
Requires-Dist: HTMP==0.0.0.dev3
|
|
27
|
+
Requires-Dist: ANSI-SGR==0.0.0.dev9
|
|
@@ -15,8 +15,11 @@ src/mdit/generate.py
|
|
|
15
15
|
src/mdit/parse.py
|
|
16
16
|
src/mdit/protocol.py
|
|
17
17
|
src/mdit/render.py
|
|
18
|
-
src/mdit/
|
|
18
|
+
src/mdit/renderable.py
|
|
19
19
|
src/mdit/template.py
|
|
20
20
|
src/mdit/data/__init__.py
|
|
21
21
|
src/mdit/data/file.py
|
|
22
|
-
src/mdit/data/schema.py
|
|
22
|
+
src/mdit/data/schema.py
|
|
23
|
+
src/mdit/target/__init__.py
|
|
24
|
+
src/mdit/target/md.py
|
|
25
|
+
src/mdit/target/rich.py
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
sphinx<8
|
|
2
|
+
myst-parser<4,>3
|
|
3
|
+
pydata-sphinx-theme
|
|
4
|
+
sphinx-togglebutton
|
|
5
|
+
sphinx-design
|
|
6
|
+
markdown-it-py
|
|
7
|
+
mdit-py-plugins
|
|
8
|
+
linkify-it-py
|
|
9
|
+
readme-renderer
|
|
10
|
+
cmarkgfm
|
|
11
|
+
zundler
|
|
12
|
+
IPython
|
|
13
|
+
jupyterlab_myst
|
|
14
|
+
pygments
|
|
15
|
+
rich
|
|
16
|
+
PkgData==0.0.0.dev3
|
|
17
|
+
PySerials==0.0.0.dev7
|
|
18
|
+
PyLinks==0.0.0.dev27
|
|
19
|
+
PyBadger==0.0.0.dev8
|
|
20
|
+
PyColorIt==0.0.0.dev5
|
|
21
|
+
ProtocolMan==0.0.0.dev2
|
|
22
|
+
HTMP==0.0.0.dev3
|
|
23
|
+
ANSI-SGR==0.0.0.dev9
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"""Generate and process Markdown content.
|
|
2
|
+
|
|
3
|
+
References
|
|
4
|
+
----------
|
|
5
|
+
- [GitHub Flavored Markdown Spec](https://github.github.com/gfm/)
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import TYPE_CHECKING as _TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
from mdit import display
|
|
13
|
+
from mdit.container import Container, MDContainer
|
|
14
|
+
from mdit.document import Document
|
|
15
|
+
from mdit.generate import DocumentGenerator
|
|
16
|
+
from mdit import render, target, element, parse, protocol, template
|
|
17
|
+
|
|
18
|
+
if _TYPE_CHECKING:
|
|
19
|
+
from typing import Callable
|
|
20
|
+
from mdit.protocol import ContainerContentType, ContainerContentInputType, ContainerContentSingleInputType, Stringable, TargetConfig, TargetConfigs, MDTargetConfig, RichTargetConfig, ContainerContentInputType
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def generate(config: dict | list):
|
|
24
|
+
return DocumentGenerator().generate(config)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def document(
|
|
28
|
+
heading: element.Heading | MDContainer | ContainerContentInputType = None,
|
|
29
|
+
body: MDContainer | ContainerContentInputType = None,
|
|
30
|
+
section: Container | None = None,
|
|
31
|
+
footer: MDContainer | ContainerContentInputType = None,
|
|
32
|
+
frontmatter: dict | element.FrontMatter | None = None,
|
|
33
|
+
frontmatter_conditions: list[str] | None = None,
|
|
34
|
+
separate_sections: bool = False,
|
|
35
|
+
current_section_key: list[str | int] | None = None,
|
|
36
|
+
toctree_args: dict[str, str] | None = None,
|
|
37
|
+
toctree_dirhtml: bool = True,
|
|
38
|
+
target_configs_md: dict[str, MDTargetConfig | dict] | None = None,
|
|
39
|
+
target_configs_rich: dict[str, RichTargetConfig | dict] | None = None,
|
|
40
|
+
target_default: str = "sphinx",
|
|
41
|
+
deep_section_generator: Callable[[Document], str] | None = None,
|
|
42
|
+
content_separator_heading: str = "",
|
|
43
|
+
):
|
|
44
|
+
# Process target configs
|
|
45
|
+
target_configs = {}
|
|
46
|
+
for key, config in (target_configs_md or {}).items():
|
|
47
|
+
config_obj = config if isinstance(config, protocol.MDTargetConfig) else target.md.Config(**config)
|
|
48
|
+
target_configs[key] = config_obj
|
|
49
|
+
for key, config in (target_configs_rich or {}).items():
|
|
50
|
+
config_obj = config if isinstance(config, protocol.RichTargetConfig) else target.rich.Config(**config)
|
|
51
|
+
if key in target_configs:
|
|
52
|
+
raise ValueError(f"Target config key '{key}' already exists.")
|
|
53
|
+
target_configs[key] = config_obj
|
|
54
|
+
# Process heading
|
|
55
|
+
if heading and not isinstance(heading, element.Heading):
|
|
56
|
+
heading = element.heading(
|
|
57
|
+
content=heading,
|
|
58
|
+
target_configs=target_configs,
|
|
59
|
+
target_default=target_default,
|
|
60
|
+
)
|
|
61
|
+
body = to_block_container(body)
|
|
62
|
+
if isinstance(section, Container):
|
|
63
|
+
pass
|
|
64
|
+
elif not section:
|
|
65
|
+
section = section_container()
|
|
66
|
+
elif isinstance(section, dict):
|
|
67
|
+
section = section_container(**section)
|
|
68
|
+
elif isinstance(section, (list, tuple)):
|
|
69
|
+
section = section_container(*section)
|
|
70
|
+
else:
|
|
71
|
+
section = section_container(section)
|
|
72
|
+
footer = to_block_container(footer)
|
|
73
|
+
if isinstance(frontmatter, dict):
|
|
74
|
+
frontmatter = element.frontmatter(frontmatter)
|
|
75
|
+
return Document(
|
|
76
|
+
heading=heading,
|
|
77
|
+
body=body,
|
|
78
|
+
section=section,
|
|
79
|
+
footer=footer,
|
|
80
|
+
frontmatter=frontmatter,
|
|
81
|
+
frontmatter_conditions=frontmatter_conditions,
|
|
82
|
+
separate_sections=separate_sections,
|
|
83
|
+
current_section_key=current_section_key,
|
|
84
|
+
toctree_args=toctree_args,
|
|
85
|
+
toctree_dirhtml=toctree_dirhtml,
|
|
86
|
+
target_configs=target_configs,
|
|
87
|
+
target_default=target_default,
|
|
88
|
+
deep_section_generator=deep_section_generator,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
def block_container(
|
|
92
|
+
*contents: ContainerContentInputType,
|
|
93
|
+
html_container: Stringable | None = None,
|
|
94
|
+
html_container_attrs: dict | None = None,
|
|
95
|
+
html_container_conditions: list[str] | None = None,
|
|
96
|
+
target_configs: TargetConfigs = None,
|
|
97
|
+
target_default: str = "sphinx",
|
|
98
|
+
) -> MDContainer:
|
|
99
|
+
return container(
|
|
100
|
+
*contents,
|
|
101
|
+
content_separator="\n\n",
|
|
102
|
+
html_container=html_container,
|
|
103
|
+
html_container_attrs=html_container_attrs,
|
|
104
|
+
html_container_conditions=html_container_conditions,
|
|
105
|
+
target_configs=target_configs,
|
|
106
|
+
target_default=target_default,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def inline_container(
|
|
111
|
+
*contents: ContainerContentInputType,
|
|
112
|
+
separator: str = "",
|
|
113
|
+
html_container: Stringable | None = None,
|
|
114
|
+
html_container_attrs: dict | None = None,
|
|
115
|
+
html_container_conditions: list[str] | None = None,
|
|
116
|
+
target_configs: TargetConfigs = None,
|
|
117
|
+
target_default: str = "sphinx",
|
|
118
|
+
) -> MDContainer:
|
|
119
|
+
return container(
|
|
120
|
+
*contents,
|
|
121
|
+
content_separator=separator,
|
|
122
|
+
html_container=html_container,
|
|
123
|
+
html_container_attrs=html_container_attrs,
|
|
124
|
+
html_container_conditions=html_container_conditions,
|
|
125
|
+
target_configs=target_configs,
|
|
126
|
+
target_default=target_default,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def container(
|
|
131
|
+
*contents: ContainerContentInputType,
|
|
132
|
+
content_separator: str,
|
|
133
|
+
html_container: Stringable | None = None,
|
|
134
|
+
html_container_attrs: dict | None = None,
|
|
135
|
+
html_container_conditions: list[str] | None = None,
|
|
136
|
+
target_configs: TargetConfigs = None,
|
|
137
|
+
target_default: str = "sphinx",
|
|
138
|
+
) -> MDContainer:
|
|
139
|
+
container_ = MDContainer(
|
|
140
|
+
content_separator=content_separator,
|
|
141
|
+
html_container=html_container,
|
|
142
|
+
html_container_attrs=html_container_attrs,
|
|
143
|
+
html_container_conditions=html_container_conditions,
|
|
144
|
+
target_configs=target_configs,
|
|
145
|
+
target_default=target_default,
|
|
146
|
+
)
|
|
147
|
+
container_.extend(list(contents))
|
|
148
|
+
return container_
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def section_container(
|
|
152
|
+
*unlabeled_contents: ContainerContentInputType,
|
|
153
|
+
**labeled_contents: ContainerContentInputType,
|
|
154
|
+
) -> Container:
|
|
155
|
+
container_ = Container()
|
|
156
|
+
container_.extend(*unlabeled_contents, **labeled_contents)
|
|
157
|
+
return container_
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def to_block_container(
|
|
161
|
+
content: MDContainer | ContainerContentInputType,
|
|
162
|
+
separator: str = "\n\n",
|
|
163
|
+
html_container: Stringable | None = None,
|
|
164
|
+
html_container_attrs: dict | None = None,
|
|
165
|
+
html_container_conditions: list[str] | None = None,
|
|
166
|
+
target_configs: TargetConfigs = None,
|
|
167
|
+
target_default: str = "sphinx",
|
|
168
|
+
) -> MDContainer:
|
|
169
|
+
return to_md_container(
|
|
170
|
+
content,
|
|
171
|
+
content_separator=separator,
|
|
172
|
+
html_container=html_container,
|
|
173
|
+
html_container_attrs=html_container_attrs,
|
|
174
|
+
html_container_conditions=html_container_conditions,
|
|
175
|
+
target_configs=target_configs,
|
|
176
|
+
target_default=target_default,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def to_inline_container(
|
|
181
|
+
content: MDContainer | ContainerContentInputType,
|
|
182
|
+
separator: str = "",
|
|
183
|
+
html_container: Stringable | None = None,
|
|
184
|
+
html_container_attrs: dict | None = None,
|
|
185
|
+
html_container_conditions: list[str] | None = None,
|
|
186
|
+
target_configs: TargetConfigs = None,
|
|
187
|
+
target_default: str = "sphinx",
|
|
188
|
+
) -> MDContainer:
|
|
189
|
+
return to_md_container(
|
|
190
|
+
content,
|
|
191
|
+
content_separator=separator,
|
|
192
|
+
html_container=html_container,
|
|
193
|
+
html_container_attrs=html_container_attrs,
|
|
194
|
+
html_container_conditions=html_container_conditions,
|
|
195
|
+
target_configs=target_configs,
|
|
196
|
+
target_default=target_default,
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def to_md_container(
|
|
201
|
+
content: MDContainer | ContainerContentInputType,
|
|
202
|
+
content_separator: str,
|
|
203
|
+
html_container: Stringable | None = None,
|
|
204
|
+
html_container_attrs: dict | None = None,
|
|
205
|
+
html_container_conditions: list[str] | None = None,
|
|
206
|
+
target_configs: TargetConfigs = None,
|
|
207
|
+
target_default: str = "sphinx",
|
|
208
|
+
) -> MDContainer:
|
|
209
|
+
if isinstance(content, MDContainer):
|
|
210
|
+
return content
|
|
211
|
+
container_ = MDContainer(
|
|
212
|
+
content_separator=content_separator,
|
|
213
|
+
html_container=html_container,
|
|
214
|
+
html_container_attrs=html_container_attrs,
|
|
215
|
+
html_container_conditions=html_container_conditions,
|
|
216
|
+
target_configs=target_configs,
|
|
217
|
+
target_default=target_default,
|
|
218
|
+
)
|
|
219
|
+
container_.extend(content)
|
|
220
|
+
return container_
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING as _TYPE_CHECKING, NamedTuple as _NamedTuple
|
|
4
|
+
|
|
5
|
+
import htmp as _htmp
|
|
6
|
+
import rich
|
|
7
|
+
import rich.text
|
|
8
|
+
import rich.markdown
|
|
9
|
+
|
|
10
|
+
from mdit.protocol import MDITRenderable as _MDCode
|
|
11
|
+
from mdit.renderable import Renderable as _Renderable
|
|
12
|
+
|
|
13
|
+
if _TYPE_CHECKING:
|
|
14
|
+
from rich.console import RenderableType
|
|
15
|
+
from mdit.protocol import ContainerContentType, ContainerContentConditionType, ContainerContentInputType, TargetConfigs, Stringable, MDTargetConfig, RichTargetConfig
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ContainerContent(_NamedTuple):
|
|
19
|
+
content: ContainerContentType
|
|
20
|
+
conditions: list[str]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Container:
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
data: dict[str | int, ContainerContent] | None = None,
|
|
28
|
+
*args,
|
|
29
|
+
**kwargs
|
|
30
|
+
):
|
|
31
|
+
self._data = data or {}
|
|
32
|
+
super().__init__(*args, **kwargs)
|
|
33
|
+
return
|
|
34
|
+
|
|
35
|
+
def append(
|
|
36
|
+
self,
|
|
37
|
+
content: ContainerContentType,
|
|
38
|
+
conditions: ContainerContentConditionType = None,
|
|
39
|
+
key: str | int | None = None
|
|
40
|
+
) -> str | int:
|
|
41
|
+
if not key:
|
|
42
|
+
key = max((key for key in self._data.keys() if isinstance(key, int)), default=-1) + 1
|
|
43
|
+
if key in self._data:
|
|
44
|
+
raise ValueError("Key already exists in content.")
|
|
45
|
+
if not conditions:
|
|
46
|
+
conditions = []
|
|
47
|
+
elif isinstance(conditions, str):
|
|
48
|
+
conditions = [conditions]
|
|
49
|
+
else:
|
|
50
|
+
conditions = list(conditions)
|
|
51
|
+
self._data[key] = ContainerContent(content=content, conditions=conditions)
|
|
52
|
+
return key
|
|
53
|
+
|
|
54
|
+
def extend(self, *unlabeled_contents: ContainerContentInputType, **labeled_contents: ContainerContentInputType) -> list[str | int]:
|
|
55
|
+
|
|
56
|
+
def resolve_value(input_values):
|
|
57
|
+
if not input_values:
|
|
58
|
+
return
|
|
59
|
+
if isinstance(input_values, list):
|
|
60
|
+
for input_value in input_values:
|
|
61
|
+
yield from resolve_value(input_value)
|
|
62
|
+
elif isinstance(input_values, tuple):
|
|
63
|
+
val = input_values[0]
|
|
64
|
+
cond = input_values[1] if len(input_values) > 1 else None
|
|
65
|
+
key = input_values[2] if len(input_values) > 2 else None
|
|
66
|
+
yield val, cond, key
|
|
67
|
+
elif isinstance(input_values, dict):
|
|
68
|
+
for k, v in input_values.items():
|
|
69
|
+
key = k
|
|
70
|
+
if isinstance(v, (list, tuple)):
|
|
71
|
+
val = v[0]
|
|
72
|
+
cond = v[1] if len(v) > 1 else None
|
|
73
|
+
else:
|
|
74
|
+
val = v
|
|
75
|
+
cond = None
|
|
76
|
+
yield val, cond, key
|
|
77
|
+
else:
|
|
78
|
+
yield input_values, None, None
|
|
79
|
+
|
|
80
|
+
added_keys = []
|
|
81
|
+
if unlabeled_contents:
|
|
82
|
+
first_available_key = max(
|
|
83
|
+
(key for key in self._data.keys() if isinstance(key, int)), default=-1
|
|
84
|
+
) + 1
|
|
85
|
+
for idx, value in enumerate(unlabeled_contents):
|
|
86
|
+
for content, conditions, key in resolve_value(value):
|
|
87
|
+
added_keys.append(self.append(content, conditions, key or first_available_key + idx))
|
|
88
|
+
if labeled_contents:
|
|
89
|
+
for key, value in labeled_contents.items():
|
|
90
|
+
for content, conditions, sub_key in resolve_value(value):
|
|
91
|
+
final_key = key if sub_key is None else f"{key}.{sub_key}"
|
|
92
|
+
added_keys.append(self.append(content, conditions, final_key))
|
|
93
|
+
return added_keys
|
|
94
|
+
|
|
95
|
+
def elements(
|
|
96
|
+
self,
|
|
97
|
+
target: TargetConfigs | None = None,
|
|
98
|
+
filters: str | list[str] | None = None,
|
|
99
|
+
source: bool = False,
|
|
100
|
+
) -> list:
|
|
101
|
+
elements = []
|
|
102
|
+
if isinstance(filters, str):
|
|
103
|
+
filters = [filters]
|
|
104
|
+
for content, conditions in self.values():
|
|
105
|
+
if not filters or not conditions or any(filter in conditions for filter in filters):
|
|
106
|
+
if not source:
|
|
107
|
+
elements.append(content)
|
|
108
|
+
elif isinstance(content, _MDCode):
|
|
109
|
+
elements.append(content.source(target=target, filters=filters))
|
|
110
|
+
else:
|
|
111
|
+
elements.append(str(content))
|
|
112
|
+
return elements
|
|
113
|
+
|
|
114
|
+
def get(self, key: str | int, default=None):
|
|
115
|
+
return self._data.get(key, default)
|
|
116
|
+
|
|
117
|
+
def keys(self):
|
|
118
|
+
return self._data.keys()
|
|
119
|
+
|
|
120
|
+
def values(self):
|
|
121
|
+
return self._data.values()
|
|
122
|
+
|
|
123
|
+
def items(self):
|
|
124
|
+
return self._data.items()
|
|
125
|
+
|
|
126
|
+
def __getitem__(self, item):
|
|
127
|
+
return self._data[item]
|
|
128
|
+
|
|
129
|
+
def __setitem__(self, key, value):
|
|
130
|
+
self._data[key] = value
|
|
131
|
+
return
|
|
132
|
+
|
|
133
|
+
def __contains__(self, item):
|
|
134
|
+
return item in self._data
|
|
135
|
+
|
|
136
|
+
def __bool__(self):
|
|
137
|
+
return bool(self._data)
|
|
138
|
+
|
|
139
|
+
def __len__(self):
|
|
140
|
+
return len(self._data)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class MDContainer(Container, _Renderable):
|
|
144
|
+
# Multiple inheritance: https://stackoverflow.com/questions/9575409/calling-parent-class-init-with-multiple-inheritance-whats-the-right-way
|
|
145
|
+
def __init__(
|
|
146
|
+
self,
|
|
147
|
+
content: dict[str | int, ContainerContent] | None = None,
|
|
148
|
+
content_separator: str = "\n\n",
|
|
149
|
+
html_container: Stringable | None = None,
|
|
150
|
+
html_container_attrs: dict | None = None,
|
|
151
|
+
html_container_conditions: list[str] | None = None,
|
|
152
|
+
target_configs: TargetConfigs = None,
|
|
153
|
+
target_default: str = "sphinx"
|
|
154
|
+
):
|
|
155
|
+
super().__init__(
|
|
156
|
+
data=content,
|
|
157
|
+
target_configs=target_configs,
|
|
158
|
+
target_default=target_default
|
|
159
|
+
)
|
|
160
|
+
self.content_separator = content_separator
|
|
161
|
+
self.html_container = html_container
|
|
162
|
+
self.html_container_attrs = html_container_attrs or {}
|
|
163
|
+
self.html_container_conditions = html_container_conditions or []
|
|
164
|
+
return
|
|
165
|
+
|
|
166
|
+
@property
|
|
167
|
+
def code_fence_count(self) -> int:
|
|
168
|
+
return max(
|
|
169
|
+
(
|
|
170
|
+
content.code_fence_count if isinstance(content, _MDCode)
|
|
171
|
+
else self._count_code_fence(str(content))
|
|
172
|
+
for content, _ in self._data.values()
|
|
173
|
+
),
|
|
174
|
+
default=0,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
def _source_rich(self, target: RichTargetConfig, filters: str | list[str] | None = None) -> RenderableType:
|
|
178
|
+
block_container = "\n" in self.content_separator
|
|
179
|
+
elements = self.elements(target=target, filters=filters, source=True)
|
|
180
|
+
if not elements:
|
|
181
|
+
return ""
|
|
182
|
+
if block_container:
|
|
183
|
+
group = [
|
|
184
|
+
rich.markdown.Markdown(element) if isinstance(element, str) else element
|
|
185
|
+
for element in elements
|
|
186
|
+
]
|
|
187
|
+
return rich.console.Group(*group) if len(group) > 1 else group[0]
|
|
188
|
+
text = rich.text.Text()
|
|
189
|
+
for element in elements[:-1]:
|
|
190
|
+
text.append(element)
|
|
191
|
+
text.append(self.content_separator)
|
|
192
|
+
text.append(elements[-1])
|
|
193
|
+
return text
|
|
194
|
+
|
|
195
|
+
def _source_md(self, target: MDTargetConfig, filters: str | list[str] | None = None) -> str:
|
|
196
|
+
elements = self.elements(target=target, filters=filters, source=True)
|
|
197
|
+
elements_str = self.content_separator.join(elements)
|
|
198
|
+
if self.html_container and self.html_container_attrs and (
|
|
199
|
+
not filters
|
|
200
|
+
or not self.html_container_conditions
|
|
201
|
+
or any(filter in self.html_container_conditions for filter in filters)
|
|
202
|
+
):
|
|
203
|
+
container_func = getattr(_htmp.element, str(self.html_container))
|
|
204
|
+
return container_func(_htmp.elementor.markdown(elements_str), self.html_container_attrs).source(
|
|
205
|
+
indent=-1)
|
|
206
|
+
return elements_str
|
|
207
|
+
|
|
208
|
+
def __str__(self) -> str:
|
|
209
|
+
return self.source()
|
|
@@ -10,6 +10,10 @@ import pyserials as _ps
|
|
|
10
10
|
from mdit.data import file as _file
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
_REGISTRY = None
|
|
14
|
+
_SCHEMATA = None
|
|
15
|
+
|
|
16
|
+
|
|
13
17
|
def make_registry(
|
|
14
18
|
dynamic: bool = False,
|
|
15
19
|
crawl: bool = True,
|
|
@@ -33,6 +37,9 @@ def make_registry(
|
|
|
33
37
|
|
|
34
38
|
|
|
35
39
|
def validate(data: dict, schema_id: str):
|
|
40
|
+
global _REGISTRY, _SCHEMATA
|
|
41
|
+
if not _REGISTRY:
|
|
42
|
+
_REGISTRY, _SCHEMATA = make_registry()
|
|
36
43
|
_ps.validate.jsonschema(
|
|
37
44
|
data=data,
|
|
38
45
|
schema=_SCHEMATA[schema_id],
|
|
@@ -41,5 +48,3 @@ def validate(data: dict, schema_id: str):
|
|
|
41
48
|
)
|
|
42
49
|
return
|
|
43
50
|
|
|
44
|
-
|
|
45
|
-
# _REGISTRY, _SCHEMATA = make_registry()
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
"""Display HTML and Markdown content in web browser or IPython notebook."""
|
|
2
|
+
from __future__ import annotations as _annotations
|
|
3
|
+
|
|
4
|
+
from typing import TYPE_CHECKING as _TYPE_CHECKING
|
|
2
5
|
|
|
3
6
|
import webbrowser as _webbrowser
|
|
4
7
|
import tempfile as _tempfile
|
|
5
8
|
import time as _time
|
|
6
9
|
|
|
10
|
+
import rich as _rich
|
|
7
11
|
from IPython import display as _display
|
|
8
12
|
|
|
13
|
+
if _TYPE_CHECKING:
|
|
14
|
+
from rich.console import Console
|
|
15
|
+
|
|
9
16
|
|
|
10
17
|
def browser(content: str) -> None:
|
|
11
18
|
"""Display HTML content in a web browser.
|
|
@@ -44,3 +51,9 @@ def ipython(content: str, as_md: bool = True) -> None:
|
|
|
44
51
|
renderer = _display.Markdown if as_md else _display.HTML
|
|
45
52
|
_display.display(renderer(content))
|
|
46
53
|
return
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def console(content, output: Console | None = None) -> None:
|
|
57
|
+
writer = output or _rich
|
|
58
|
+
writer.print(content)
|
|
59
|
+
return
|