markdown-to-confluence 0.5.1__py3-none-any.whl → 0.5.3__py3-none-any.whl
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.
- {markdown_to_confluence-0.5.1.dist-info → markdown_to_confluence-0.5.3.dist-info}/METADATA +160 -11
- markdown_to_confluence-0.5.3.dist-info/RECORD +55 -0
- {markdown_to_confluence-0.5.1.dist-info → markdown_to_confluence-0.5.3.dist-info}/licenses/LICENSE +1 -1
- md2conf/__init__.py +2 -2
- md2conf/__main__.py +94 -29
- md2conf/api.py +55 -10
- md2conf/attachment.py +72 -0
- md2conf/coalesce.py +43 -0
- md2conf/collection.py +1 -1
- md2conf/{extra.py → compatibility.py} +1 -1
- md2conf/converter.py +417 -590
- md2conf/csf.py +13 -11
- md2conf/drawio/__init__.py +0 -0
- md2conf/drawio/extension.py +116 -0
- md2conf/{drawio.py → drawio/render.py} +1 -1
- md2conf/emoticon.py +3 -3
- md2conf/environment.py +2 -2
- md2conf/extension.py +78 -0
- md2conf/external.py +49 -0
- md2conf/formatting.py +135 -0
- md2conf/frontmatter.py +70 -0
- md2conf/image.py +127 -0
- md2conf/latex.py +7 -186
- md2conf/local.py +8 -8
- md2conf/markdown.py +1 -1
- md2conf/matcher.py +1 -1
- md2conf/mermaid/__init__.py +0 -0
- md2conf/mermaid/config.py +20 -0
- md2conf/mermaid/extension.py +109 -0
- md2conf/{mermaid.py → mermaid/render.py} +10 -38
- md2conf/mermaid/scanner.py +55 -0
- md2conf/metadata.py +1 -1
- md2conf/options.py +116 -0
- md2conf/plantuml/__init__.py +0 -0
- md2conf/plantuml/config.py +20 -0
- md2conf/plantuml/extension.py +158 -0
- md2conf/plantuml/render.py +139 -0
- md2conf/plantuml/scanner.py +56 -0
- md2conf/png.py +202 -0
- md2conf/processor.py +32 -11
- md2conf/publisher.py +17 -18
- md2conf/scanner.py +31 -128
- md2conf/serializer.py +2 -2
- md2conf/svg.py +341 -0
- md2conf/text.py +1 -1
- md2conf/toc.py +1 -1
- md2conf/uri.py +1 -1
- md2conf/xml.py +1 -1
- markdown_to_confluence-0.5.1.dist-info/RECORD +0 -35
- md2conf/domain.py +0 -52
- {markdown_to_confluence-0.5.1.dist-info → markdown_to_confluence-0.5.3.dist-info}/WHEEL +0 -0
- {markdown_to_confluence-0.5.1.dist-info → markdown_to_confluence-0.5.3.dist-info}/entry_points.txt +0 -0
- {markdown_to_confluence-0.5.1.dist-info → markdown_to_confluence-0.5.3.dist-info}/top_level.txt +0 -0
- {markdown_to_confluence-0.5.1.dist-info → markdown_to_confluence-0.5.3.dist-info}/zip-safe +0 -0
md2conf/processor.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Publish Markdown files to Confluence wiki.
|
|
3
3
|
|
|
4
|
-
Copyright 2022-
|
|
4
|
+
Copyright 2022-2026, Levente Hunyadi
|
|
5
5
|
|
|
6
6
|
:see: https://github.com/hunyadi/md2conf
|
|
7
7
|
"""
|
|
@@ -15,16 +15,18 @@ from typing import Iterable
|
|
|
15
15
|
|
|
16
16
|
from .collection import ConfluencePageCollection
|
|
17
17
|
from .converter import ConfluenceDocument
|
|
18
|
-
from .domain import ConfluenceDocumentOptions, ConfluencePageID
|
|
19
18
|
from .environment import ArgumentError
|
|
20
19
|
from .matcher import DirectoryEntry, FileEntry, Matcher, MatcherOptions
|
|
21
20
|
from .metadata import ConfluenceSiteMetadata
|
|
21
|
+
from .options import ConfluencePageID, DocumentOptions
|
|
22
22
|
from .scanner import Scanner
|
|
23
23
|
|
|
24
24
|
LOGGER = logging.getLogger(__name__)
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class DocumentNode:
|
|
28
|
+
"Represents a Markdown document in a hierarchy."
|
|
29
|
+
|
|
28
30
|
absolute_path: Path
|
|
29
31
|
page_id: str | None
|
|
30
32
|
space_key: str | None
|
|
@@ -49,24 +51,42 @@ class DocumentNode:
|
|
|
49
51
|
self._children = []
|
|
50
52
|
|
|
51
53
|
def count(self) -> int:
|
|
54
|
+
"Number of descendants in the sub-tree spanned by this node (excluding the top-level node)."
|
|
55
|
+
|
|
52
56
|
c = len(self._children)
|
|
53
57
|
for child in self._children:
|
|
54
58
|
c += child.count()
|
|
55
59
|
return c
|
|
56
60
|
|
|
57
61
|
def add_child(self, child: "DocumentNode") -> None:
|
|
62
|
+
"Adds a new node to the list of direct children."
|
|
63
|
+
|
|
58
64
|
self._children.append(child)
|
|
59
65
|
|
|
60
66
|
def children(self) -> Iterable["DocumentNode"]:
|
|
67
|
+
"Direct children of this node."
|
|
68
|
+
|
|
61
69
|
for child in self._children:
|
|
62
70
|
yield child
|
|
63
71
|
|
|
64
72
|
def descendants(self) -> Iterable["DocumentNode"]:
|
|
73
|
+
"""
|
|
74
|
+
Descendants of this node, part of its sub-tree.
|
|
75
|
+
|
|
76
|
+
Traversal follows depth-first search.
|
|
77
|
+
"""
|
|
78
|
+
|
|
65
79
|
for child in self._children:
|
|
66
80
|
yield child
|
|
67
81
|
yield from child.descendants()
|
|
68
82
|
|
|
69
83
|
def all(self) -> Iterable["DocumentNode"]:
|
|
84
|
+
"""
|
|
85
|
+
Descendants of this node, part of the sub-tree including the top-level node.
|
|
86
|
+
|
|
87
|
+
Traversal follows depth-first search.
|
|
88
|
+
"""
|
|
89
|
+
|
|
70
90
|
yield self
|
|
71
91
|
for child in self._children:
|
|
72
92
|
yield from child.all()
|
|
@@ -77,7 +97,7 @@ class Processor:
|
|
|
77
97
|
Processes a single Markdown page or a directory of Markdown pages.
|
|
78
98
|
"""
|
|
79
99
|
|
|
80
|
-
options:
|
|
100
|
+
options: DocumentOptions
|
|
81
101
|
site: ConfluenceSiteMetadata
|
|
82
102
|
root_dir: Path
|
|
83
103
|
|
|
@@ -85,7 +105,7 @@ class Processor:
|
|
|
85
105
|
|
|
86
106
|
def __init__(
|
|
87
107
|
self,
|
|
88
|
-
options:
|
|
108
|
+
options: DocumentOptions,
|
|
89
109
|
site: ConfluenceSiteMetadata,
|
|
90
110
|
root_dir: Path,
|
|
91
111
|
) -> None:
|
|
@@ -140,7 +160,7 @@ class Processor:
|
|
|
140
160
|
self._update_page(page_id, document, path)
|
|
141
161
|
|
|
142
162
|
@abstractmethod
|
|
143
|
-
def _synchronize_tree(self,
|
|
163
|
+
def _synchronize_tree(self, tree: DocumentNode, root_id: ConfluencePageID | None) -> None:
|
|
144
164
|
"""
|
|
145
165
|
Creates the cross-reference index and synchronizes the directory tree structure with the Confluence page hierarchy.
|
|
146
166
|
|
|
@@ -228,12 +248,13 @@ class Processor:
|
|
|
228
248
|
# extract information from a Markdown document found in a local directory.
|
|
229
249
|
document = Scanner().read(path)
|
|
230
250
|
|
|
251
|
+
props = document.properties
|
|
231
252
|
return DocumentNode(
|
|
232
253
|
absolute_path=path,
|
|
233
|
-
page_id=
|
|
234
|
-
space_key=
|
|
235
|
-
title=
|
|
236
|
-
synchronized=
|
|
254
|
+
page_id=props.page_id,
|
|
255
|
+
space_key=props.space_key,
|
|
256
|
+
title=props.title,
|
|
257
|
+
synchronized=props.synchronized if props.synchronized is not None else True,
|
|
237
258
|
)
|
|
238
259
|
|
|
239
260
|
def _generate_hash(self, absolute_path: Path) -> str:
|
|
@@ -247,10 +268,10 @@ class Processor:
|
|
|
247
268
|
|
|
248
269
|
|
|
249
270
|
class ProcessorFactory:
|
|
250
|
-
options:
|
|
271
|
+
options: DocumentOptions
|
|
251
272
|
site: ConfluenceSiteMetadata
|
|
252
273
|
|
|
253
|
-
def __init__(self, options:
|
|
274
|
+
def __init__(self, options: DocumentOptions, site: ConfluenceSiteMetadata) -> None:
|
|
254
275
|
self.options = options
|
|
255
276
|
self.site = site
|
|
256
277
|
|
md2conf/publisher.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Publish Markdown files to Confluence wiki.
|
|
3
3
|
|
|
4
|
-
Copyright 2022-
|
|
4
|
+
Copyright 2022-2026, Levente Hunyadi
|
|
5
5
|
|
|
6
6
|
:see: https://github.com/hunyadi/md2conf
|
|
7
7
|
"""
|
|
@@ -10,12 +10,13 @@ import logging
|
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
12
|
from .api import ConfluenceContentProperty, ConfluenceLabel, ConfluenceSession, ConfluenceStatus
|
|
13
|
-
from .
|
|
13
|
+
from .attachment import attachment_name
|
|
14
|
+
from .compatibility import override, path_relative_to
|
|
15
|
+
from .converter import ConfluenceDocument, get_volatile_attributes, get_volatile_elements
|
|
14
16
|
from .csf import AC_ATTR, elements_from_string
|
|
15
|
-
from .domain import ConfluenceDocumentOptions, ConfluencePageID
|
|
16
17
|
from .environment import PageError
|
|
17
|
-
from .extra import override, path_relative_to
|
|
18
18
|
from .metadata import ConfluencePageMetadata
|
|
19
|
+
from .options import ConfluencePageID, DocumentOptions
|
|
19
20
|
from .processor import Converter, DocumentNode, Processor, ProcessorFactory
|
|
20
21
|
from .xml import is_xml_equal, unwrap_substitute
|
|
21
22
|
|
|
@@ -29,7 +30,7 @@ class SynchronizingProcessor(Processor):
|
|
|
29
30
|
|
|
30
31
|
api: ConfluenceSession
|
|
31
32
|
|
|
32
|
-
def __init__(self, api: ConfluenceSession, options:
|
|
33
|
+
def __init__(self, api: ConfluenceSession, options: DocumentOptions, root_dir: Path) -> None:
|
|
33
34
|
"""
|
|
34
35
|
Initializes a new processor instance.
|
|
35
36
|
|
|
@@ -42,7 +43,7 @@ class SynchronizingProcessor(Processor):
|
|
|
42
43
|
self.api = api
|
|
43
44
|
|
|
44
45
|
@override
|
|
45
|
-
def _synchronize_tree(self,
|
|
46
|
+
def _synchronize_tree(self, tree: DocumentNode, root_id: ConfluencePageID | None) -> None:
|
|
46
47
|
"""
|
|
47
48
|
Creates the cross-reference index and synchronizes the directory tree structure with the Confluence page hierarchy.
|
|
48
49
|
|
|
@@ -51,21 +52,16 @@ class SynchronizingProcessor(Processor):
|
|
|
51
52
|
Updates the original Markdown document to add tags to associate the document with its corresponding Confluence page.
|
|
52
53
|
"""
|
|
53
54
|
|
|
54
|
-
if
|
|
55
|
-
raise PageError(f"expected: root page ID in options, or explicit page ID in {
|
|
56
|
-
elif
|
|
57
|
-
|
|
58
|
-
raise PageError(f"mismatched inferred page ID of {root_id.page_id} and explicit page ID in {root.absolute_path}")
|
|
59
|
-
|
|
60
|
-
real_id = root_id
|
|
55
|
+
if tree.page_id is None and root_id is None:
|
|
56
|
+
raise PageError(f"expected: root page ID in options, or explicit page ID in {tree.absolute_path}")
|
|
57
|
+
elif tree.page_id is not None:
|
|
58
|
+
real_id = ConfluencePageID(tree.page_id) # explicit page ID takes precedence
|
|
61
59
|
elif root_id is not None:
|
|
62
60
|
real_id = root_id
|
|
63
|
-
elif root.page_id is not None:
|
|
64
|
-
real_id = ConfluencePageID(root.page_id)
|
|
65
61
|
else:
|
|
66
62
|
raise NotImplementedError("condition not exhaustive")
|
|
67
63
|
|
|
68
|
-
self._synchronize_subtree(
|
|
64
|
+
self._synchronize_subtree(tree, real_id)
|
|
69
65
|
|
|
70
66
|
def _synchronize_subtree(self, node: DocumentNode, parent_id: ConfluencePageID) -> None:
|
|
71
67
|
if node.page_id is not None:
|
|
@@ -81,6 +77,9 @@ class SynchronizingProcessor(Processor):
|
|
|
81
77
|
digest = self._generate_hash(node.absolute_path)
|
|
82
78
|
title = f"{node.absolute_path.stem} [{digest}]"
|
|
83
79
|
|
|
80
|
+
if self.options.title_prefix is not None:
|
|
81
|
+
title = f"{self.options.title_prefix} {title}"
|
|
82
|
+
|
|
84
83
|
# look up page by (possibly auto-generated) title
|
|
85
84
|
page = self.api.get_or_create_page(title, parent_id.page_id)
|
|
86
85
|
|
|
@@ -209,7 +208,7 @@ class SynchronizingProcessor(Processor):
|
|
|
209
208
|
class SynchronizingProcessorFactory(ProcessorFactory):
|
|
210
209
|
api: ConfluenceSession
|
|
211
210
|
|
|
212
|
-
def __init__(self, api: ConfluenceSession, options:
|
|
211
|
+
def __init__(self, api: ConfluenceSession, options: DocumentOptions) -> None:
|
|
213
212
|
super().__init__(options, api.site)
|
|
214
213
|
self.api = api
|
|
215
214
|
|
|
@@ -224,5 +223,5 @@ class Publisher(Converter):
|
|
|
224
223
|
This is the class instantiated by the command-line application.
|
|
225
224
|
"""
|
|
226
225
|
|
|
227
|
-
def __init__(self, api: ConfluenceSession, options:
|
|
226
|
+
def __init__(self, api: ConfluenceSession, options: DocumentOptions) -> None:
|
|
228
227
|
super().__init__(SynchronizingProcessorFactory(api, options))
|
md2conf/scanner.py
CHANGED
|
@@ -1,55 +1,34 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Publish Markdown files to Confluence wiki.
|
|
3
3
|
|
|
4
|
-
Copyright 2022-
|
|
4
|
+
Copyright 2022-2026, Levente Hunyadi
|
|
5
5
|
|
|
6
6
|
:see: https://github.com/hunyadi/md2conf
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
import re
|
|
10
|
-
import typing
|
|
11
9
|
from dataclasses import dataclass
|
|
12
10
|
from pathlib import Path
|
|
13
|
-
from typing import
|
|
11
|
+
from typing import TypeVar
|
|
14
12
|
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
from .
|
|
13
|
+
from .coalesce import coalesce
|
|
14
|
+
from .frontmatter import extract_frontmatter_json, extract_value
|
|
15
|
+
from .options import LayoutOptions
|
|
18
16
|
from .serializer import JsonType, json_to_object
|
|
19
17
|
|
|
20
18
|
T = TypeVar("T")
|
|
21
19
|
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
values.append(matchobj.group(1))
|
|
28
|
-
return ""
|
|
29
|
-
|
|
30
|
-
text = re.sub(pattern, _repl_func, text, count=1, flags=re.ASCII)
|
|
31
|
-
value = values[0] if values else None
|
|
32
|
-
return value, text
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def extract_frontmatter_block(text: str) -> tuple[str | None, str]:
|
|
36
|
-
"Extracts the front-matter from a Markdown document as a blob of unparsed text."
|
|
37
|
-
|
|
38
|
-
return extract_value(r"(?ms)\A---$(.+?)^---$", text)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def extract_frontmatter_properties(text: str) -> tuple[dict[str, JsonType] | None, str]:
|
|
42
|
-
"Extracts the front-matter from a Markdown document as a dictionary."
|
|
43
|
-
|
|
44
|
-
block, text = extract_frontmatter_block(text)
|
|
21
|
+
@dataclass
|
|
22
|
+
class AliasProperties:
|
|
23
|
+
"""
|
|
24
|
+
An object that holds properties extracted from the front-matter of a Markdown document.
|
|
45
25
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if isinstance(data, dict):
|
|
50
|
-
properties = typing.cast(dict[str, JsonType], data)
|
|
26
|
+
:param confluence_page_id: Confluence page ID. (Alternative name for JSON de-serialization.)
|
|
27
|
+
:param confluence_space_key: Confluence space key. (Alternative name for JSON de-serialization.)
|
|
28
|
+
"""
|
|
51
29
|
|
|
52
|
-
|
|
30
|
+
confluence_page_id: str | None = None
|
|
31
|
+
confluence_space_key: str | None = None
|
|
53
32
|
|
|
54
33
|
|
|
55
34
|
@dataclass
|
|
@@ -59,26 +38,22 @@ class DocumentProperties:
|
|
|
59
38
|
|
|
60
39
|
:param page_id: Confluence page ID.
|
|
61
40
|
:param space_key: Confluence space key.
|
|
62
|
-
:param confluence_page_id: Confluence page ID. (Alternative name for JSON de-serialization.)
|
|
63
|
-
:param confluence_space_key: Confluence space key. (Alternative name for JSON de-serialization.)
|
|
64
41
|
:param generated_by: Text identifying the tool that generated the document.
|
|
65
42
|
:param title: The title extracted from front-matter.
|
|
66
43
|
:param tags: A list of tags (content labels) extracted from front-matter.
|
|
67
44
|
:param synchronized: True if the document content is parsed and synchronized with Confluence.
|
|
68
45
|
:param properties: A dictionary of key-value pairs extracted from front-matter to apply as page properties.
|
|
69
|
-
:param
|
|
46
|
+
:param layout: Layout options for content on a Confluence page.
|
|
70
47
|
"""
|
|
71
48
|
|
|
72
49
|
page_id: str | None = None
|
|
73
50
|
space_key: str | None = None
|
|
74
|
-
confluence_page_id: str | None = None
|
|
75
|
-
confluence_space_key: str | None = None
|
|
76
51
|
generated_by: str | None = None
|
|
77
52
|
title: str | None = None
|
|
78
53
|
tags: list[str] | None = None
|
|
79
54
|
synchronized: bool | None = None
|
|
80
55
|
properties: dict[str, JsonType] | None = None
|
|
81
|
-
|
|
56
|
+
layout: LayoutOptions | None = None
|
|
82
57
|
|
|
83
58
|
|
|
84
59
|
@dataclass
|
|
@@ -86,25 +61,11 @@ class ScannedDocument:
|
|
|
86
61
|
"""
|
|
87
62
|
An object that holds properties extracted from a Markdown document, including remaining source text.
|
|
88
63
|
|
|
89
|
-
:param
|
|
90
|
-
:param space_key: Confluence space key.
|
|
91
|
-
:param generated_by: Text identifying the tool that generated the document.
|
|
92
|
-
:param title: The title extracted from front-matter.
|
|
93
|
-
:param tags: A list of tags (content labels) extracted from front-matter.
|
|
94
|
-
:param synchronized: True if the document content is parsed and synchronized with Confluence.
|
|
95
|
-
:param properties: A dictionary of key-value pairs extracted from front-matter to apply as page properties.
|
|
96
|
-
:param alignment: Alignment for block-level images and formulas.
|
|
64
|
+
:param properties: Properties extracted from the front-matter of a Markdown document.
|
|
97
65
|
:param text: Text that remains after front-matter and inline properties have been extracted.
|
|
98
66
|
"""
|
|
99
67
|
|
|
100
|
-
|
|
101
|
-
space_key: str | None
|
|
102
|
-
generated_by: str | None
|
|
103
|
-
title: str | None
|
|
104
|
-
tags: list[str] | None
|
|
105
|
-
synchronized: bool | None
|
|
106
|
-
properties: dict[str, JsonType] | None
|
|
107
|
-
alignment: Literal["center", "left", "right"] | None
|
|
68
|
+
properties: DocumentProperties
|
|
108
69
|
text: str
|
|
109
70
|
|
|
110
71
|
|
|
@@ -127,77 +88,19 @@ class Scanner:
|
|
|
127
88
|
# extract 'generated-by' tag text
|
|
128
89
|
generated_by, text = extract_value(r"<!--\s+generated[-_]by:\s*(.*)\s+-->", text)
|
|
129
90
|
|
|
130
|
-
|
|
131
|
-
tags: list[str] | None = None
|
|
132
|
-
synchronized: bool | None = None
|
|
133
|
-
properties: dict[str, JsonType] | None = None
|
|
134
|
-
alignment: Literal["center", "left", "right"] | None = None
|
|
91
|
+
body_props = DocumentProperties(page_id=page_id, space_key=space_key, generated_by=generated_by)
|
|
135
92
|
|
|
136
93
|
# extract front-matter
|
|
137
|
-
data, text =
|
|
94
|
+
data, text = extract_frontmatter_json(text)
|
|
138
95
|
if data is not None:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
return ScannedDocument(
|
|
150
|
-
page_id=page_id,
|
|
151
|
-
space_key=space_key,
|
|
152
|
-
generated_by=generated_by,
|
|
153
|
-
title=title,
|
|
154
|
-
tags=tags,
|
|
155
|
-
synchronized=synchronized,
|
|
156
|
-
properties=properties,
|
|
157
|
-
alignment=alignment,
|
|
158
|
-
text=text,
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
@dataclass
|
|
163
|
-
class MermaidProperties:
|
|
164
|
-
"""
|
|
165
|
-
An object that holds the front-matter properties structure for Mermaid diagrams.
|
|
166
|
-
|
|
167
|
-
:param title: The title of the diagram.
|
|
168
|
-
:param config: Configuration options for rendering.
|
|
169
|
-
"""
|
|
170
|
-
|
|
171
|
-
title: str | None = None
|
|
172
|
-
config: MermaidConfigProperties | None = None
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
class MermaidScanner:
|
|
176
|
-
"""
|
|
177
|
-
Extracts properties from the JSON/YAML front-matter of a Mermaid diagram.
|
|
178
|
-
"""
|
|
179
|
-
|
|
180
|
-
def read(self, content: str) -> MermaidProperties:
|
|
181
|
-
"""
|
|
182
|
-
Extracts rendering preferences from a Mermaid front-matter content.
|
|
183
|
-
|
|
184
|
-
```
|
|
185
|
-
---
|
|
186
|
-
title: Tiny flow diagram
|
|
187
|
-
config:
|
|
188
|
-
scale: 1
|
|
189
|
-
---
|
|
190
|
-
flowchart LR
|
|
191
|
-
A[Component A] --> B[Component B]
|
|
192
|
-
B --> C[Component C]
|
|
193
|
-
```
|
|
194
|
-
"""
|
|
195
|
-
|
|
196
|
-
properties, _ = extract_frontmatter_properties(content)
|
|
197
|
-
if properties is not None:
|
|
198
|
-
front_matter = json_to_object(MermaidProperties, properties)
|
|
199
|
-
config = front_matter.config or MermaidConfigProperties()
|
|
200
|
-
|
|
201
|
-
return MermaidProperties(title=front_matter.title, config=config)
|
|
202
|
-
|
|
203
|
-
return MermaidProperties()
|
|
96
|
+
frontmatter_props = json_to_object(DocumentProperties, data)
|
|
97
|
+
alias_props = json_to_object(AliasProperties, data)
|
|
98
|
+
if alias_props.confluence_page_id is not None:
|
|
99
|
+
frontmatter_props.page_id = alias_props.confluence_page_id
|
|
100
|
+
if alias_props.confluence_space_key is not None:
|
|
101
|
+
frontmatter_props.space_key = alias_props.confluence_space_key
|
|
102
|
+
props = coalesce(body_props, frontmatter_props)
|
|
103
|
+
else:
|
|
104
|
+
props = body_props
|
|
105
|
+
|
|
106
|
+
return ScannedDocument(properties=props, text=text)
|
md2conf/serializer.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Publish Markdown files to Confluence wiki.
|
|
3
3
|
|
|
4
|
-
Copyright 2022-
|
|
4
|
+
Copyright 2022-2026, Levente Hunyadi
|
|
5
5
|
|
|
6
6
|
:see: https://github.com/hunyadi/md2conf
|
|
7
7
|
"""
|
|
@@ -10,7 +10,7 @@ import sys
|
|
|
10
10
|
from datetime import datetime
|
|
11
11
|
from typing import TypeVar
|
|
12
12
|
|
|
13
|
-
from cattrs.preconf.orjson import make_converter
|
|
13
|
+
from cattrs.preconf.orjson import make_converter # spellchecker:disable-line
|
|
14
14
|
|
|
15
15
|
JsonType = None | bool | int | float | str | dict[str, "JsonType"] | list["JsonType"]
|
|
16
16
|
JsonComposite = dict[str, "JsonType"] | list["JsonType"]
|