markdown-to-confluence 0.3.4__py3-none-any.whl → 0.4.0__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.
md2conf/scanner.py ADDED
@@ -0,0 +1,149 @@
1
+ """
2
+ Publish Markdown files to Confluence wiki.
3
+
4
+ Copyright 2022-2025, Levente Hunyadi
5
+
6
+ :see: https://github.com/hunyadi/md2conf
7
+ """
8
+
9
+ import re
10
+ from dataclasses import dataclass
11
+ from pathlib import Path
12
+ from typing import Any, Optional, TypeVar
13
+
14
+ import yaml
15
+ from strong_typing.core import JsonType
16
+ from strong_typing.serialization import DeserializerOptions, json_to_object
17
+
18
+ T = TypeVar("T")
19
+
20
+
21
+ def _json_to_object(
22
+ typ: type[T],
23
+ data: JsonType,
24
+ ) -> T:
25
+ return json_to_object(typ, data, options=DeserializerOptions(skip_unassigned=True))
26
+
27
+
28
+ def extract_value(pattern: str, text: str) -> tuple[Optional[str], str]:
29
+ values: list[str] = []
30
+
31
+ def _repl_func(matchobj: re.Match[str]) -> str:
32
+ values.append(matchobj.group(1))
33
+ return ""
34
+
35
+ text = re.sub(pattern, _repl_func, text, count=1, flags=re.ASCII)
36
+ value = values[0] if values else None
37
+ return value, text
38
+
39
+
40
+ def extract_frontmatter_block(text: str) -> tuple[Optional[str], str]:
41
+ "Extracts the front-matter from a Markdown document as a blob of unparsed text."
42
+
43
+ return extract_value(r"(?ms)\A---$(.+?)^---$", text)
44
+
45
+
46
+ def extract_frontmatter_properties(text: str) -> tuple[Optional[dict[str, Any]], str]:
47
+ "Extracts the front-matter from a Markdown document as a dictionary."
48
+
49
+ block, text = extract_frontmatter_block(text)
50
+
51
+ properties: Optional[dict[str, Any]] = None
52
+ if block is not None:
53
+ data = yaml.safe_load(block)
54
+ if isinstance(data, dict):
55
+ properties = data
56
+
57
+ return properties, text
58
+
59
+
60
+ @dataclass
61
+ class DocumentProperties:
62
+ """
63
+ An object that holds properties extracted from the front-matter of a Markdown document.
64
+
65
+ :param page_id: Confluence page ID.
66
+ :param space_key: Confluence space key.
67
+ :param confluence_page_id: Confluence page ID. (Alternative name for JSON de-serialization.)
68
+ :param confluence_space_key: Confluence space key. (Alternative name for JSON de-serialization.)
69
+ :param generated_by: Text identifying the tool that generated the document.
70
+ :param title: The title extracted from front-matter.
71
+ :param tags: A list of tags (content labels) extracted from front-matter.
72
+ """
73
+
74
+ page_id: Optional[str]
75
+ space_key: Optional[str]
76
+ confluence_page_id: Optional[str]
77
+ confluence_space_key: Optional[str]
78
+ generated_by: Optional[str]
79
+ title: Optional[str]
80
+ tags: Optional[list[str]]
81
+
82
+
83
+ @dataclass
84
+ class ScannedDocument:
85
+ """
86
+ An object that holds properties extracted from a Markdown document, including remaining source text.
87
+
88
+ :param page_id: Confluence page ID.
89
+ :param space_key: Confluence space key.
90
+ :param generated_by: Text identifying the tool that generated the document.
91
+ :param title: The title extracted from front-matter.
92
+ :param tags: A list of tags (content labels) extracted from front-matter.
93
+ :param text: Text that remains after front-matter and inline properties have been extracted.
94
+ """
95
+
96
+ page_id: Optional[str]
97
+ space_key: Optional[str]
98
+ generated_by: Optional[str]
99
+ title: Optional[str]
100
+ tags: Optional[list[str]]
101
+ text: str
102
+
103
+
104
+ class Scanner:
105
+ def read(self, absolute_path: Path) -> ScannedDocument:
106
+ """
107
+ Extracts essential properties from a Markdown document.
108
+ """
109
+
110
+ # parse file
111
+ with open(absolute_path, "r", encoding="utf-8") as f:
112
+ text = f.read()
113
+
114
+ # extract Confluence page ID
115
+ page_id, text = extract_value(
116
+ r"<!--\s+confluence[-_]page[-_]id:\s*(\d+)\s+-->", text
117
+ )
118
+
119
+ # extract Confluence space key
120
+ space_key, text = extract_value(
121
+ r"<!--\s+confluence[-_]space[-_]key:\s*(\S+)\s+-->", text
122
+ )
123
+
124
+ # extract 'generated-by' tag text
125
+ generated_by, text = extract_value(
126
+ r"<!--\s+generated[-_]by:\s*(.*)\s+-->", text
127
+ )
128
+
129
+ title: Optional[str] = None
130
+ tags: Optional[list[str]] = None
131
+
132
+ # extract front-matter
133
+ data, text = extract_frontmatter_properties(text)
134
+ if data is not None:
135
+ p = _json_to_object(DocumentProperties, data)
136
+ page_id = page_id or p.confluence_page_id or p.page_id
137
+ space_key = space_key or p.confluence_space_key or p.space_key
138
+ generated_by = generated_by or p.generated_by
139
+ title = p.title
140
+ tags = p.tags
141
+
142
+ return ScannedDocument(
143
+ page_id=page_id,
144
+ space_key=space_key,
145
+ generated_by=generated_by,
146
+ title=title,
147
+ tags=tags,
148
+ text=text,
149
+ )
@@ -1,22 +0,0 @@
1
- markdown_to_confluence-0.3.4.dist-info/licenses/LICENSE,sha256=Pv43so2bPfmKhmsrmXFyAvS7M30-1i1tzjz6-dfhyOo,1077
2
- md2conf/__init__.py,sha256=9gI6OYCv9-54FzxjNHLOH09H5quUDEMWq9pdbhnwoXM,402
3
- md2conf/__main__.py,sha256=bFcfmSnTWeuhmDm7bJ3jJabZ2S8W9biuAP6_R-Cc9As,8034
4
- md2conf/api.py,sha256=ZIYoBXclLbzrrQ_oFRllsTEnQIMbxqd9OD80-AC5qM0,22769
5
- md2conf/application.py,sha256=eIVeAGUzfdIq1uYLYpTg30UNSq-YcUIY-OgKKK3M4E4,6436
6
- md2conf/converter.py,sha256=2Sgq1WQd-dCtrdTVrBwhowPC8PmubMNCH1aAcRwntjs,39404
7
- md2conf/emoji.py,sha256=48QJtOD0F3Be1laYLvAOwe0GxrJS-vcfjtCdiBsNcAc,1960
8
- md2conf/entities.dtd,sha256=M6NzqL5N7dPs_eUA_6sDsiSLzDaAacrx9LdttiufvYU,30215
9
- md2conf/local.py,sha256=AOuwyvPOXrRRPGOTDeoVYkMPJ9MI2zqRGAvHuY35wy4,3884
10
- md2conf/matcher.py,sha256=FgMFPvGiOqGezCs8OyerfsVo-iIHFoI6LRMzdcjM5UY,3693
11
- md2conf/mermaid.py,sha256=un_KHBDpG5Zad_QD3HN1uBwUxp4I-HVJYhNKbH7KwcA,2312
12
- md2conf/metadata.py,sha256=9BtNRsICbKzPTs63P70XekNARePdW1DtdKNJqXh2ZFM,1013
13
- md2conf/processor.py,sha256=Ko_3WqLK6jM-bEN7OD9Vc3g3vhSjRYawz3fG6uoUsXc,6733
14
- md2conf/properties.py,sha256=TOCXLdTfYkKjRwZaMgvXw0mNCI4opEUwpBXro2Kv2B4,2467
15
- md2conf/puppeteer-config.json,sha256=-dMTAN_7kNTGbDlfXzApl0KJpAWna9YKZdwMKbpOb60,159
16
- md2conf/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- markdown_to_confluence-0.3.4.dist-info/METADATA,sha256=PUtJXudDooVfwOzVtohxweWHMjgDv5CIrDvyqiJ0tlg,17745
18
- markdown_to_confluence-0.3.4.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
19
- markdown_to_confluence-0.3.4.dist-info/entry_points.txt,sha256=F1zxa1wtEObtbHS-qp46330WVFLHdMnV2wQ-ZorRmX0,50
20
- markdown_to_confluence-0.3.4.dist-info/top_level.txt,sha256=_FJfl_kHrHNidyjUOuS01ngu_jDsfc-ZjSocNRJnTzU,8
21
- markdown_to_confluence-0.3.4.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
22
- markdown_to_confluence-0.3.4.dist-info/RECORD,,