markdown-to-confluence 0.1.12__tar.gz → 0.2.0__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.
Files changed (28) hide show
  1. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/PKG-INFO +64 -11
  2. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/README.md +60 -7
  3. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/markdown_to_confluence.egg-info/PKG-INFO +64 -11
  4. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/markdown_to_confluence.egg-info/SOURCES.txt +2 -1
  5. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/markdown_to_confluence.egg-info/requires.txt +3 -3
  6. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/__init__.py +1 -1
  7. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/__main__.py +31 -2
  8. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/api.py +35 -8
  9. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/application.py +14 -3
  10. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/converter.py +258 -14
  11. markdown_to_confluence-0.2.0/md2conf/mermaid.py +54 -0
  12. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/processor.py +2 -2
  13. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/setup.cfg +3 -3
  14. markdown_to_confluence-0.2.0/tests/test_conversion.py +113 -0
  15. markdown_to_confluence-0.2.0/tests/test_mermaid.py +53 -0
  16. markdown_to_confluence-0.1.12/tests/test_api.py +0 -138
  17. markdown_to_confluence-0.1.12/tests/test_conversion.py +0 -58
  18. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/LICENSE +0 -0
  19. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/markdown_to_confluence.egg-info/dependency_links.txt +0 -0
  20. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/markdown_to_confluence.egg-info/entry_points.txt +0 -0
  21. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/markdown_to_confluence.egg-info/top_level.txt +0 -0
  22. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/markdown_to_confluence.egg-info/zip-safe +0 -0
  23. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/entities.dtd +0 -0
  24. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/properties.py +0 -0
  25. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/py.typed +0 -0
  26. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/pyproject.toml +0 -0
  27. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/setup.py +0 -0
  28. {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/tests/test_processor.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: markdown-to-confluence
3
- Version: 0.1.12
3
+ Version: 0.2.0
4
4
  Summary: Publish Markdown files to Confluence wiki
5
5
  Home-page: https://github.com/hunyadi/md2conf
6
6
  Author: Levente Hunyadi
@@ -21,11 +21,11 @@ Classifier: Typing :: Typed
21
21
  Requires-Python: >=3.8
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
- Requires-Dist: lxml>=5.2
25
- Requires-Dist: types-lxml>=2024.4.14
24
+ Requires-Dist: lxml>=5.3
25
+ Requires-Dist: types-lxml>=2024.8.7
26
26
  Requires-Dist: markdown>=3.6
27
27
  Requires-Dist: types-markdown>=3.6
28
- Requires-Dist: pymdown-extensions>=10.8
28
+ Requires-Dist: pymdown-extensions>=10.9
29
29
  Requires-Dist: requests>=2.32
30
30
  Requires-Dist: types-requests>=2.32
31
31
 
@@ -45,12 +45,29 @@ This Python package
45
45
 
46
46
  * Sections and subsections
47
47
  * Text with **bold**, *italic*, `monospace`, <ins>underline</ins> and ~~strikethrough~~
48
- * Link to [external locations](http://example.com/)
48
+ * Link to [sections on the same page](#getting-started) or [external locations](http://example.com/)
49
49
  * Ordered and unordered lists
50
50
  * Code blocks (e.g. Python, JSON, XML)
51
51
  * Image references (uploaded as Confluence page attachments)
52
- * [Table of Contents](https://docs.gitlab.com/ee/user/markdown.html#table-of-contents)
53
- * [Admonitions](https://python-markdown.github.io/extensions/admonition/) (converted into *info*, *tip*, *note* and *warning* Confluence panels)
52
+ * Tables
53
+ * [Table of contents](https://docs.gitlab.com/ee/user/markdown.html#table-of-contents)
54
+ * [Admonitions](https://python-markdown.github.io/extensions/admonition/) and [alerts](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts)
55
+ * [Collapsed sections](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-collapsed-sections)
56
+ * [Mermaid diagrams](https://mermaid.live/) in code blocks (converted to images)
57
+
58
+ ## Installation
59
+
60
+ Install the core package from PyPI:
61
+
62
+ ```sh
63
+ pip install markdown-to-confluence
64
+ ```
65
+
66
+ Converting code blocks of Mermaid diagrams into Confluence image attachments requires [mermaid-cli](https://github.com/mermaid-js/mermaid-cli):
67
+
68
+ ```sh
69
+ npm install -g @mermaid-js/mermaid-cli
70
+ ```
54
71
 
55
72
  ## Getting started
56
73
 
@@ -131,7 +148,7 @@ Alternatively, use the `--generated-by GENERATED_BY` option. The tag takes prece
131
148
 
132
149
  You execute the command-line tool `md2conf` to synchronize the Markdown file with Confluence:
133
150
 
134
- ```console
151
+ ```sh
135
152
  $ python3 -m md2conf sample/example.md
136
153
  ```
137
154
 
@@ -139,14 +156,15 @@ Use the `--help` switch to get a full list of supported command-line options:
139
156
 
140
157
  ```console
141
158
  $ python3 -m md2conf --help
142
- usage: md2conf [-h] [-d DOMAIN] [-p PATH] [-u USERNAME] [-a APIKEY] [-s SPACE] [-l {debug,info,warning,error,critical}] [-r ROOT_PAGE] [--generated-by GENERATED_BY]
143
- [--no-generated-by] [--ignore-invalid-url] [--local]
159
+ usage: md2conf [-h] [-d DOMAIN] [-p PATH] [-u USERNAME] [-a APIKEY] [-s SPACE] [-l {debug,info,warning,error,critical}] [-r ROOT_PAGE]
160
+ [--generated-by GENERATED_BY] [--no-generated-by] [--render-mermaid] [--no-render-mermaid]
161
+ [--render-mermaid-format {png,svg}] [--heading-anchors] [--ignore-invalid-url] [--local]
144
162
  mdpath
145
163
 
146
164
  positional arguments:
147
165
  mdpath Path to Markdown file or directory to convert and publish.
148
166
 
149
- optional arguments:
167
+ options:
150
168
  -h, --help show this help message and exit
151
169
  -d DOMAIN, --domain DOMAIN
152
170
  Confluence organization domain.
@@ -163,6 +181,41 @@ optional arguments:
163
181
  --generated-by GENERATED_BY
164
182
  Add prompt to pages (default: 'This page has been generated with a tool.').
165
183
  --no-generated-by Do not add 'generated by a tool' prompt to pages.
184
+ --render-mermaid Render Mermaid diagrams as image files and add as attachments.
185
+ --no-render-mermaid Inline Mermaid diagram in Confluence page.
186
+ --render-mermaid-format {png,svg}
187
+ Format for rendering Mermaid diagrams (default: 'png').
188
+ --heading-anchors Place an anchor at each section heading with GitHub-style same-page identifiers.
166
189
  --ignore-invalid-url Emit a warning but otherwise ignore relative URLs that point to ill-specified locations.
167
190
  --local Write XHTML-based Confluence Storage Format files locally without invoking Confluence API.
168
191
  ```
192
+
193
+ ### Using the docker container
194
+
195
+ You can run the docker container via `docker run` or via `Dockerfile`. Either can accept the environment variables or arguments similar to the Python options. The final argument `./` corresponds to `mdpath` in the command-line utility.
196
+
197
+ ```sh
198
+ docker run --rm --name md2conf hunyadi/md2conf -d instructure.atlassian.net -u levente.hunyadi@instructure.com -a 0123456789abcdef -s DAP ./
199
+ ```
200
+
201
+ Note that the entry point for the docker container's base image is `ENTRYPOINT ["python3", "-m", "md2conf"]`.
202
+
203
+ ```Dockerfile
204
+ FROM hunyadi/md2conf:latest
205
+
206
+ ENV CONFLUENCE_DOMAIN='instructure.atlassian.net'
207
+ ENV CONFLUENCE_PATH='/wiki/'
208
+ ENV CONFLUENCE_USER_NAME='levente.hunyadi@instructure.com'
209
+ ENV CONFLUENCE_API_KEY='0123456789abcdef'
210
+ ENV CONFLUENCE_SPACE_KEY='DAP'
211
+
212
+ CMD ["./"]
213
+ ```
214
+
215
+ Alternatively,
216
+
217
+ ```Dockerfile
218
+ FROM hunyadi/md2conf:latest
219
+
220
+ CMD ["-d", "instructure.atlassian.net", "-u", "levente.hunyadi@instructure.com", "-a", "0123456789abcdef", "-s", "DAP", "./"]
221
+ ```
@@ -14,12 +14,29 @@ This Python package
14
14
 
15
15
  * Sections and subsections
16
16
  * Text with **bold**, *italic*, `monospace`, <ins>underline</ins> and ~~strikethrough~~
17
- * Link to [external locations](http://example.com/)
17
+ * Link to [sections on the same page](#getting-started) or [external locations](http://example.com/)
18
18
  * Ordered and unordered lists
19
19
  * Code blocks (e.g. Python, JSON, XML)
20
20
  * Image references (uploaded as Confluence page attachments)
21
- * [Table of Contents](https://docs.gitlab.com/ee/user/markdown.html#table-of-contents)
22
- * [Admonitions](https://python-markdown.github.io/extensions/admonition/) (converted into *info*, *tip*, *note* and *warning* Confluence panels)
21
+ * Tables
22
+ * [Table of contents](https://docs.gitlab.com/ee/user/markdown.html#table-of-contents)
23
+ * [Admonitions](https://python-markdown.github.io/extensions/admonition/) and [alerts](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts)
24
+ * [Collapsed sections](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-collapsed-sections)
25
+ * [Mermaid diagrams](https://mermaid.live/) in code blocks (converted to images)
26
+
27
+ ## Installation
28
+
29
+ Install the core package from PyPI:
30
+
31
+ ```sh
32
+ pip install markdown-to-confluence
33
+ ```
34
+
35
+ Converting code blocks of Mermaid diagrams into Confluence image attachments requires [mermaid-cli](https://github.com/mermaid-js/mermaid-cli):
36
+
37
+ ```sh
38
+ npm install -g @mermaid-js/mermaid-cli
39
+ ```
23
40
 
24
41
  ## Getting started
25
42
 
@@ -100,7 +117,7 @@ Alternatively, use the `--generated-by GENERATED_BY` option. The tag takes prece
100
117
 
101
118
  You execute the command-line tool `md2conf` to synchronize the Markdown file with Confluence:
102
119
 
103
- ```console
120
+ ```sh
104
121
  $ python3 -m md2conf sample/example.md
105
122
  ```
106
123
 
@@ -108,14 +125,15 @@ Use the `--help` switch to get a full list of supported command-line options:
108
125
 
109
126
  ```console
110
127
  $ python3 -m md2conf --help
111
- usage: md2conf [-h] [-d DOMAIN] [-p PATH] [-u USERNAME] [-a APIKEY] [-s SPACE] [-l {debug,info,warning,error,critical}] [-r ROOT_PAGE] [--generated-by GENERATED_BY]
112
- [--no-generated-by] [--ignore-invalid-url] [--local]
128
+ usage: md2conf [-h] [-d DOMAIN] [-p PATH] [-u USERNAME] [-a APIKEY] [-s SPACE] [-l {debug,info,warning,error,critical}] [-r ROOT_PAGE]
129
+ [--generated-by GENERATED_BY] [--no-generated-by] [--render-mermaid] [--no-render-mermaid]
130
+ [--render-mermaid-format {png,svg}] [--heading-anchors] [--ignore-invalid-url] [--local]
113
131
  mdpath
114
132
 
115
133
  positional arguments:
116
134
  mdpath Path to Markdown file or directory to convert and publish.
117
135
 
118
- optional arguments:
136
+ options:
119
137
  -h, --help show this help message and exit
120
138
  -d DOMAIN, --domain DOMAIN
121
139
  Confluence organization domain.
@@ -132,6 +150,41 @@ optional arguments:
132
150
  --generated-by GENERATED_BY
133
151
  Add prompt to pages (default: 'This page has been generated with a tool.').
134
152
  --no-generated-by Do not add 'generated by a tool' prompt to pages.
153
+ --render-mermaid Render Mermaid diagrams as image files and add as attachments.
154
+ --no-render-mermaid Inline Mermaid diagram in Confluence page.
155
+ --render-mermaid-format {png,svg}
156
+ Format for rendering Mermaid diagrams (default: 'png').
157
+ --heading-anchors Place an anchor at each section heading with GitHub-style same-page identifiers.
135
158
  --ignore-invalid-url Emit a warning but otherwise ignore relative URLs that point to ill-specified locations.
136
159
  --local Write XHTML-based Confluence Storage Format files locally without invoking Confluence API.
137
160
  ```
161
+
162
+ ### Using the docker container
163
+
164
+ You can run the docker container via `docker run` or via `Dockerfile`. Either can accept the environment variables or arguments similar to the Python options. The final argument `./` corresponds to `mdpath` in the command-line utility.
165
+
166
+ ```sh
167
+ docker run --rm --name md2conf hunyadi/md2conf -d instructure.atlassian.net -u levente.hunyadi@instructure.com -a 0123456789abcdef -s DAP ./
168
+ ```
169
+
170
+ Note that the entry point for the docker container's base image is `ENTRYPOINT ["python3", "-m", "md2conf"]`.
171
+
172
+ ```Dockerfile
173
+ FROM hunyadi/md2conf:latest
174
+
175
+ ENV CONFLUENCE_DOMAIN='instructure.atlassian.net'
176
+ ENV CONFLUENCE_PATH='/wiki/'
177
+ ENV CONFLUENCE_USER_NAME='levente.hunyadi@instructure.com'
178
+ ENV CONFLUENCE_API_KEY='0123456789abcdef'
179
+ ENV CONFLUENCE_SPACE_KEY='DAP'
180
+
181
+ CMD ["./"]
182
+ ```
183
+
184
+ Alternatively,
185
+
186
+ ```Dockerfile
187
+ FROM hunyadi/md2conf:latest
188
+
189
+ CMD ["-d", "instructure.atlassian.net", "-u", "levente.hunyadi@instructure.com", "-a", "0123456789abcdef", "-s", "DAP", "./"]
190
+ ```
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: markdown-to-confluence
3
- Version: 0.1.12
3
+ Version: 0.2.0
4
4
  Summary: Publish Markdown files to Confluence wiki
5
5
  Home-page: https://github.com/hunyadi/md2conf
6
6
  Author: Levente Hunyadi
@@ -21,11 +21,11 @@ Classifier: Typing :: Typed
21
21
  Requires-Python: >=3.8
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
- Requires-Dist: lxml>=5.2
25
- Requires-Dist: types-lxml>=2024.4.14
24
+ Requires-Dist: lxml>=5.3
25
+ Requires-Dist: types-lxml>=2024.8.7
26
26
  Requires-Dist: markdown>=3.6
27
27
  Requires-Dist: types-markdown>=3.6
28
- Requires-Dist: pymdown-extensions>=10.8
28
+ Requires-Dist: pymdown-extensions>=10.9
29
29
  Requires-Dist: requests>=2.32
30
30
  Requires-Dist: types-requests>=2.32
31
31
 
@@ -45,12 +45,29 @@ This Python package
45
45
 
46
46
  * Sections and subsections
47
47
  * Text with **bold**, *italic*, `monospace`, <ins>underline</ins> and ~~strikethrough~~
48
- * Link to [external locations](http://example.com/)
48
+ * Link to [sections on the same page](#getting-started) or [external locations](http://example.com/)
49
49
  * Ordered and unordered lists
50
50
  * Code blocks (e.g. Python, JSON, XML)
51
51
  * Image references (uploaded as Confluence page attachments)
52
- * [Table of Contents](https://docs.gitlab.com/ee/user/markdown.html#table-of-contents)
53
- * [Admonitions](https://python-markdown.github.io/extensions/admonition/) (converted into *info*, *tip*, *note* and *warning* Confluence panels)
52
+ * Tables
53
+ * [Table of contents](https://docs.gitlab.com/ee/user/markdown.html#table-of-contents)
54
+ * [Admonitions](https://python-markdown.github.io/extensions/admonition/) and [alerts](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts)
55
+ * [Collapsed sections](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-collapsed-sections)
56
+ * [Mermaid diagrams](https://mermaid.live/) in code blocks (converted to images)
57
+
58
+ ## Installation
59
+
60
+ Install the core package from PyPI:
61
+
62
+ ```sh
63
+ pip install markdown-to-confluence
64
+ ```
65
+
66
+ Converting code blocks of Mermaid diagrams into Confluence image attachments requires [mermaid-cli](https://github.com/mermaid-js/mermaid-cli):
67
+
68
+ ```sh
69
+ npm install -g @mermaid-js/mermaid-cli
70
+ ```
54
71
 
55
72
  ## Getting started
56
73
 
@@ -131,7 +148,7 @@ Alternatively, use the `--generated-by GENERATED_BY` option. The tag takes prece
131
148
 
132
149
  You execute the command-line tool `md2conf` to synchronize the Markdown file with Confluence:
133
150
 
134
- ```console
151
+ ```sh
135
152
  $ python3 -m md2conf sample/example.md
136
153
  ```
137
154
 
@@ -139,14 +156,15 @@ Use the `--help` switch to get a full list of supported command-line options:
139
156
 
140
157
  ```console
141
158
  $ python3 -m md2conf --help
142
- usage: md2conf [-h] [-d DOMAIN] [-p PATH] [-u USERNAME] [-a APIKEY] [-s SPACE] [-l {debug,info,warning,error,critical}] [-r ROOT_PAGE] [--generated-by GENERATED_BY]
143
- [--no-generated-by] [--ignore-invalid-url] [--local]
159
+ usage: md2conf [-h] [-d DOMAIN] [-p PATH] [-u USERNAME] [-a APIKEY] [-s SPACE] [-l {debug,info,warning,error,critical}] [-r ROOT_PAGE]
160
+ [--generated-by GENERATED_BY] [--no-generated-by] [--render-mermaid] [--no-render-mermaid]
161
+ [--render-mermaid-format {png,svg}] [--heading-anchors] [--ignore-invalid-url] [--local]
144
162
  mdpath
145
163
 
146
164
  positional arguments:
147
165
  mdpath Path to Markdown file or directory to convert and publish.
148
166
 
149
- optional arguments:
167
+ options:
150
168
  -h, --help show this help message and exit
151
169
  -d DOMAIN, --domain DOMAIN
152
170
  Confluence organization domain.
@@ -163,6 +181,41 @@ optional arguments:
163
181
  --generated-by GENERATED_BY
164
182
  Add prompt to pages (default: 'This page has been generated with a tool.').
165
183
  --no-generated-by Do not add 'generated by a tool' prompt to pages.
184
+ --render-mermaid Render Mermaid diagrams as image files and add as attachments.
185
+ --no-render-mermaid Inline Mermaid diagram in Confluence page.
186
+ --render-mermaid-format {png,svg}
187
+ Format for rendering Mermaid diagrams (default: 'png').
188
+ --heading-anchors Place an anchor at each section heading with GitHub-style same-page identifiers.
166
189
  --ignore-invalid-url Emit a warning but otherwise ignore relative URLs that point to ill-specified locations.
167
190
  --local Write XHTML-based Confluence Storage Format files locally without invoking Confluence API.
168
191
  ```
192
+
193
+ ### Using the docker container
194
+
195
+ You can run the docker container via `docker run` or via `Dockerfile`. Either can accept the environment variables or arguments similar to the Python options. The final argument `./` corresponds to `mdpath` in the command-line utility.
196
+
197
+ ```sh
198
+ docker run --rm --name md2conf hunyadi/md2conf -d instructure.atlassian.net -u levente.hunyadi@instructure.com -a 0123456789abcdef -s DAP ./
199
+ ```
200
+
201
+ Note that the entry point for the docker container's base image is `ENTRYPOINT ["python3", "-m", "md2conf"]`.
202
+
203
+ ```Dockerfile
204
+ FROM hunyadi/md2conf:latest
205
+
206
+ ENV CONFLUENCE_DOMAIN='instructure.atlassian.net'
207
+ ENV CONFLUENCE_PATH='/wiki/'
208
+ ENV CONFLUENCE_USER_NAME='levente.hunyadi@instructure.com'
209
+ ENV CONFLUENCE_API_KEY='0123456789abcdef'
210
+ ENV CONFLUENCE_SPACE_KEY='DAP'
211
+
212
+ CMD ["./"]
213
+ ```
214
+
215
+ Alternatively,
216
+
217
+ ```Dockerfile
218
+ FROM hunyadi/md2conf:latest
219
+
220
+ CMD ["-d", "instructure.atlassian.net", "-u", "levente.hunyadi@instructure.com", "-a", "0123456789abcdef", "-s", "DAP", "./"]
221
+ ```
@@ -16,9 +16,10 @@ md2conf/api.py
16
16
  md2conf/application.py
17
17
  md2conf/converter.py
18
18
  md2conf/entities.dtd
19
+ md2conf/mermaid.py
19
20
  md2conf/processor.py
20
21
  md2conf/properties.py
21
22
  md2conf/py.typed
22
- tests/test_api.py
23
23
  tests/test_conversion.py
24
+ tests/test_mermaid.py
24
25
  tests/test_processor.py
@@ -1,7 +1,7 @@
1
- lxml>=5.2
2
- types-lxml>=2024.4.14
1
+ lxml>=5.3
2
+ types-lxml>=2024.8.7
3
3
  markdown>=3.6
4
4
  types-markdown>=3.6
5
- pymdown-extensions>=10.8
5
+ pymdown-extensions>=10.9
6
6
  requests>=2.32
7
7
  types-requests>=2.32
@@ -5,7 +5,7 @@ Parses Markdown files, converts Markdown content into the Confluence Storage For
5
5
  Confluence API endpoints to upload images and content.
6
6
  """
7
7
 
8
- __version__ = "0.1.12"
8
+ __version__ = "0.2.0"
9
9
  __author__ = "Levente Hunyadi"
10
10
  __copyright__ = "Copyright 2022-2024, Levente Hunyadi"
11
11
  __license__ = "MIT"
@@ -2,7 +2,6 @@ import argparse
2
2
  import logging
3
3
  import os.path
4
4
  import sys
5
- import typing
6
5
  from pathlib import Path
7
6
  from typing import Optional
8
7
 
@@ -24,6 +23,7 @@ class Arguments(argparse.Namespace):
24
23
  space: str
25
24
  loglevel: str
26
25
  ignore_invalid_url: bool
26
+ heading_anchors: bool
27
27
  generated_by: Optional[str]
28
28
 
29
29
 
@@ -52,7 +52,7 @@ def main() -> None:
52
52
  "-l",
53
53
  "--loglevel",
54
54
  choices=[
55
- typing.cast(str, logging.getLevelName(level)).lower()
55
+ logging.getLevelName(level).lower()
56
56
  for level in (
57
57
  logging.DEBUG,
58
58
  logging.INFO,
@@ -81,6 +81,32 @@ def main() -> None:
81
81
  const=None,
82
82
  help="Do not add 'generated by a tool' prompt to pages.",
83
83
  )
84
+ parser.add_argument(
85
+ "--render-mermaid",
86
+ dest="render_mermaid",
87
+ action="store_true",
88
+ default=True,
89
+ help="Render Mermaid diagrams as image files and add as attachments.",
90
+ )
91
+ parser.add_argument(
92
+ "--no-render-mermaid",
93
+ dest="render_mermaid",
94
+ action="store_false",
95
+ help="Inline Mermaid diagram in Confluence page.",
96
+ )
97
+ parser.add_argument(
98
+ "--render-mermaid-format",
99
+ dest="diagram_output_format",
100
+ choices=["png", "svg"],
101
+ default="png",
102
+ help="Format for rendering Mermaid diagrams (default: 'png').",
103
+ )
104
+ parser.add_argument(
105
+ "--heading-anchors",
106
+ action="store_true",
107
+ default=False,
108
+ help="Place an anchor at each section heading with GitHub-style same-page identifiers.",
109
+ )
84
110
  parser.add_argument(
85
111
  "--ignore-invalid-url",
86
112
  action="store_true",
@@ -107,9 +133,12 @@ def main() -> None:
107
133
  )
108
134
 
109
135
  options = ConfluenceDocumentOptions(
136
+ heading_anchors=args.heading_anchors,
110
137
  ignore_invalid_url=args.ignore_invalid_url,
111
138
  generated_by=args.generated_by,
112
139
  root_page_id=args.root_page,
140
+ render_mermaid=args.render_mermaid,
141
+ diagram_output_format=args.diagram_output_format,
113
142
  )
114
143
  properties = ConfluenceProperties(
115
144
  args.domain, args.path, args.username, args.apikey, args.space
@@ -1,3 +1,4 @@
1
+ import io
1
2
  import json
2
3
  import logging
3
4
  import mimetypes
@@ -177,7 +178,8 @@ class ConfluenceSession:
177
178
  extensions = typing.cast(Dict[str, JsonType], result["extensions"])
178
179
  media_type = typing.cast(str, extensions["mediaType"])
179
180
  file_size = typing.cast(int, extensions["fileSize"])
180
- comment = typing.cast(str, extensions["comment"])
181
+ comment = extensions.get("comment", "")
182
+ comment = typing.cast(str, comment)
181
183
  return ConfluenceAttachment(id, media_type, file_size, comment)
182
184
 
183
185
  def upload_attachment(
@@ -185,6 +187,7 @@ class ConfluenceSession:
185
187
  page_id: str,
186
188
  attachment_path: Path,
187
189
  attachment_name: str,
190
+ raw_data: Optional[bytes] = None,
188
191
  comment: Optional[str] = None,
189
192
  *,
190
193
  space_key: Optional[str] = None,
@@ -192,7 +195,7 @@ class ConfluenceSession:
192
195
  ) -> None:
193
196
  content_type = mimetypes.guess_type(attachment_path, strict=True)[0]
194
197
 
195
- if not attachment_path.is_file():
198
+ if not raw_data and not attachment_path.is_file():
196
199
  raise ConfluenceError(f"file not found: {attachment_path}")
197
200
 
198
201
  try:
@@ -200,9 +203,14 @@ class ConfluenceSession:
200
203
  page_id, attachment_name, space_key=space_key
201
204
  )
202
205
 
203
- if not force and attachment.file_size == attachment_path.stat().st_size:
204
- LOGGER.info("Up-to-date attachment: %s", attachment_name)
205
- return
206
+ if not raw_data:
207
+ if not force and attachment.file_size == attachment_path.stat().st_size:
208
+ LOGGER.info("Up-to-date attachment: %s", attachment_name)
209
+ return
210
+ else:
211
+ if not force and attachment.file_size == len(raw_data):
212
+ LOGGER.info("Up-to-date embedded image: %s", attachment_name)
213
+ return
206
214
 
207
215
  id = removeprefix(attachment.id, "att")
208
216
  path = f"/content/{page_id}/child/attachment/{id}/data"
@@ -212,17 +220,36 @@ class ConfluenceSession:
212
220
 
213
221
  url = self._build_url(path)
214
222
 
215
- with open(attachment_path, "rb") as attachment_file:
223
+ if not raw_data:
224
+ with open(attachment_path, "rb") as attachment_file:
225
+ file_to_upload = {
226
+ "comment": comment,
227
+ "file": (
228
+ attachment_name, # will truncate path component
229
+ attachment_file,
230
+ content_type,
231
+ {"Expires": "0"},
232
+ ),
233
+ }
234
+ LOGGER.info("Uploading attachment: %s", attachment_name)
235
+ response = self.session.post(
236
+ url,
237
+ files=file_to_upload, # type: ignore
238
+ headers={"X-Atlassian-Token": "no-check"},
239
+ )
240
+ else:
241
+ LOGGER.info("Uploading raw data: %s", attachment_name)
242
+
216
243
  file_to_upload = {
217
244
  "comment": comment,
218
245
  "file": (
219
246
  attachment_name, # will truncate path component
220
- attachment_file,
247
+ io.BytesIO(raw_data), # type: ignore
221
248
  content_type,
222
249
  {"Expires": "0"},
223
250
  ),
224
251
  }
225
- LOGGER.info("Uploading attachment: %s", attachment_name)
252
+
226
253
  response = self.session.post(
227
254
  url,
228
255
  files=file_to_upload, # type: ignore
@@ -94,7 +94,7 @@ class Application:
94
94
  """
95
95
 
96
96
  # parse file
97
- with open(absolute_path, "r") as f:
97
+ with open(absolute_path, "r", encoding="utf-8") as f:
98
98
  document = f.read()
99
99
 
100
100
  qualified_id, document = extract_qualified_id(document)
@@ -131,9 +131,20 @@ class Application:
131
131
  )
132
132
 
133
133
  def _update_document(self, document: ConfluenceDocument, base_path: Path) -> None:
134
+
134
135
  for image in document.images:
135
136
  self.api.upload_attachment(
136
- document.id.page_id, base_path / image, attachment_name(image), ""
137
+ document.id.page_id,
138
+ base_path / image,
139
+ attachment_name(image),
140
+ )
141
+
142
+ for image, data in document.embedded_images.items():
143
+ self.api.upload_attachment(
144
+ document.id.page_id,
145
+ Path("EMB") / image,
146
+ attachment_name(image),
147
+ raw_data=data,
137
148
  )
138
149
 
139
150
  content = document.xhtml()
@@ -147,7 +158,7 @@ class Application:
147
158
  page_id: str,
148
159
  space_key: Optional[str],
149
160
  ) -> None:
150
- with open(path, "w") as file:
161
+ with open(path, "w", encoding="utf-8") as file:
151
162
  file.write(f"<!-- confluence-page-id: {page_id} -->\n")
152
163
  if space_key:
153
164
  file.write(f"<!-- confluence-space-key: {space_key} -->\n")