markdown-to-confluence 0.3.3__py3-none-any.whl → 0.3.5__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,117 @@
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
13
+
14
+ import yaml
15
+
16
+
17
+ def extract_value(pattern: str, text: str) -> tuple[Optional[str], str]:
18
+ values: list[str] = []
19
+
20
+ def _repl_func(matchobj: re.Match) -> str:
21
+ values.append(matchobj.group(1))
22
+ return ""
23
+
24
+ text = re.sub(pattern, _repl_func, text, count=1, flags=re.ASCII)
25
+ value = values[0] if values else None
26
+ return value, text
27
+
28
+
29
+ def extract_frontmatter_block(text: str) -> tuple[Optional[str], str]:
30
+ "Extracts the front-matter from a Markdown document as a blob of unparsed text."
31
+
32
+ return extract_value(r"(?ms)\A---$(.+?)^---$", text)
33
+
34
+
35
+ def extract_frontmatter_properties(text: str) -> tuple[Optional[dict[str, Any]], str]:
36
+ "Extracts the front-matter from a Markdown document as a dictionary."
37
+
38
+ block, text = extract_frontmatter_block(text)
39
+
40
+ properties: Optional[dict[str, Any]] = None
41
+ if block is not None:
42
+ data = yaml.safe_load(block)
43
+ if isinstance(data, dict):
44
+ properties = data
45
+
46
+ return properties, text
47
+
48
+
49
+ def get_string(properties: dict[str, Any], key: str) -> Optional[str]:
50
+ value = properties.get(key)
51
+ if value is None:
52
+ return None
53
+ elif not isinstance(value, str):
54
+ raise ValueError(
55
+ f"expected dictionary value type of `str` for key `{key}`; got value of type `{type(value).__name__}`"
56
+ )
57
+ else:
58
+ return value
59
+
60
+
61
+ @dataclass
62
+ class ScannedDocument:
63
+ """
64
+ An object that holds properties extracted from a Markdown document, including remaining source text.
65
+
66
+ :param page_id: Confluence page ID.
67
+ :param space_key: Confluence space key.
68
+ :param generated_by: Text identifying the tool that generated the document.
69
+ :param title: The title extracted from front-matter.
70
+ :param text: Text that remains after front-matter and inline properties have been extracted.
71
+ """
72
+
73
+ page_id: Optional[str]
74
+ space_key: Optional[str]
75
+ generated_by: Optional[str]
76
+ title: Optional[str]
77
+ text: str
78
+
79
+
80
+ class Scanner:
81
+ def read(self, absolute_path: Path) -> ScannedDocument:
82
+ """
83
+ Extracts essential properties from a Markdown document.
84
+ """
85
+
86
+ # parse file
87
+ with open(absolute_path, "r", encoding="utf-8") as f:
88
+ text = f.read()
89
+
90
+ # extract Confluence page ID
91
+ page_id, text = extract_value(r"<!--\s+confluence-page-id:\s*(\d+)\s+-->", text)
92
+
93
+ # extract Confluence space key
94
+ space_key, text = extract_value(
95
+ r"<!--\s+confluence-space-key:\s*(\S+)\s+-->", text
96
+ )
97
+
98
+ # extract 'generated-by' tag text
99
+ generated_by, text = extract_value(r"<!--\s+generated-by:\s*(.*)\s+-->", text)
100
+
101
+ title: Optional[str] = None
102
+
103
+ # extract front-matter
104
+ properties, text = extract_frontmatter_properties(text)
105
+ if properties is not None:
106
+ page_id = page_id or get_string(properties, "confluence-page-id")
107
+ space_key = space_key or get_string(properties, "confluence-space-key")
108
+ generated_by = generated_by or get_string(properties, "generated-by")
109
+ title = get_string(properties, "title")
110
+
111
+ return ScannedDocument(
112
+ page_id=page_id,
113
+ space_key=space_key,
114
+ generated_by=generated_by,
115
+ title=title,
116
+ text=text,
117
+ )
@@ -1,20 +0,0 @@
1
- markdown_to_confluence-0.3.3.dist-info/licenses/LICENSE,sha256=Pv43so2bPfmKhmsrmXFyAvS7M30-1i1tzjz6-dfhyOo,1077
2
- md2conf/__init__.py,sha256=NHoSu8tHMVLytWmla4BA_Uzkl-04rV_O8YkkFxUkT_E,402
3
- md2conf/__main__.py,sha256=aTRiXcvoIYMkwCGejL6MUriHXBo3qVP2Acr2I-XzMyg,7947
4
- md2conf/api.py,sha256=S5IB7j48wE9MHSj1jodHYmTE6scSXb80faULW6-5RjU,20376
5
- md2conf/application.py,sha256=FkJ9zYBLwYcCRkd_WiX6JI6nlw4QMETmrOXHeSzCwCE,9735
6
- md2conf/converter.py,sha256=B4Z8afTmhea6nSXhzDVxN55GfMvlY34tGqCLspQ_p5g,38983
7
- md2conf/emoji.py,sha256=48QJtOD0F3Be1laYLvAOwe0GxrJS-vcfjtCdiBsNcAc,1960
8
- md2conf/entities.dtd,sha256=M6NzqL5N7dPs_eUA_6sDsiSLzDaAacrx9LdttiufvYU,30215
9
- md2conf/matcher.py,sha256=FgMFPvGiOqGezCs8OyerfsVo-iIHFoI6LRMzdcjM5UY,3693
10
- md2conf/mermaid.py,sha256=un_KHBDpG5Zad_QD3HN1uBwUxp4I-HVJYhNKbH7KwcA,2312
11
- md2conf/processor.py,sha256=9jPswgPewh2glLSHdgxyXesGxkcxPVa_h7oUhM9EsA4,4740
12
- md2conf/properties.py,sha256=TOCXLdTfYkKjRwZaMgvXw0mNCI4opEUwpBXro2Kv2B4,2467
13
- md2conf/puppeteer-config.json,sha256=-dMTAN_7kNTGbDlfXzApl0KJpAWna9YKZdwMKbpOb60,159
14
- md2conf/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- markdown_to_confluence-0.3.3.dist-info/METADATA,sha256=SiOfBvA3jMCn3Hjd_Let9R-DqcMuPG48xP-1x2pg_JI,16495
16
- markdown_to_confluence-0.3.3.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
17
- markdown_to_confluence-0.3.3.dist-info/entry_points.txt,sha256=F1zxa1wtEObtbHS-qp46330WVFLHdMnV2wQ-ZorRmX0,50
18
- markdown_to_confluence-0.3.3.dist-info/top_level.txt,sha256=_FJfl_kHrHNidyjUOuS01ngu_jDsfc-ZjSocNRJnTzU,8
19
- markdown_to_confluence-0.3.3.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
20
- markdown_to_confluence-0.3.3.dist-info/RECORD,,