mdforge 0.2.2__tar.gz → 0.2.3__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.
- {mdforge-0.2.2 → mdforge-0.2.3}/PKG-INFO +14 -14
- {mdforge-0.2.2 → mdforge-0.2.3}/README.md +1 -1
- mdforge-0.2.3/pyproject.toml +107 -0
- mdforge-0.2.3/src/mdforge/__init__.py +105 -0
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/_norm.py +13 -18
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/_utils.py +3 -5
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/container.py +8 -24
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/document.py +3 -1
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/element.py +22 -25
- mdforge-0.2.3/src/mdforge/elements/__init__.py +71 -0
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/_image.py +1 -1
- mdforge-0.2.3/src/mdforge/elements/block/__init__.py +60 -0
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/basic.py +8 -12
- mdforge-0.2.3/src/mdforge/elements/block/lists/__init__.py +33 -0
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/lists/definition.py +5 -11
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/lists/item.py +10 -11
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/section.py +6 -8
- mdforge-0.2.3/src/mdforge/elements/block/table/__init__.py +22 -0
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/table/_context.py +2 -5
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/table/_flavors/flavors.py +7 -12
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/table/_flavors/frame/__init__.py +1 -2
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/table/_flavors/frame/context.py +52 -82
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/table/_flavors/frame/variant.py +2 -4
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/table/_flavors/frame/variants.py +1 -1
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/table/_params.py +33 -47
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/table/_variant.py +6 -13
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/table/_vcell.py +16 -14
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/table/cell.py +6 -12
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/table/table.py +10 -19
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/text.py +1 -1
- mdforge-0.2.3/src/mdforge/elements/inline/__init__.py +39 -0
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/inline/basic.py +2 -3
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/inline/text.py +14 -17
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/exceptions.py +2 -2
- mdforge-0.2.3/src/mdforge/py.typed +0 -0
- mdforge-0.2.2/mdforge/__init__.py +0 -15
- mdforge-0.2.2/mdforge/elements/__init__.py +0 -11
- mdforge-0.2.2/mdforge/elements/block/__init__.py +0 -14
- mdforge-0.2.2/mdforge/elements/block/lists/__init__.py +0 -11
- mdforge-0.2.2/mdforge/elements/block/table/__init__.py +0 -11
- mdforge-0.2.2/mdforge/elements/inline/__init__.py +0 -11
- mdforge-0.2.2/pyproject.toml +0 -71
- {mdforge-0.2.2 → mdforge-0.2.3}/LICENSE +0 -0
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/elements/block/table/_flavors/list/__init__.py +0 -0
- {mdforge-0.2.2 → mdforge-0.2.3/src}/mdforge/types.py +0 -0
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: mdforge
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Pythonic multi-flavor Markdown generator
|
|
5
5
|
Author: mm21
|
|
6
|
-
Author-email: mm21.dev@gmail.com
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Classifier: Operating System :: OS Independent
|
|
10
|
-
Classifier: Typing :: Typed
|
|
11
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
6
|
+
Author-email: mm21 <mm21.dev@gmail.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
12
9
|
Classifier: Development Status :: 3 - Alpha
|
|
13
10
|
Classifier: Natural Language :: English
|
|
14
|
-
Classifier:
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
15
12
|
Classifier: Programming Language :: Python :: 3
|
|
16
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
14
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Dist: pyyaml>=6.0.2,<7
|
|
20
|
+
Requires-Python: >=3.12, <4.0
|
|
21
|
+
Project-URL: homepage, https://github.com/mm21/mdforge
|
|
21
22
|
Description-Content-Type: text/markdown
|
|
22
23
|
|
|
23
24
|
# MDForge
|
|
@@ -378,7 +379,7 @@ doc += Table(
|
|
|
378
379
|
],
|
|
379
380
|
header=[
|
|
380
381
|
[Cell("Column 1", rspan=2), Cell("Columns 2 & 3", cspan=2)],
|
|
381
|
-
["Column 2", "Column 3"],
|
|
382
|
+
[Cell("Column 2"), Cell("Column 3")],
|
|
382
383
|
],
|
|
383
384
|
block=True,
|
|
384
385
|
)
|
|
@@ -616,4 +617,3 @@ doc += Strikethrough("This text is struck through")
|
|
|
616
617
|
extensions = doc.get_pandoc_extensions()
|
|
617
618
|
assert extensions == ["header_attributes", "strikeout"]
|
|
618
619
|
```
|
|
619
|
-
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# managed (in part) by pyprojkit: https://github.com/mm21/pyprojkit
|
|
2
|
+
|
|
3
|
+
[project]
|
|
4
|
+
authors = [{name = "mm21", email = "mm21.dev@gmail.com"}]
|
|
5
|
+
classifiers = [
|
|
6
|
+
"Development Status :: 3 - Alpha",
|
|
7
|
+
"Natural Language :: English",
|
|
8
|
+
"Operating System :: OS Independent",
|
|
9
|
+
"Programming Language :: Python :: 3", # pyprojkit-managed
|
|
10
|
+
"Programming Language :: Python :: 3.12", # pyprojkit-managed
|
|
11
|
+
"Programming Language :: Python :: 3.13", # pyprojkit-managed
|
|
12
|
+
"Programming Language :: Python :: 3.14", # pyprojkit-managed
|
|
13
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
14
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
15
|
+
"Typing :: Typed" # pyprojkit-managed
|
|
16
|
+
]
|
|
17
|
+
dependencies = [
|
|
18
|
+
"pyyaml>=6.0.2,<7"
|
|
19
|
+
]
|
|
20
|
+
description = "Pythonic multi-flavor Markdown generator"
|
|
21
|
+
license = "MIT"
|
|
22
|
+
license-files = ["LICENSE"]
|
|
23
|
+
name = "mdforge"
|
|
24
|
+
readme = "README.md"
|
|
25
|
+
requires-python = ">=3.12,<4.0" # pyprojkit-managed
|
|
26
|
+
version = "0.2.3"
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
homepage = "https://github.com/mm21/mdforge"
|
|
30
|
+
|
|
31
|
+
[dependency-groups]
|
|
32
|
+
dev = [
|
|
33
|
+
"pyprojkit[all]>=0.8.1,<0.9.0",
|
|
34
|
+
"pytest-powerpack>=0.1.5,<0.2",
|
|
35
|
+
"types-pyyaml>=6.0.12,<7"
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[build-system]
|
|
39
|
+
build-backend = "uv_build"
|
|
40
|
+
requires = ["uv_build>=0.11.6,<0.12.0"]
|
|
41
|
+
|
|
42
|
+
[tool.autoflake]
|
|
43
|
+
in_place = true # pyprojkit-managed
|
|
44
|
+
recursive = true # pyprojkit-managed
|
|
45
|
+
remove-all-unused-imports = true # pyprojkit-managed
|
|
46
|
+
remove-unused-variables = true # pyprojkit-managed
|
|
47
|
+
|
|
48
|
+
[tool.black]
|
|
49
|
+
quiet = true # pyprojkit-managed
|
|
50
|
+
target-version = [
|
|
51
|
+
"py312",
|
|
52
|
+
"py313",
|
|
53
|
+
"py314"
|
|
54
|
+
] # pyprojkit-managed
|
|
55
|
+
|
|
56
|
+
[tool.coverage.report]
|
|
57
|
+
exclude_lines = [
|
|
58
|
+
"if TYPE_CHECKING:",
|
|
59
|
+
"\\.\\.\\.$"
|
|
60
|
+
] # pyprojkit-managed
|
|
61
|
+
|
|
62
|
+
[tool.coverage.run]
|
|
63
|
+
data_file = "__cache__/.coverage" # pyprojkit-managed
|
|
64
|
+
|
|
65
|
+
[tool.docfmt]
|
|
66
|
+
force-reflow = true # pyprojkit-managed
|
|
67
|
+
in-place = true # pyprojkit-managed
|
|
68
|
+
recursive = true # pyprojkit-managed
|
|
69
|
+
summary-on-own-line = true # pyprojkit-managed
|
|
70
|
+
|
|
71
|
+
[tool.doit]
|
|
72
|
+
dep_file = "__cache__/.doit.db" # pyprojkit-managed
|
|
73
|
+
verbosity = 2 # pyprojkit-managed
|
|
74
|
+
|
|
75
|
+
[tool.isort]
|
|
76
|
+
profile = "black" # pyprojkit-managed
|
|
77
|
+
quiet = true # pyprojkit-managed
|
|
78
|
+
|
|
79
|
+
[tool.mypy]
|
|
80
|
+
check_untyped_defs = true # pyprojkit-managed
|
|
81
|
+
python_version = "3.12" # pyprojkit-managed
|
|
82
|
+
|
|
83
|
+
[[tool.mypy.overrides]]
|
|
84
|
+
ignore_missing_imports = true
|
|
85
|
+
module = ["pytest_powerpack", "pytest_powerpack.*"]
|
|
86
|
+
|
|
87
|
+
[tool.nox]
|
|
88
|
+
default_venv_backend = "uv" # pyprojkit-managed
|
|
89
|
+
envdir = "__cache__/nox" # pyprojkit-managed
|
|
90
|
+
|
|
91
|
+
[tool.pyright]
|
|
92
|
+
pythonVersion = "3.12" # pyprojkit-managed
|
|
93
|
+
|
|
94
|
+
[tool.pytest.ini_options]
|
|
95
|
+
addopts = "--import-mode=importlib -s -v -rA" # pyprojkit-managed
|
|
96
|
+
cache_dir = "__cache__/pytest" # pyprojkit-managed
|
|
97
|
+
powerpack_underline = true
|
|
98
|
+
testpaths = ["test"] # pyprojkit-managed
|
|
99
|
+
|
|
100
|
+
[tool.tomlsort]
|
|
101
|
+
sort_first = [
|
|
102
|
+
"project",
|
|
103
|
+
"dependency-groups",
|
|
104
|
+
"build-system"
|
|
105
|
+
] # pyprojkit-managed
|
|
106
|
+
sort_table_keys = true # pyprojkit-managed
|
|
107
|
+
spaces_before_inline_comment = 2 # pyprojkit-managed
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MDForge: Forge Markdown files in a Python way.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
__submodules__ = [
|
|
6
|
+
"types",
|
|
7
|
+
"document",
|
|
8
|
+
"element",
|
|
9
|
+
"container",
|
|
10
|
+
"elements",
|
|
11
|
+
"exceptions",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
# isort: off
|
|
15
|
+
# <AUTOGEN_INIT>
|
|
16
|
+
from .types import (
|
|
17
|
+
FlavorType,
|
|
18
|
+
AlignType,
|
|
19
|
+
)
|
|
20
|
+
from .document import (
|
|
21
|
+
Document,
|
|
22
|
+
)
|
|
23
|
+
from .element import (
|
|
24
|
+
BaseElement,
|
|
25
|
+
BaseInlineElement,
|
|
26
|
+
BaseBlockElement,
|
|
27
|
+
Attributes,
|
|
28
|
+
)
|
|
29
|
+
from .container import (
|
|
30
|
+
InlineContainer,
|
|
31
|
+
BlockContainer,
|
|
32
|
+
)
|
|
33
|
+
from .elements import (
|
|
34
|
+
Section,
|
|
35
|
+
Heading,
|
|
36
|
+
BlockImage,
|
|
37
|
+
Paragraph,
|
|
38
|
+
BlockText,
|
|
39
|
+
ListItemType,
|
|
40
|
+
ListItem,
|
|
41
|
+
BulletList,
|
|
42
|
+
NumberedList,
|
|
43
|
+
BaseItemList,
|
|
44
|
+
DefinitionItem,
|
|
45
|
+
DefinitionList,
|
|
46
|
+
Table,
|
|
47
|
+
Cell,
|
|
48
|
+
CellType,
|
|
49
|
+
RowType,
|
|
50
|
+
Text,
|
|
51
|
+
Emph,
|
|
52
|
+
Strong,
|
|
53
|
+
Underline,
|
|
54
|
+
Strikethrough,
|
|
55
|
+
Link,
|
|
56
|
+
Ref,
|
|
57
|
+
Newline,
|
|
58
|
+
Span,
|
|
59
|
+
InlineImage,
|
|
60
|
+
)
|
|
61
|
+
from .exceptions import (
|
|
62
|
+
ValidationError,
|
|
63
|
+
RenderError,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
__all__ = [
|
|
67
|
+
"FlavorType",
|
|
68
|
+
"AlignType",
|
|
69
|
+
"Document",
|
|
70
|
+
"BaseElement",
|
|
71
|
+
"BaseInlineElement",
|
|
72
|
+
"BaseBlockElement",
|
|
73
|
+
"Attributes",
|
|
74
|
+
"InlineContainer",
|
|
75
|
+
"BlockContainer",
|
|
76
|
+
"Section",
|
|
77
|
+
"Heading",
|
|
78
|
+
"BlockImage",
|
|
79
|
+
"Paragraph",
|
|
80
|
+
"BlockText",
|
|
81
|
+
"ListItemType",
|
|
82
|
+
"ListItem",
|
|
83
|
+
"BulletList",
|
|
84
|
+
"NumberedList",
|
|
85
|
+
"BaseItemList",
|
|
86
|
+
"DefinitionItem",
|
|
87
|
+
"DefinitionList",
|
|
88
|
+
"Table",
|
|
89
|
+
"Cell",
|
|
90
|
+
"CellType",
|
|
91
|
+
"RowType",
|
|
92
|
+
"Text",
|
|
93
|
+
"Emph",
|
|
94
|
+
"Strong",
|
|
95
|
+
"Underline",
|
|
96
|
+
"Strikethrough",
|
|
97
|
+
"Link",
|
|
98
|
+
"Ref",
|
|
99
|
+
"Newline",
|
|
100
|
+
"Span",
|
|
101
|
+
"InlineImage",
|
|
102
|
+
"ValidationError",
|
|
103
|
+
"RenderError",
|
|
104
|
+
]
|
|
105
|
+
# </AUTOGEN_INIT>
|
|
@@ -5,7 +5,7 @@ Utilities to normalize objects.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from dataclasses import dataclass
|
|
8
|
-
from typing import Any, Callable, Iterable
|
|
8
|
+
from typing import Any, Callable, Iterable
|
|
9
9
|
|
|
10
10
|
__all__ = [
|
|
11
11
|
"CoerceSpec",
|
|
@@ -14,10 +14,6 @@ __all__ = [
|
|
|
14
14
|
]
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
ExpectT = TypeVar("ExpectT")
|
|
18
|
-
CoerceT = TypeVar("CoerceT", bound=ExpectT)
|
|
19
|
-
|
|
20
|
-
|
|
21
17
|
@dataclass
|
|
22
18
|
class CoerceSpec[CoerceT]:
|
|
23
19
|
"""
|
|
@@ -26,8 +22,9 @@ class CoerceSpec[CoerceT]:
|
|
|
26
22
|
|
|
27
23
|
to_type: Callable[[Any], CoerceT]
|
|
28
24
|
"""
|
|
29
|
-
Type to which to coerce, or a callable returning that type.
|
|
30
|
-
|
|
25
|
+
Type to which to coerce, or a callable returning that type.
|
|
26
|
+
|
|
27
|
+
Must take a single argument of one of the type(s) given in `from_types`.
|
|
31
28
|
"""
|
|
32
29
|
|
|
33
30
|
from_types: type[Any] | tuple[Any, ...]
|
|
@@ -36,17 +33,17 @@ class CoerceSpec[CoerceT]:
|
|
|
36
33
|
"""
|
|
37
34
|
|
|
38
35
|
|
|
39
|
-
def norm_obj[
|
|
40
|
-
ExpectT, CoerceT
|
|
41
|
-
](
|
|
36
|
+
def norm_obj[ExpectT](
|
|
42
37
|
obj: Any,
|
|
43
|
-
expect_type: type[ExpectT],
|
|
44
|
-
*coerce_specs: CoerceSpec[
|
|
38
|
+
expect_type: type[ExpectT] | tuple[type[ExpectT], ...],
|
|
39
|
+
*coerce_specs: CoerceSpec[ExpectT],
|
|
45
40
|
) -> ExpectT:
|
|
46
41
|
"""
|
|
47
42
|
Normalize object to the expected type, coercing if applicable.
|
|
48
43
|
"""
|
|
49
44
|
|
|
45
|
+
note: str | None
|
|
46
|
+
|
|
50
47
|
if isinstance(obj, expect_type):
|
|
51
48
|
# already have expected type
|
|
52
49
|
return obj
|
|
@@ -74,12 +71,10 @@ def norm_obj[
|
|
|
74
71
|
raise ValueError(_err_str(obj, expect_type, note))
|
|
75
72
|
|
|
76
73
|
|
|
77
|
-
def norm_list[
|
|
78
|
-
ExpectT, CoerceT
|
|
79
|
-
](
|
|
74
|
+
def norm_list[ExpectT](
|
|
80
75
|
objs: Any | Iterable[Any],
|
|
81
|
-
expect_type: type[ExpectT],
|
|
82
|
-
*coerce_specs: CoerceSpec[
|
|
76
|
+
expect_type: type[ExpectT] | tuple[type[ExpectT], ...],
|
|
77
|
+
*coerce_specs: CoerceSpec[ExpectT],
|
|
83
78
|
) -> list[ExpectT]:
|
|
84
79
|
"""
|
|
85
80
|
Normalize object(s) to a list of the expected type, coercing if applicable.
|
|
@@ -101,7 +96,7 @@ def norm_list[
|
|
|
101
96
|
|
|
102
97
|
|
|
103
98
|
def _err_str(
|
|
104
|
-
obj: Any, expect_type: type[
|
|
99
|
+
obj: Any, expect_type: type[Any] | tuple[type[Any], ...], note: str | None = None
|
|
105
100
|
) -> str:
|
|
106
101
|
note_norm = f" {note}" if note else ""
|
|
107
102
|
return f"Object {obj} of type {type(obj)} is not of expected type {expect_type}{note_norm}"
|
|
@@ -18,12 +18,10 @@ def coerce_text(obj: str) -> BaseElement:
|
|
|
18
18
|
return BlockText(obj) if "\n" in obj else Text(obj)
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
def coerce_inline_text(
|
|
22
|
-
obj: str, allow_multiline: bool = False
|
|
23
|
-
) -> BaseInlineElement:
|
|
21
|
+
def coerce_inline_text(obj: str, allow_multiline: bool = False) -> BaseInlineElement:
|
|
24
22
|
"""
|
|
25
|
-
Wrap text with inline element, validating based on whether newlines
|
|
26
|
-
|
|
23
|
+
Wrap text with inline element, validating based on whether newlines (non-consecutive
|
|
24
|
+
only) are allowed.
|
|
27
25
|
"""
|
|
28
26
|
from .container import InlineContainer
|
|
29
27
|
from .elements.inline.text import Newline, Text
|
|
@@ -30,13 +30,9 @@ class InlineContainerMixin(BaseElement):
|
|
|
30
30
|
__elements: list[BaseInlineElement]
|
|
31
31
|
__auto_space: bool
|
|
32
32
|
|
|
33
|
-
def __init__(
|
|
34
|
-
self, *elements: BaseInlineElement | str, auto_space: bool = False
|
|
35
|
-
):
|
|
33
|
+
def __init__(self, *elements: BaseInlineElement | str, auto_space: bool = False):
|
|
36
34
|
def coerce(obj: str) -> BaseInlineElement:
|
|
37
|
-
return coerce_inline_text(
|
|
38
|
-
obj, allow_multiline=self._allow_multiline
|
|
39
|
-
)
|
|
35
|
+
return coerce_inline_text(obj, allow_multiline=self._allow_multiline)
|
|
40
36
|
|
|
41
37
|
self.__elements = norm_list(
|
|
42
38
|
elements, BaseInlineElement, CoerceSpec(coerce, str)
|
|
@@ -52,21 +48,15 @@ class InlineContainerMixin(BaseElement):
|
|
|
52
48
|
|
|
53
49
|
def _render_elements(self, flavor: FlavorType) -> str:
|
|
54
50
|
sep = " " if self.__auto_space else ""
|
|
55
|
-
return sep.join(
|
|
56
|
-
element._render_inline(flavor) for element in self.__elements
|
|
57
|
-
)
|
|
51
|
+
return sep.join(element._render_inline(flavor) for element in self.__elements)
|
|
58
52
|
|
|
59
53
|
def _get_pandoc_extensions(self) -> set[str]:
|
|
60
|
-
return (
|
|
61
|
-
_aggregate_extensions(self.__elements)
|
|
62
|
-
| super()._get_pandoc_extensions()
|
|
63
|
-
)
|
|
54
|
+
return _aggregate_extensions(self.__elements) | super()._get_pandoc_extensions()
|
|
64
55
|
|
|
65
56
|
|
|
66
57
|
class InlineContainer(InlineContainerMixin, BaseInlineElement):
|
|
67
58
|
"""
|
|
68
|
-
Container for inline elements; wraps multiple inline elements in a single
|
|
69
|
-
one.
|
|
59
|
+
Container for inline elements; wraps multiple inline elements in a single one.
|
|
70
60
|
"""
|
|
71
61
|
|
|
72
62
|
def _render_inline(self, flavor: FlavorType) -> str:
|
|
@@ -95,17 +85,11 @@ class BaseBlockContainer(BaseBlockElement):
|
|
|
95
85
|
|
|
96
86
|
def _render_block(self, flavor: FlavorType) -> Generator[str, None, None]:
|
|
97
87
|
yield "\n\n".join(
|
|
98
|
-
[
|
|
99
|
-
"\n".join(element._render_block(flavor))
|
|
100
|
-
for element in self.__elements
|
|
101
|
-
]
|
|
88
|
+
["\n".join(element._render_block(flavor)) for element in self.__elements]
|
|
102
89
|
)
|
|
103
90
|
|
|
104
91
|
def _get_pandoc_extensions(self) -> set[str]:
|
|
105
|
-
return (
|
|
106
|
-
_aggregate_extensions(self.__elements)
|
|
107
|
-
| super()._get_pandoc_extensions()
|
|
108
|
-
)
|
|
92
|
+
return _aggregate_extensions(self.__elements) | super()._get_pandoc_extensions()
|
|
109
93
|
|
|
110
94
|
def _add_elements(self, elements: list[BaseBlockElement]):
|
|
111
95
|
for element in elements:
|
|
@@ -207,7 +191,7 @@ class BaseLevelBlockContainer(BaseBlockContainer):
|
|
|
207
191
|
container._level = self.__level + self._level_inc
|
|
208
192
|
|
|
209
193
|
|
|
210
|
-
def _aggregate_extensions(elements:
|
|
194
|
+
def _aggregate_extensions(elements: Iterable[BaseElement]) -> set[str]:
|
|
211
195
|
"""
|
|
212
196
|
Aggregate extensions from elements.
|
|
213
197
|
"""
|
|
@@ -21,7 +21,9 @@ ROOT_LEVEL: int = 1
|
|
|
21
21
|
|
|
22
22
|
class Document(BaseLevelBlockContainer):
|
|
23
23
|
"""
|
|
24
|
-
Encapsulates a Markdown document.
|
|
24
|
+
Encapsulates a Markdown document.
|
|
25
|
+
|
|
26
|
+
Add elements using the `+=` operator.
|
|
25
27
|
"""
|
|
26
28
|
|
|
27
29
|
_level_inc: int = 0
|
|
@@ -25,15 +25,15 @@ __all__ = [
|
|
|
25
25
|
|
|
26
26
|
class BaseElement(ABC):
|
|
27
27
|
"""
|
|
28
|
-
Base renderable markdown element, which may be a container of other
|
|
29
|
-
elements.
|
|
28
|
+
Base renderable markdown element, which may be a container of other elements.
|
|
30
29
|
"""
|
|
31
30
|
|
|
32
31
|
__container: BaseLevelBlockContainer | None = None
|
|
33
32
|
"""
|
|
34
|
-
Container to which this element belongs.
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
Container to which this element belongs.
|
|
34
|
+
|
|
35
|
+
Must be added to a container in order to be rendered in a document, but otherwise
|
|
36
|
+
can still be rendered standalone.
|
|
37
37
|
"""
|
|
38
38
|
|
|
39
39
|
def render(self, *, flavor: FlavorType) -> str:
|
|
@@ -52,9 +52,8 @@ class BaseElement(ABC):
|
|
|
52
52
|
|
|
53
53
|
def get_pandoc_extensions(self) -> list[str]:
|
|
54
54
|
"""
|
|
55
|
-
Get a list of extensions required to convert the resulting
|
|
56
|
-
|
|
57
|
-
rendering.
|
|
55
|
+
Get a list of extensions required to convert the resulting markdown document in
|
|
56
|
+
pandoc, assuming pandoc flavor is used for rendering.
|
|
58
57
|
"""
|
|
59
58
|
return sorted(self._get_pandoc_extensions())
|
|
60
59
|
|
|
@@ -71,20 +70,16 @@ class BaseElement(ABC):
|
|
|
71
70
|
"""
|
|
72
71
|
return set()
|
|
73
72
|
|
|
74
|
-
def _render_element_norm(
|
|
75
|
-
self, flavor: FlavorType
|
|
76
|
-
) -> Generator[str, None, None]:
|
|
73
|
+
def _render_element_norm(self, flavor: FlavorType) -> Generator[str, None, None]:
|
|
77
74
|
"""
|
|
78
|
-
Render this element, splitting any newlines embedded in content and
|
|
79
|
-
|
|
75
|
+
Render this element, splitting any newlines embedded in content and stripping
|
|
76
|
+
whitespace.
|
|
80
77
|
"""
|
|
81
78
|
yield from "\n".join(self._render_element(flavor)).strip().split("\n")
|
|
82
79
|
|
|
83
80
|
@property
|
|
84
81
|
def _container(self) -> BaseLevelBlockContainer:
|
|
85
|
-
assert
|
|
86
|
-
self.__container
|
|
87
|
-
), f"Element has not been placed in a container: {self}"
|
|
82
|
+
assert self.__container, f"Element has not been placed in a container: {self}"
|
|
88
83
|
return self.__container
|
|
89
84
|
|
|
90
85
|
@_container.setter
|
|
@@ -105,9 +100,7 @@ class BaseInlineElement(BaseElement):
|
|
|
105
100
|
"""
|
|
106
101
|
...
|
|
107
102
|
|
|
108
|
-
def _render_element(
|
|
109
|
-
self, flavor: BaseElement
|
|
110
|
-
) -> Generator[str, None, None]:
|
|
103
|
+
def _render_element(self, flavor: FlavorType) -> Generator[str, None, None]:
|
|
111
104
|
yield self._render_inline(flavor)
|
|
112
105
|
|
|
113
106
|
|
|
@@ -130,8 +123,9 @@ class BaseBlockElement(BaseElement):
|
|
|
130
123
|
@dataclass(kw_only=True)
|
|
131
124
|
class Attributes:
|
|
132
125
|
"""
|
|
133
|
-
HTML attributes which can be associated with some elements.
|
|
134
|
-
|
|
126
|
+
HTML attributes which can be associated with some elements.
|
|
127
|
+
|
|
128
|
+
Only applicable to pandoc flavor.
|
|
135
129
|
"""
|
|
136
130
|
|
|
137
131
|
html_id: str | None = None
|
|
@@ -189,8 +183,9 @@ class Attributes:
|
|
|
189
183
|
|
|
190
184
|
class AttributesMixin:
|
|
191
185
|
"""
|
|
192
|
-
Mixin to facilitate adding HTML attributes.
|
|
193
|
-
|
|
186
|
+
Mixin to facilitate adding HTML attributes.
|
|
187
|
+
|
|
188
|
+
Only supported for pandoc flavor.
|
|
194
189
|
"""
|
|
195
190
|
|
|
196
191
|
__attributes: Attributes | None = None
|
|
@@ -223,16 +218,18 @@ class AttributesMixin:
|
|
|
223
218
|
) -> str:
|
|
224
219
|
"""
|
|
225
220
|
Get string representing attributes, optionally prefixed with a space.
|
|
221
|
+
|
|
226
222
|
For pandoc flavor only.
|
|
227
223
|
"""
|
|
228
224
|
|
|
225
|
+
attributes = self.__attributes
|
|
226
|
+
|
|
229
227
|
# return if not applicable or no attributes set
|
|
230
|
-
if flavor != "pandoc" or not
|
|
228
|
+
if flavor != "pandoc" or not attributes:
|
|
231
229
|
return ""
|
|
232
230
|
|
|
233
231
|
parts: list[str] = []
|
|
234
232
|
|
|
235
|
-
attributes = self.__attributes
|
|
236
233
|
if attributes.html_id:
|
|
237
234
|
parts.append(f"#{attributes.html_id}")
|
|
238
235
|
if css_classes := attributes._css_classes_norm:
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Primitive Markdown elements which can be inserted into a document or section.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
__submodules__ = [
|
|
6
|
+
"block",
|
|
7
|
+
"inline",
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
# isort: off
|
|
11
|
+
# <AUTOGEN_INIT>
|
|
12
|
+
from .block import (
|
|
13
|
+
Section,
|
|
14
|
+
Heading,
|
|
15
|
+
BlockImage,
|
|
16
|
+
Paragraph,
|
|
17
|
+
BlockText,
|
|
18
|
+
ListItemType,
|
|
19
|
+
ListItem,
|
|
20
|
+
BulletList,
|
|
21
|
+
NumberedList,
|
|
22
|
+
BaseItemList,
|
|
23
|
+
DefinitionItem,
|
|
24
|
+
DefinitionList,
|
|
25
|
+
Table,
|
|
26
|
+
Cell,
|
|
27
|
+
CellType,
|
|
28
|
+
RowType,
|
|
29
|
+
)
|
|
30
|
+
from .inline import (
|
|
31
|
+
Text,
|
|
32
|
+
Emph,
|
|
33
|
+
Strong,
|
|
34
|
+
Underline,
|
|
35
|
+
Strikethrough,
|
|
36
|
+
Link,
|
|
37
|
+
Ref,
|
|
38
|
+
Newline,
|
|
39
|
+
Span,
|
|
40
|
+
InlineImage,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
__all__ = [
|
|
44
|
+
"Section",
|
|
45
|
+
"Heading",
|
|
46
|
+
"BlockImage",
|
|
47
|
+
"Paragraph",
|
|
48
|
+
"BlockText",
|
|
49
|
+
"ListItemType",
|
|
50
|
+
"ListItem",
|
|
51
|
+
"BulletList",
|
|
52
|
+
"NumberedList",
|
|
53
|
+
"BaseItemList",
|
|
54
|
+
"DefinitionItem",
|
|
55
|
+
"DefinitionList",
|
|
56
|
+
"Table",
|
|
57
|
+
"Cell",
|
|
58
|
+
"CellType",
|
|
59
|
+
"RowType",
|
|
60
|
+
"Text",
|
|
61
|
+
"Emph",
|
|
62
|
+
"Strong",
|
|
63
|
+
"Underline",
|
|
64
|
+
"Strikethrough",
|
|
65
|
+
"Link",
|
|
66
|
+
"Ref",
|
|
67
|
+
"Newline",
|
|
68
|
+
"Span",
|
|
69
|
+
"InlineImage",
|
|
70
|
+
]
|
|
71
|
+
# </AUTOGEN_INIT>
|
|
@@ -31,7 +31,7 @@ class ImageMixin(AttributesMixin, ABC):
|
|
|
31
31
|
self._set_attrs(attributes)
|
|
32
32
|
|
|
33
33
|
@abstractmethod
|
|
34
|
-
def _render_alt_text(self,
|
|
34
|
+
def _render_alt_text(self, flavor: FlavorType) -> str:
|
|
35
35
|
"""
|
|
36
36
|
Implemented by concrete class to get alt text.
|
|
37
37
|
"""
|