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.
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/PKG-INFO +64 -11
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/README.md +60 -7
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/markdown_to_confluence.egg-info/PKG-INFO +64 -11
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/markdown_to_confluence.egg-info/SOURCES.txt +2 -1
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/markdown_to_confluence.egg-info/requires.txt +3 -3
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/__init__.py +1 -1
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/__main__.py +31 -2
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/api.py +35 -8
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/application.py +14 -3
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/converter.py +258 -14
- markdown_to_confluence-0.2.0/md2conf/mermaid.py +54 -0
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/processor.py +2 -2
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/setup.cfg +3 -3
- markdown_to_confluence-0.2.0/tests/test_conversion.py +113 -0
- markdown_to_confluence-0.2.0/tests/test_mermaid.py +53 -0
- markdown_to_confluence-0.1.12/tests/test_api.py +0 -138
- markdown_to_confluence-0.1.12/tests/test_conversion.py +0 -58
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/LICENSE +0 -0
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/markdown_to_confluence.egg-info/dependency_links.txt +0 -0
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/markdown_to_confluence.egg-info/entry_points.txt +0 -0
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/markdown_to_confluence.egg-info/top_level.txt +0 -0
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/markdown_to_confluence.egg-info/zip-safe +0 -0
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/entities.dtd +0 -0
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/properties.py +0 -0
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/md2conf/py.typed +0 -0
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/pyproject.toml +0 -0
- {markdown_to_confluence-0.1.12 → markdown_to_confluence-0.2.0}/setup.py +0 -0
- {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.
|
|
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.
|
|
25
|
-
Requires-Dist: types-lxml>=2024.
|
|
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.
|
|
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
|
-
*
|
|
53
|
-
* [
|
|
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
|
-
```
|
|
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]
|
|
143
|
-
[--no-generated-by] [--
|
|
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
|
-
|
|
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
|
-
*
|
|
22
|
-
* [
|
|
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
|
-
```
|
|
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]
|
|
112
|
-
[--no-generated-by] [--
|
|
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
|
-
|
|
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.
|
|
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.
|
|
25
|
-
Requires-Dist: types-lxml>=2024.
|
|
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.
|
|
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
|
-
*
|
|
53
|
-
* [
|
|
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
|
-
```
|
|
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]
|
|
143
|
-
[--no-generated-by] [--
|
|
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
|
-
|
|
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
|
|
@@ -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.
|
|
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
|
-
|
|
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 =
|
|
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
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
|
|
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
|
-
|
|
247
|
+
io.BytesIO(raw_data), # type: ignore
|
|
221
248
|
content_type,
|
|
222
249
|
{"Expires": "0"},
|
|
223
250
|
),
|
|
224
251
|
}
|
|
225
|
-
|
|
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,
|
|
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")
|