markdown-to-confluence 0.4.5__tar.gz → 0.4.6__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.4.5/markdown_to_confluence.egg-info → markdown_to_confluence-0.4.6}/PKG-INFO +35 -13
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/README.md +32 -12
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6/markdown_to_confluence.egg-info}/PKG-INFO +35 -13
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/markdown_to_confluence.egg-info/SOURCES.txt +3 -2
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/markdown_to_confluence.egg-info/requires.txt +6 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/__init__.py +1 -1
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/__main__.py +16 -35
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/api.py +84 -20
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/converter.py +69 -34
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/csf.py +1 -1
- markdown_to_confluence-0.4.6/md2conf/emoticon.py +22 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/mermaid.py +18 -3
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/processor.py +1 -1
- markdown_to_confluence-0.4.5/md2conf/application.py → markdown_to_confluence-0.4.6/md2conf/publisher.py +14 -11
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/scanner.py +46 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/pyproject.toml +2 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/emoji.py +14 -3
- markdown_to_confluence-0.4.6/tests/source/missing.md +13 -0
- markdown_to_confluence-0.4.6/tests/target/missing.xml +16 -0
- markdown_to_confluence-0.4.6/tests/target/table.xml +81 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/tags.xml +8 -8
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/test_conversion.py +3 -5
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/test_scanner.py +40 -1
- markdown_to_confluence-0.4.5/tests/source/missing.md +0 -7
- markdown_to_confluence-0.4.5/tests/target/missing.xml +0 -13
- markdown_to_confluence-0.4.5/tests/target/table.xml +0 -81
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/LICENSE +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/MANIFEST.in +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/markdown_to_confluence.egg-info/dependency_links.txt +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/markdown_to_confluence.egg-info/entry_points.txt +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/markdown_to_confluence.egg-info/top_level.txt +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/markdown_to_confluence.egg-info/zip-safe +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/collection.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/domain.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/drawio.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/entities.dtd +0 -0
- /markdown_to_confluence-0.4.5/md2conf/properties.py → /markdown_to_confluence-0.4.6/md2conf/environment.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/extra.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/latex.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/local.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/markdown.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/matcher.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/metadata.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/puppeteer-config.json +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/py.typed +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/text.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/toc.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/uri.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/md2conf/xml.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/setup.cfg +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/setup.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/__init__.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/admonition.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/alert.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/anchors.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/basic.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/code.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/collapsed.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/fenced.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/figure/diagram.drawio +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/figure/diagram.drawio.png +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/figure/diagram.drawio.svg +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/figure/raster.png +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/figure/vector.svg +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/footnote.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/ignore.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/images/images.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/images.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/macro.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/math.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/mermaid.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/sections.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/status.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/table.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/tags.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/tasklist.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/title.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/source/toc.md +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/admonition.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/alert.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/anchors.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/basic.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/code.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/collapsed.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/fenced.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/footnote.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/images/images.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/images.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/macro.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/math.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/mermaid.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/sections.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/status.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/tasklist.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/target/toc.xml +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/test_drawio.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/test_matcher.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/test_mermaid.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/test_processor.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/test_text.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/test_unit.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/test_xml.py +0 -0
- {markdown_to_confluence-0.4.5 → markdown_to_confluence-0.4.6}/tests/utility.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: markdown-to-confluence
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.6
|
|
4
4
|
Summary: Publish Markdown files to Confluence wiki
|
|
5
5
|
Author-email: Levente Hunyadi <hunyadi@gmail.com>
|
|
6
6
|
Maintainer-email: Levente Hunyadi <hunyadi@gmail.com>
|
|
@@ -23,12 +23,14 @@ Classifier: Typing :: Typed
|
|
|
23
23
|
Requires-Python: >=3.9
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
License-File: LICENSE
|
|
26
|
+
Requires-Dist: certifi>=2025.8.3; python_version < "3.10"
|
|
26
27
|
Requires-Dist: json_strong_typing>=0.4
|
|
27
28
|
Requires-Dist: lxml>=6.0
|
|
28
29
|
Requires-Dist: markdown>=3.8
|
|
29
30
|
Requires-Dist: pymdown-extensions>=10.16
|
|
30
31
|
Requires-Dist: PyYAML>=6.0
|
|
31
32
|
Requires-Dist: requests>=2.32
|
|
33
|
+
Requires-Dist: truststore>=0.10; python_version >= "3.10"
|
|
32
34
|
Requires-Dist: typing-extensions>=4.14; python_version < "3.12"
|
|
33
35
|
Provides-Extra: dev
|
|
34
36
|
Requires-Dist: markdown_doc>=0.1.4; python_version >= "3.10" and extra == "dev"
|
|
@@ -143,7 +145,7 @@ export CONFLUENCE_SPACE_KEY='SPACE'
|
|
|
143
145
|
|
|
144
146
|
On Windows, these can be set via system properties.
|
|
145
147
|
|
|
146
|
-
If you use Atlassian scoped API tokens, you
|
|
148
|
+
If you use Atlassian scoped API tokens, you may want to set API URL directly, substituting `CLOUD_ID` with your own Cloud ID:
|
|
147
149
|
|
|
148
150
|
```sh
|
|
149
151
|
export CONFLUENCE_API_URL='https://api.atlassian.com/ex/confluence/CLOUD_ID/'
|
|
@@ -151,20 +153,27 @@ export CONFLUENCE_API_URL='https://api.atlassian.com/ex/confluence/CLOUD_ID/'
|
|
|
151
153
|
|
|
152
154
|
In this case, *md2conf* can automatically determine `CONFLUENCE_DOMAIN` and `CONFLUENCE_PATH`.
|
|
153
155
|
|
|
156
|
+
If you can't find your `CLOUD_ID` but assign both `CONFLUENCE_DOMAIN` and `CONFLUENCE_PATH`, *md2conf* makes a best-effort attempt to determine `CONFLUENCE_API_URL`.
|
|
157
|
+
|
|
154
158
|
### Permissions
|
|
155
159
|
|
|
156
160
|
The tool requires appropriate permissions in Confluence in order to invoke endpoints.
|
|
157
161
|
|
|
158
|
-
|
|
162
|
+
We recommend the following scopes for scoped API tokens:
|
|
159
163
|
|
|
164
|
+
* `read:attachment:confluence`
|
|
165
|
+
* `read:content:confluence`
|
|
166
|
+
* `read:content-details:confluence`
|
|
167
|
+
* `read:label:confluence`
|
|
160
168
|
* `read:page:confluence`
|
|
161
|
-
* `write:page:confluence`
|
|
162
169
|
* `read:space:confluence`
|
|
163
|
-
* `write:space:confluence`
|
|
164
|
-
* `read:attachment:confluence`
|
|
165
170
|
* `write:attachment:confluence`
|
|
166
|
-
* `
|
|
171
|
+
* `write:content:confluence`
|
|
167
172
|
* `write:label:confluence`
|
|
173
|
+
* `write:page:confluence`
|
|
174
|
+
* `delete:attachment:confluence`
|
|
175
|
+
* `delete:content:confluence`
|
|
176
|
+
* `delete:page:confluence`
|
|
168
177
|
|
|
169
178
|
If a Confluence username is set, the tool uses HTTP *Basic* authentication to pass the username and the API key to Confluence REST API endpoints. If no username is provided, the tool authenticates with HTTP *Bearer*, and passes the API key as the bearer token.
|
|
170
179
|
|
|
@@ -331,6 +340,21 @@ The following table shows standard highlight colors (CSS `background-color`) tha
|
|
|
331
340
|
|
|
332
341
|
If your Markdown lists or tables don't appear in Confluence as expected, verify that the list or table is delimited by a blank line both before and after, as per strict Markdown syntax. While some previewers accept a more lenient syntax (e.g. an itemized list immediately following a paragraph), *md2conf* uses [Python-Markdown](https://python-markdown.github.io/) internally to convert Markdown into XHTML, which expects the Markdown document to adhere to the stricter syntax.
|
|
333
342
|
|
|
343
|
+
Likewise, if you have a nested list, make sure that nested items are indented by exactly ***four*** spaces as compared to the parent node:
|
|
344
|
+
|
|
345
|
+
```markdown
|
|
346
|
+
1. List item 1
|
|
347
|
+
* Nested item 1
|
|
348
|
+
1. Item 1
|
|
349
|
+
2. Item 2
|
|
350
|
+
* Nested item 2
|
|
351
|
+
- Item 3
|
|
352
|
+
- Item 4
|
|
353
|
+
2. List item 2
|
|
354
|
+
1. Nested item 3
|
|
355
|
+
2. Nested item 4
|
|
356
|
+
```
|
|
357
|
+
|
|
334
358
|
### Publishing images
|
|
335
359
|
|
|
336
360
|
Local images referenced in a Markdown file are automatically published to Confluence as attachments to the page.
|
|
@@ -348,7 +372,7 @@ Inline formulas can be enclosed with `$` signs, or delimited with `\(` and `\)`,
|
|
|
348
372
|
|
|
349
373
|
Block formulas can be enclosed with `$$`, or wrapped in code blocks specifying the language `math`:
|
|
350
374
|
|
|
351
|
-
```
|
|
375
|
+
```markdown
|
|
352
376
|
$$\int _{a}^{b}f(x)dx=F(b)-F(a)$$
|
|
353
377
|
```
|
|
354
378
|
|
|
@@ -385,7 +409,7 @@ Displaying math formulas in Confluence requires the extension [LaTeX Math for Co
|
|
|
385
409
|
|
|
386
410
|
Use the pseudo-language `csf` in a Markdown code block to pass content directly to Confluence. The content must be a single XML node that conforms to Confluence Storage Format (typically an `ac:structured-macro`) but is otherwise not validated. The following example shows how to create a panel similar to an *info panel* but with custom background color and emoji. Notice that `ac:rich-text-body` uses XHTML, not Markdown.
|
|
387
411
|
|
|
388
|
-
````
|
|
412
|
+
````markdown
|
|
389
413
|
```csf
|
|
390
414
|
<ac:structured-macro ac:name="panel" ac:schema-version="1">
|
|
391
415
|
<ac:parameter ac:name="panelIcon">:slight_smile:</ac:parameter>
|
|
@@ -496,7 +520,7 @@ If *md2conf* encounters a Markdown link that points to a file in the directory h
|
|
|
496
520
|
|
|
497
521
|
*md2conf* implicitly defines some URLs, as if you included the following at the start of the Markdown document for each URL:
|
|
498
522
|
|
|
499
|
-
```
|
|
523
|
+
```markdown
|
|
500
524
|
[CUSTOM-URL]: https://example.com/path/to/resource
|
|
501
525
|
```
|
|
502
526
|
|
|
@@ -531,7 +555,7 @@ options:
|
|
|
531
555
|
--api-url API_URL Confluence API URL. Required for scoped tokens. Refer to documentation how to obtain one.
|
|
532
556
|
-u, --username USERNAME
|
|
533
557
|
Confluence user name.
|
|
534
|
-
-a, --
|
|
558
|
+
-a, --api-key API_KEY
|
|
535
559
|
Confluence API key. Refer to documentation how to obtain one.
|
|
536
560
|
-s, --space SPACE Confluence space key for pages to be published. If omitted, will default to user space.
|
|
537
561
|
-l, --loglevel {debug,info,warning,error,critical}
|
|
@@ -550,8 +574,6 @@ options:
|
|
|
550
574
|
--no-render-latex Inline LaTeX formulas in Confluence page. (Marketplace app required to display.)
|
|
551
575
|
--diagram-output-format {png,svg}
|
|
552
576
|
Format for rendering Mermaid and draw.io diagrams (default: 'png').
|
|
553
|
-
--render-mermaid-format FORMAT
|
|
554
|
-
Format for rendering Mermaid diagrams (default: 'png').
|
|
555
577
|
--heading-anchors Place an anchor at each section heading with GitHub-style same-page identifiers.
|
|
556
578
|
--no-heading-anchors Don't place an anchor at each section heading.
|
|
557
579
|
--ignore-invalid-url Emit a warning but otherwise ignore relative URLs that point to ill-specified locations.
|
|
@@ -99,7 +99,7 @@ export CONFLUENCE_SPACE_KEY='SPACE'
|
|
|
99
99
|
|
|
100
100
|
On Windows, these can be set via system properties.
|
|
101
101
|
|
|
102
|
-
If you use Atlassian scoped API tokens, you
|
|
102
|
+
If you use Atlassian scoped API tokens, you may want to set API URL directly, substituting `CLOUD_ID` with your own Cloud ID:
|
|
103
103
|
|
|
104
104
|
```sh
|
|
105
105
|
export CONFLUENCE_API_URL='https://api.atlassian.com/ex/confluence/CLOUD_ID/'
|
|
@@ -107,20 +107,27 @@ export CONFLUENCE_API_URL='https://api.atlassian.com/ex/confluence/CLOUD_ID/'
|
|
|
107
107
|
|
|
108
108
|
In this case, *md2conf* can automatically determine `CONFLUENCE_DOMAIN` and `CONFLUENCE_PATH`.
|
|
109
109
|
|
|
110
|
+
If you can't find your `CLOUD_ID` but assign both `CONFLUENCE_DOMAIN` and `CONFLUENCE_PATH`, *md2conf* makes a best-effort attempt to determine `CONFLUENCE_API_URL`.
|
|
111
|
+
|
|
110
112
|
### Permissions
|
|
111
113
|
|
|
112
114
|
The tool requires appropriate permissions in Confluence in order to invoke endpoints.
|
|
113
115
|
|
|
114
|
-
|
|
116
|
+
We recommend the following scopes for scoped API tokens:
|
|
115
117
|
|
|
118
|
+
* `read:attachment:confluence`
|
|
119
|
+
* `read:content:confluence`
|
|
120
|
+
* `read:content-details:confluence`
|
|
121
|
+
* `read:label:confluence`
|
|
116
122
|
* `read:page:confluence`
|
|
117
|
-
* `write:page:confluence`
|
|
118
123
|
* `read:space:confluence`
|
|
119
|
-
* `write:space:confluence`
|
|
120
|
-
* `read:attachment:confluence`
|
|
121
124
|
* `write:attachment:confluence`
|
|
122
|
-
* `
|
|
125
|
+
* `write:content:confluence`
|
|
123
126
|
* `write:label:confluence`
|
|
127
|
+
* `write:page:confluence`
|
|
128
|
+
* `delete:attachment:confluence`
|
|
129
|
+
* `delete:content:confluence`
|
|
130
|
+
* `delete:page:confluence`
|
|
124
131
|
|
|
125
132
|
If a Confluence username is set, the tool uses HTTP *Basic* authentication to pass the username and the API key to Confluence REST API endpoints. If no username is provided, the tool authenticates with HTTP *Bearer*, and passes the API key as the bearer token.
|
|
126
133
|
|
|
@@ -287,6 +294,21 @@ The following table shows standard highlight colors (CSS `background-color`) tha
|
|
|
287
294
|
|
|
288
295
|
If your Markdown lists or tables don't appear in Confluence as expected, verify that the list or table is delimited by a blank line both before and after, as per strict Markdown syntax. While some previewers accept a more lenient syntax (e.g. an itemized list immediately following a paragraph), *md2conf* uses [Python-Markdown](https://python-markdown.github.io/) internally to convert Markdown into XHTML, which expects the Markdown document to adhere to the stricter syntax.
|
|
289
296
|
|
|
297
|
+
Likewise, if you have a nested list, make sure that nested items are indented by exactly ***four*** spaces as compared to the parent node:
|
|
298
|
+
|
|
299
|
+
```markdown
|
|
300
|
+
1. List item 1
|
|
301
|
+
* Nested item 1
|
|
302
|
+
1. Item 1
|
|
303
|
+
2. Item 2
|
|
304
|
+
* Nested item 2
|
|
305
|
+
- Item 3
|
|
306
|
+
- Item 4
|
|
307
|
+
2. List item 2
|
|
308
|
+
1. Nested item 3
|
|
309
|
+
2. Nested item 4
|
|
310
|
+
```
|
|
311
|
+
|
|
290
312
|
### Publishing images
|
|
291
313
|
|
|
292
314
|
Local images referenced in a Markdown file are automatically published to Confluence as attachments to the page.
|
|
@@ -304,7 +326,7 @@ Inline formulas can be enclosed with `$` signs, or delimited with `\(` and `\)`,
|
|
|
304
326
|
|
|
305
327
|
Block formulas can be enclosed with `$$`, or wrapped in code blocks specifying the language `math`:
|
|
306
328
|
|
|
307
|
-
```
|
|
329
|
+
```markdown
|
|
308
330
|
$$\int _{a}^{b}f(x)dx=F(b)-F(a)$$
|
|
309
331
|
```
|
|
310
332
|
|
|
@@ -341,7 +363,7 @@ Displaying math formulas in Confluence requires the extension [LaTeX Math for Co
|
|
|
341
363
|
|
|
342
364
|
Use the pseudo-language `csf` in a Markdown code block to pass content directly to Confluence. The content must be a single XML node that conforms to Confluence Storage Format (typically an `ac:structured-macro`) but is otherwise not validated. The following example shows how to create a panel similar to an *info panel* but with custom background color and emoji. Notice that `ac:rich-text-body` uses XHTML, not Markdown.
|
|
343
365
|
|
|
344
|
-
````
|
|
366
|
+
````markdown
|
|
345
367
|
```csf
|
|
346
368
|
<ac:structured-macro ac:name="panel" ac:schema-version="1">
|
|
347
369
|
<ac:parameter ac:name="panelIcon">:slight_smile:</ac:parameter>
|
|
@@ -452,7 +474,7 @@ If *md2conf* encounters a Markdown link that points to a file in the directory h
|
|
|
452
474
|
|
|
453
475
|
*md2conf* implicitly defines some URLs, as if you included the following at the start of the Markdown document for each URL:
|
|
454
476
|
|
|
455
|
-
```
|
|
477
|
+
```markdown
|
|
456
478
|
[CUSTOM-URL]: https://example.com/path/to/resource
|
|
457
479
|
```
|
|
458
480
|
|
|
@@ -487,7 +509,7 @@ options:
|
|
|
487
509
|
--api-url API_URL Confluence API URL. Required for scoped tokens. Refer to documentation how to obtain one.
|
|
488
510
|
-u, --username USERNAME
|
|
489
511
|
Confluence user name.
|
|
490
|
-
-a, --
|
|
512
|
+
-a, --api-key API_KEY
|
|
491
513
|
Confluence API key. Refer to documentation how to obtain one.
|
|
492
514
|
-s, --space SPACE Confluence space key for pages to be published. If omitted, will default to user space.
|
|
493
515
|
-l, --loglevel {debug,info,warning,error,critical}
|
|
@@ -506,8 +528,6 @@ options:
|
|
|
506
528
|
--no-render-latex Inline LaTeX formulas in Confluence page. (Marketplace app required to display.)
|
|
507
529
|
--diagram-output-format {png,svg}
|
|
508
530
|
Format for rendering Mermaid and draw.io diagrams (default: 'png').
|
|
509
|
-
--render-mermaid-format FORMAT
|
|
510
|
-
Format for rendering Mermaid diagrams (default: 'png').
|
|
511
531
|
--heading-anchors Place an anchor at each section heading with GitHub-style same-page identifiers.
|
|
512
532
|
--no-heading-anchors Don't place an anchor at each section heading.
|
|
513
533
|
--ignore-invalid-url Emit a warning but otherwise ignore relative URLs that point to ill-specified locations.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: markdown-to-confluence
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.6
|
|
4
4
|
Summary: Publish Markdown files to Confluence wiki
|
|
5
5
|
Author-email: Levente Hunyadi <hunyadi@gmail.com>
|
|
6
6
|
Maintainer-email: Levente Hunyadi <hunyadi@gmail.com>
|
|
@@ -23,12 +23,14 @@ Classifier: Typing :: Typed
|
|
|
23
23
|
Requires-Python: >=3.9
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
License-File: LICENSE
|
|
26
|
+
Requires-Dist: certifi>=2025.8.3; python_version < "3.10"
|
|
26
27
|
Requires-Dist: json_strong_typing>=0.4
|
|
27
28
|
Requires-Dist: lxml>=6.0
|
|
28
29
|
Requires-Dist: markdown>=3.8
|
|
29
30
|
Requires-Dist: pymdown-extensions>=10.16
|
|
30
31
|
Requires-Dist: PyYAML>=6.0
|
|
31
32
|
Requires-Dist: requests>=2.32
|
|
33
|
+
Requires-Dist: truststore>=0.10; python_version >= "3.10"
|
|
32
34
|
Requires-Dist: typing-extensions>=4.14; python_version < "3.12"
|
|
33
35
|
Provides-Extra: dev
|
|
34
36
|
Requires-Dist: markdown_doc>=0.1.4; python_version >= "3.10" and extra == "dev"
|
|
@@ -143,7 +145,7 @@ export CONFLUENCE_SPACE_KEY='SPACE'
|
|
|
143
145
|
|
|
144
146
|
On Windows, these can be set via system properties.
|
|
145
147
|
|
|
146
|
-
If you use Atlassian scoped API tokens, you
|
|
148
|
+
If you use Atlassian scoped API tokens, you may want to set API URL directly, substituting `CLOUD_ID` with your own Cloud ID:
|
|
147
149
|
|
|
148
150
|
```sh
|
|
149
151
|
export CONFLUENCE_API_URL='https://api.atlassian.com/ex/confluence/CLOUD_ID/'
|
|
@@ -151,20 +153,27 @@ export CONFLUENCE_API_URL='https://api.atlassian.com/ex/confluence/CLOUD_ID/'
|
|
|
151
153
|
|
|
152
154
|
In this case, *md2conf* can automatically determine `CONFLUENCE_DOMAIN` and `CONFLUENCE_PATH`.
|
|
153
155
|
|
|
156
|
+
If you can't find your `CLOUD_ID` but assign both `CONFLUENCE_DOMAIN` and `CONFLUENCE_PATH`, *md2conf* makes a best-effort attempt to determine `CONFLUENCE_API_URL`.
|
|
157
|
+
|
|
154
158
|
### Permissions
|
|
155
159
|
|
|
156
160
|
The tool requires appropriate permissions in Confluence in order to invoke endpoints.
|
|
157
161
|
|
|
158
|
-
|
|
162
|
+
We recommend the following scopes for scoped API tokens:
|
|
159
163
|
|
|
164
|
+
* `read:attachment:confluence`
|
|
165
|
+
* `read:content:confluence`
|
|
166
|
+
* `read:content-details:confluence`
|
|
167
|
+
* `read:label:confluence`
|
|
160
168
|
* `read:page:confluence`
|
|
161
|
-
* `write:page:confluence`
|
|
162
169
|
* `read:space:confluence`
|
|
163
|
-
* `write:space:confluence`
|
|
164
|
-
* `read:attachment:confluence`
|
|
165
170
|
* `write:attachment:confluence`
|
|
166
|
-
* `
|
|
171
|
+
* `write:content:confluence`
|
|
167
172
|
* `write:label:confluence`
|
|
173
|
+
* `write:page:confluence`
|
|
174
|
+
* `delete:attachment:confluence`
|
|
175
|
+
* `delete:content:confluence`
|
|
176
|
+
* `delete:page:confluence`
|
|
168
177
|
|
|
169
178
|
If a Confluence username is set, the tool uses HTTP *Basic* authentication to pass the username and the API key to Confluence REST API endpoints. If no username is provided, the tool authenticates with HTTP *Bearer*, and passes the API key as the bearer token.
|
|
170
179
|
|
|
@@ -331,6 +340,21 @@ The following table shows standard highlight colors (CSS `background-color`) tha
|
|
|
331
340
|
|
|
332
341
|
If your Markdown lists or tables don't appear in Confluence as expected, verify that the list or table is delimited by a blank line both before and after, as per strict Markdown syntax. While some previewers accept a more lenient syntax (e.g. an itemized list immediately following a paragraph), *md2conf* uses [Python-Markdown](https://python-markdown.github.io/) internally to convert Markdown into XHTML, which expects the Markdown document to adhere to the stricter syntax.
|
|
333
342
|
|
|
343
|
+
Likewise, if you have a nested list, make sure that nested items are indented by exactly ***four*** spaces as compared to the parent node:
|
|
344
|
+
|
|
345
|
+
```markdown
|
|
346
|
+
1. List item 1
|
|
347
|
+
* Nested item 1
|
|
348
|
+
1. Item 1
|
|
349
|
+
2. Item 2
|
|
350
|
+
* Nested item 2
|
|
351
|
+
- Item 3
|
|
352
|
+
- Item 4
|
|
353
|
+
2. List item 2
|
|
354
|
+
1. Nested item 3
|
|
355
|
+
2. Nested item 4
|
|
356
|
+
```
|
|
357
|
+
|
|
334
358
|
### Publishing images
|
|
335
359
|
|
|
336
360
|
Local images referenced in a Markdown file are automatically published to Confluence as attachments to the page.
|
|
@@ -348,7 +372,7 @@ Inline formulas can be enclosed with `$` signs, or delimited with `\(` and `\)`,
|
|
|
348
372
|
|
|
349
373
|
Block formulas can be enclosed with `$$`, or wrapped in code blocks specifying the language `math`:
|
|
350
374
|
|
|
351
|
-
```
|
|
375
|
+
```markdown
|
|
352
376
|
$$\int _{a}^{b}f(x)dx=F(b)-F(a)$$
|
|
353
377
|
```
|
|
354
378
|
|
|
@@ -385,7 +409,7 @@ Displaying math formulas in Confluence requires the extension [LaTeX Math for Co
|
|
|
385
409
|
|
|
386
410
|
Use the pseudo-language `csf` in a Markdown code block to pass content directly to Confluence. The content must be a single XML node that conforms to Confluence Storage Format (typically an `ac:structured-macro`) but is otherwise not validated. The following example shows how to create a panel similar to an *info panel* but with custom background color and emoji. Notice that `ac:rich-text-body` uses XHTML, not Markdown.
|
|
387
411
|
|
|
388
|
-
````
|
|
412
|
+
````markdown
|
|
389
413
|
```csf
|
|
390
414
|
<ac:structured-macro ac:name="panel" ac:schema-version="1">
|
|
391
415
|
<ac:parameter ac:name="panelIcon">:slight_smile:</ac:parameter>
|
|
@@ -496,7 +520,7 @@ If *md2conf* encounters a Markdown link that points to a file in the directory h
|
|
|
496
520
|
|
|
497
521
|
*md2conf* implicitly defines some URLs, as if you included the following at the start of the Markdown document for each URL:
|
|
498
522
|
|
|
499
|
-
```
|
|
523
|
+
```markdown
|
|
500
524
|
[CUSTOM-URL]: https://example.com/path/to/resource
|
|
501
525
|
```
|
|
502
526
|
|
|
@@ -531,7 +555,7 @@ options:
|
|
|
531
555
|
--api-url API_URL Confluence API URL. Required for scoped tokens. Refer to documentation how to obtain one.
|
|
532
556
|
-u, --username USERNAME
|
|
533
557
|
Confluence user name.
|
|
534
|
-
-a, --
|
|
558
|
+
-a, --api-key API_KEY
|
|
535
559
|
Confluence API key. Refer to documentation how to obtain one.
|
|
536
560
|
-s, --space SPACE Confluence space key for pages to be published. If omitted, will default to user space.
|
|
537
561
|
-l, --loglevel {debug,info,warning,error,critical}
|
|
@@ -550,8 +574,6 @@ options:
|
|
|
550
574
|
--no-render-latex Inline LaTeX formulas in Confluence page. (Marketplace app required to display.)
|
|
551
575
|
--diagram-output-format {png,svg}
|
|
552
576
|
Format for rendering Mermaid and draw.io diagrams (default: 'png').
|
|
553
|
-
--render-mermaid-format FORMAT
|
|
554
|
-
Format for rendering Mermaid diagrams (default: 'png').
|
|
555
577
|
--heading-anchors Place an anchor at each section heading with GitHub-style same-page identifiers.
|
|
556
578
|
--no-heading-anchors Don't place an anchor at each section heading.
|
|
557
579
|
--ignore-invalid-url Emit a warning but otherwise ignore relative URLs that point to ill-specified locations.
|
|
@@ -13,13 +13,14 @@ markdown_to_confluence.egg-info/zip-safe
|
|
|
13
13
|
md2conf/__init__.py
|
|
14
14
|
md2conf/__main__.py
|
|
15
15
|
md2conf/api.py
|
|
16
|
-
md2conf/application.py
|
|
17
16
|
md2conf/collection.py
|
|
18
17
|
md2conf/converter.py
|
|
19
18
|
md2conf/csf.py
|
|
20
19
|
md2conf/domain.py
|
|
21
20
|
md2conf/drawio.py
|
|
21
|
+
md2conf/emoticon.py
|
|
22
22
|
md2conf/entities.dtd
|
|
23
|
+
md2conf/environment.py
|
|
23
24
|
md2conf/extra.py
|
|
24
25
|
md2conf/latex.py
|
|
25
26
|
md2conf/local.py
|
|
@@ -28,7 +29,7 @@ md2conf/matcher.py
|
|
|
28
29
|
md2conf/mermaid.py
|
|
29
30
|
md2conf/metadata.py
|
|
30
31
|
md2conf/processor.py
|
|
31
|
-
md2conf/
|
|
32
|
+
md2conf/publisher.py
|
|
32
33
|
md2conf/puppeteer-config.json
|
|
33
34
|
md2conf/py.typed
|
|
34
35
|
md2conf/scanner.py
|
|
@@ -5,9 +5,15 @@ pymdown-extensions>=10.16
|
|
|
5
5
|
PyYAML>=6.0
|
|
6
6
|
requests>=2.32
|
|
7
7
|
|
|
8
|
+
[:python_version < "3.10"]
|
|
9
|
+
certifi>=2025.8.3
|
|
10
|
+
|
|
8
11
|
[:python_version < "3.12"]
|
|
9
12
|
typing-extensions>=4.14
|
|
10
13
|
|
|
14
|
+
[:python_version >= "3.10"]
|
|
15
|
+
truststore>=0.10
|
|
16
|
+
|
|
11
17
|
[dev]
|
|
12
18
|
types-lxml>=2025.3.30
|
|
13
19
|
types-markdown>=3.8
|
|
@@ -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.4.
|
|
8
|
+
__version__ = "0.4.6"
|
|
9
9
|
__author__ = "Levente Hunyadi"
|
|
10
10
|
__copyright__ = "Copyright 2022-2025, Levente Hunyadi"
|
|
11
11
|
__license__ = "MIT"
|
|
@@ -14,14 +14,15 @@ import logging
|
|
|
14
14
|
import os.path
|
|
15
15
|
import sys
|
|
16
16
|
import typing
|
|
17
|
+
from io import StringIO
|
|
17
18
|
from pathlib import Path
|
|
18
19
|
from typing import Any, Iterable, Literal, Optional, Sequence, Union
|
|
19
20
|
|
|
20
21
|
from . import __version__
|
|
21
22
|
from .domain import ConfluenceDocumentOptions, ConfluencePageID
|
|
23
|
+
from .environment import ArgumentError, ConfluenceConnectionProperties, ConfluenceSiteProperties
|
|
22
24
|
from .extra import override
|
|
23
25
|
from .metadata import ConfluenceSiteMetadata
|
|
24
|
-
from .properties import ArgumentError, ConfluenceConnectionProperties, ConfluenceSiteProperties
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
class Arguments(argparse.Namespace):
|
|
@@ -68,30 +69,6 @@ class KwargsAppendAction(argparse.Action):
|
|
|
68
69
|
setattr(namespace, self.dest, d)
|
|
69
70
|
|
|
70
71
|
|
|
71
|
-
def unsupported(prefer: str) -> type[argparse.Action]:
|
|
72
|
-
class UnsupportedAction(argparse.Action):
|
|
73
|
-
"""Display an error for unsupported command-line options."""
|
|
74
|
-
|
|
75
|
-
@override
|
|
76
|
-
def __call__(
|
|
77
|
-
self,
|
|
78
|
-
parser: argparse.ArgumentParser,
|
|
79
|
-
namespace: argparse.Namespace,
|
|
80
|
-
values: Union[None, str, Sequence[Any]],
|
|
81
|
-
option_string: Optional[str] = None,
|
|
82
|
-
) -> None:
|
|
83
|
-
raise argparse.ArgumentError(
|
|
84
|
-
self,
|
|
85
|
-
f"this command-line option is no longer supported, use `--{prefer}`",
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
@override
|
|
89
|
-
def __repr__(self) -> str:
|
|
90
|
-
return f"{unsupported.__name__}({repr(prefer)})"
|
|
91
|
-
|
|
92
|
-
return UnsupportedAction
|
|
93
|
-
|
|
94
|
-
|
|
95
72
|
class PositionalOnlyHelpFormatter(argparse.HelpFormatter):
|
|
96
73
|
def _format_usage(
|
|
97
74
|
self,
|
|
@@ -112,7 +89,7 @@ class PositionalOnlyHelpFormatter(argparse.HelpFormatter):
|
|
|
112
89
|
return usage_str
|
|
113
90
|
|
|
114
91
|
|
|
115
|
-
def
|
|
92
|
+
def get_parser() -> argparse.ArgumentParser:
|
|
116
93
|
parser = argparse.ArgumentParser(formatter_class=PositionalOnlyHelpFormatter)
|
|
117
94
|
parser.prog = os.path.basename(os.path.dirname(__file__))
|
|
118
95
|
parser.add_argument("--version", action="version", version=__version__)
|
|
@@ -127,7 +104,6 @@ def main() -> None:
|
|
|
127
104
|
parser.add_argument("-u", "--username", help="Confluence user name.")
|
|
128
105
|
parser.add_argument(
|
|
129
106
|
"-a",
|
|
130
|
-
"--apikey",
|
|
131
107
|
"--api-key",
|
|
132
108
|
dest="api_key",
|
|
133
109
|
help="Confluence API key. Refer to documentation how to obtain one.",
|
|
@@ -228,12 +204,6 @@ def main() -> None:
|
|
|
228
204
|
default="png",
|
|
229
205
|
help="Format for rendering Mermaid and draw.io diagrams (default: 'png').",
|
|
230
206
|
)
|
|
231
|
-
parser.add_argument(
|
|
232
|
-
"--render-mermaid-format",
|
|
233
|
-
action=unsupported("diagram-output-format"),
|
|
234
|
-
metavar="FORMAT",
|
|
235
|
-
help="Format for rendering Mermaid diagrams (default: 'png').",
|
|
236
|
-
)
|
|
237
207
|
parser.add_argument(
|
|
238
208
|
"--heading-anchors",
|
|
239
209
|
action="store_true",
|
|
@@ -272,7 +242,18 @@ def main() -> None:
|
|
|
272
242
|
default=False,
|
|
273
243
|
help="Enable Confluence Web UI links. (Typically required for on-prem versions of Confluence.)",
|
|
274
244
|
)
|
|
245
|
+
return parser
|
|
246
|
+
|
|
275
247
|
|
|
248
|
+
def get_help() -> str:
|
|
249
|
+
parser = get_parser()
|
|
250
|
+
with StringIO() as buf:
|
|
251
|
+
parser.print_help(file=buf)
|
|
252
|
+
return buf.getvalue()
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def main() -> None:
|
|
256
|
+
parser = get_parser()
|
|
276
257
|
args = Arguments()
|
|
277
258
|
parser.parse_args(namespace=args)
|
|
278
259
|
|
|
@@ -316,7 +297,7 @@ def main() -> None:
|
|
|
316
297
|
from requests import HTTPError, JSONDecodeError
|
|
317
298
|
|
|
318
299
|
from .api import ConfluenceAPI
|
|
319
|
-
from .
|
|
300
|
+
from .publisher import Publisher
|
|
320
301
|
|
|
321
302
|
try:
|
|
322
303
|
properties = ConfluenceConnectionProperties(
|
|
@@ -332,7 +313,7 @@ def main() -> None:
|
|
|
332
313
|
parser.error(str(e))
|
|
333
314
|
try:
|
|
334
315
|
with ConfluenceAPI(properties) as api:
|
|
335
|
-
|
|
316
|
+
Publisher(
|
|
336
317
|
api,
|
|
337
318
|
options,
|
|
338
319
|
).process(args.mdpath)
|