markdown-to-confluence 0.3.5__tar.gz → 0.4.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 (36) hide show
  1. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/PKG-INFO +118 -7
  2. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/README.md +114 -5
  3. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/markdown_to_confluence.egg-info/PKG-INFO +118 -7
  4. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/markdown_to_confluence.egg-info/SOURCES.txt +2 -0
  5. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/markdown_to_confluence.egg-info/requires.txt +5 -1
  6. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/__init__.py +1 -1
  7. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/__main__.py +18 -7
  8. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/api.py +372 -186
  9. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/application.py +82 -70
  10. markdown_to_confluence-0.4.0/md2conf/collection.py +31 -0
  11. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/converter.py +17 -10
  12. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/emoji.py +28 -3
  13. markdown_to_confluence-0.4.0/md2conf/extra.py +14 -0
  14. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/local.py +30 -35
  15. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/metadata.py +0 -2
  16. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/processor.py +134 -38
  17. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/properties.py +24 -5
  18. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/scanner.py +53 -21
  19. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/setup.cfg +3 -1
  20. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/tests/test_conversion.py +12 -8
  21. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/tests/test_mermaid.py +3 -0
  22. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/tests/test_processor.py +6 -1
  23. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/tests/test_scanner.py +13 -1
  24. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/LICENSE +0 -0
  25. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/markdown_to_confluence.egg-info/dependency_links.txt +0 -0
  26. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/markdown_to_confluence.egg-info/entry_points.txt +0 -0
  27. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/markdown_to_confluence.egg-info/top_level.txt +0 -0
  28. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/markdown_to_confluence.egg-info/zip-safe +0 -0
  29. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/entities.dtd +0 -0
  30. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/matcher.py +0 -0
  31. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/mermaid.py +0 -0
  32. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/puppeteer-config.json +0 -0
  33. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/md2conf/py.typed +0 -0
  34. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/pyproject.toml +0 -0
  35. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/setup.py +0 -0
  36. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.0}/tests/test_matcher.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: markdown-to-confluence
3
- Version: 0.3.5
3
+ Version: 0.4.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,15 +21,17 @@ Classifier: Typing :: Typed
21
21
  Requires-Python: >=3.9
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
+ Requires-Dist: json_strong_typing>=0.3.9
24
25
  Requires-Dist: lxml>=5.4
25
26
  Requires-Dist: types-lxml>=2025.3.30
26
27
  Requires-Dist: markdown>=3.8
27
28
  Requires-Dist: types-markdown>=3.8
28
- Requires-Dist: pymdown-extensions>=10.15
29
+ Requires-Dist: pymdown-extensions>=10.16
29
30
  Requires-Dist: PyYAML>=6.0
30
31
  Requires-Dist: types-PyYAML>=6.0
31
32
  Requires-Dist: requests>=2.32
32
33
  Requires-Dist: types-requests>=2.32
34
+ Requires-Dist: typing_extensions>=4.14; python_version < "3.12"
33
35
  Dynamic: license-file
34
36
 
35
37
  # Publish Markdown files to Confluence wiki
@@ -49,7 +51,10 @@ This Python package
49
51
  * Sections and subsections
50
52
  * Text with **bold**, *italic*, `monospace`, <ins>underline</ins> and ~~strikethrough~~
51
53
  * Link to [sections on the same page](#getting-started) or [external locations](http://example.com/)
54
+ * Subscript and superscript (with HTML tags `<sub>` and `<sup>`)
55
+ * Emoji
52
56
  * Ordered and unordered lists
57
+ * Block quotes
53
58
  * Code blocks (e.g. Python, JSON, XML)
54
59
  * Images (uploaded as Confluence page attachments or hosted externally)
55
60
  * Tables
@@ -95,7 +100,7 @@ In order to get started, you will need
95
100
 
96
101
  Confluence organization domain, base path, username, API token and space key can be specified at runtime or set as Confluence environment variables (e.g. add to your `~/.profile` on Linux, or `~/.bash_profile` or `~/.zshenv` on MacOS):
97
102
 
98
- ```bash
103
+ ```sh
99
104
  export CONFLUENCE_DOMAIN='example.atlassian.net'
100
105
  export CONFLUENCE_PATH='/wiki/'
101
106
  export CONFLUENCE_USER_NAME='levente.hunyadi@instructure.com'
@@ -105,10 +110,29 @@ export CONFLUENCE_SPACE_KEY='SPACE'
105
110
 
106
111
  On Windows, these can be set via system properties.
107
112
 
113
+ If you use Atlassian scoped API tokens, you should set API URL, substituting `CLOUD_ID` with your own Cloud ID:
114
+
115
+ ```sh
116
+ export CONFLUENCE_API_URL='https://api.atlassian.com/ex/confluence/CLOUD_ID/'
117
+ ```
118
+
119
+ In this case, *md2conf* can automatically determine `CONFLUENCE_DOMAIN` and `CONFLUENCE_PATH`.
120
+
108
121
  ### Permissions
109
122
 
110
123
  The tool requires appropriate permissions in Confluence in order to invoke endpoints.
111
124
 
125
+ Required scopes for scoped API tokens are as follows:
126
+
127
+ * `read:page:confluence`
128
+ * `write:page:confluence`
129
+ * `read:space:confluence`
130
+ * `write:space:confluence`
131
+ * `read:attachment:confluence`
132
+ * `write:attachment:confluence`
133
+ * `read:label:confluence`
134
+ * `write:label:confluence`
135
+
112
136
  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.
113
137
 
114
138
  If you lack appropriate permissions, you will get an *Unauthorized* response from Confluence. The tool will emit a message that looks as follows:
@@ -198,6 +222,65 @@ root
198
222
  └── Mean vs. median
199
223
  ```
200
224
 
225
+ ### Emoji
226
+
227
+ The short name notation `:smile:` in a Markdown document is converted into the corresponding emoji 😄 when publishing to Confluence.
228
+
229
+ *md2conf* relies on the [Emoji extension](https://facelessuser.github.io/pymdown-extensions/extensions/emoji/) of [PyMdown Extensions](https://facelessuser.github.io/pymdown-extensions/) to parse the short name notation with colons, and generate Confluence Storage Format output such as
230
+
231
+ ```xml
232
+ <ac:emoticon ac:name="smile" ac:emoji-shortname=":smile:" ac:emoji-id="1f604" ac:emoji-fallback="&#128516;"/>
233
+ ```
234
+
235
+ ### Colors
236
+
237
+ Confluence allows setting text color and highlight color. Even though Markdown doesn't directly support colors, it is possible to set text and highlight color via the HTML element `<span>` and the CSS attributes `color` and `background-color`, respectively:
238
+
239
+ Text in <span style="color: rgb(255,86,48);">red</span>, <span style="color: rgb(54,179,126);">green</span> and <span style="color: rgb(76,154,255);">blue</span>:
240
+
241
+ ```markdown
242
+ Text in <span style="color: rgb(255,86,48);">red</span>, <span style="color: rgb(54,179,126);">green</span> and <span style="color: rgb(76,154,255);">blue</span>.
243
+ ```
244
+
245
+ Highlight in <span style="background-color: rgb(198,237,251);">teal</span>, <span style="background-color: rgb(211,241,167);">lime</span> and <span style="background-color: rgb(254,222,200);">yellow</span>:
246
+
247
+ ```markdown
248
+ Highlight in <span style="background-color: rgb(198,237,251);">teal</span>, <span style="background-color: rgb(211,241,167);">lime</span> and <span style="background-color: rgb(254,222,200);">yellow</span>.
249
+ ```
250
+
251
+ The following table shows standard text colors (CSS `color`) that are available via Confluence UI:
252
+
253
+ | Color name | CSS attribute value |
254
+ | ------------- | ------------------- |
255
+ | bold blue | rgb(7,71,166) |
256
+ | blue | rgb(76,154,255) |
257
+ | subtle blue | rgb(179,212,255) |
258
+ | bold teal | rgb(0,141,166) |
259
+ | teal | rgb(0,184,217) |
260
+ | subtle teal | rgb(179,245,255) |
261
+ | bold green | rgb(0,102,68) |
262
+ | green | rgb(54,179,126) |
263
+ | subtle green | rgb(171,245,209) |
264
+ | bold orange | rgb(255,153,31) |
265
+ | yellow | rgb(255,196,0) |
266
+ | subtle yellow | rgb(255,240,179) |
267
+ | bold red | rgb(191,38,0) |
268
+ | red | rgb(255,86,48) |
269
+ | subtle red | rgb(255,189,173) |
270
+ | bold purple | rgb(64,50,148) |
271
+ | purple | rgb(101,84,192) |
272
+ | subtle purple | rgb(234,230,255) |
273
+
274
+ The following table shows standard highlight colors (CSS `background-color`) that are available via Confluence UI:
275
+
276
+ | Color name | CSS attribute value |
277
+ | ------------- | ------------------- |
278
+ | teal | rgb(198,237,251) |
279
+ | lime | rgb(211,241,167) |
280
+ | yellow | rgb(254,222,200) |
281
+ | magenta | rgb(253,208,236) |
282
+ | purple | rgb(223,216,253) |
283
+
201
284
  ### Lists and tables
202
285
 
203
286
  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.
@@ -222,12 +305,27 @@ Relative paths to items in a nested directory are not supported. You must put `.
222
305
 
223
306
  *md2conf* makes a best-effort attempt at setting the Confluence wiki page title when it publishes a Markdown document the first time. The following are probed in this order:
224
307
 
225
- 1. The `title` attribute set in the [front-matter](https://daily-dev-tips.com/posts/what-exactly-is-frontmatter/). Front-matter is a block delimited by `---` at the beginning of a Markdown document. Currently, only YAML syntax is supported.
308
+ 1. The `title` attribute set in the [front-matter](https://daily-dev-tips.com/posts/what-exactly-is-frontmatter/). Front-matter is a block delimited by `---` at the beginning of a Markdown document. Both JSON and YAML syntax are supported.
226
309
  2. The text of the topmost unique Markdown heading (`#`). For example, if a document has a single first-level heading (e.g. `# My document`), its text is used. However, if there are multiple first-level headings, this step is skipped.
227
310
  3. The file name (without the extension `.md`).
228
311
 
229
312
  If a matching Confluence page already exists for a Markdown file, the page title in Confluence is left unchanged.
230
313
 
314
+ ### Labels
315
+
316
+ If a Markdown document has the front-matter attribute `tags`, *md2conf* assigns the specified tags to the Confluence page as labels.
317
+
318
+ ```yaml
319
+ ---
320
+ title: "Example document"
321
+ tags: ["markdown", "md", "wiki"]
322
+ ---
323
+ ```
324
+
325
+ Any previously assigned labels are discarded. As per Confluence terminology, new labels have the `prefix` of `global`.
326
+
327
+ If a document has no `tags` attribute, existing Confluence labels are left intact.
328
+
231
329
  ### Converting diagrams
232
330
 
233
331
  You can include [Mermaid diagrams](https://mermaid.js.org/) in your Markdown documents to create visual representations of systems, processes, and relationships. When a Markdown document contains a code block with the language specifier `mermaid`, *md2conf* offers two options to publish the diagram:
@@ -235,6 +333,18 @@ You can include [Mermaid diagrams](https://mermaid.js.org/) in your Markdown doc
235
333
  1. Pre-render into an image. The code block is interpreted by and converted into a PNG or SVG image with the Mermaid diagram utility [mermaid-cli](https://github.com/mermaid-js/mermaid-cli). The generated image is then uploaded to Confluence as an attachment to the page. This is the approach we use and support.
236
334
  2. Render on demand. The code block is transformed into a [diagram macro](https://atlasauthority.atlassian.net/wiki/spaces/MARKDOWNCLOUD/pages/2946826241/Diagram+Macro), which is processed by Confluence. You need a [Confluence plugin](https://marketplace.atlassian.com/apps/1211438/markdown-html-plantuml-latex-diagrams-open-api-mermaid) to turn macro definitions into images when a Confluence page is visited. This is a contributed feature. As authors of *md2conf*, we don't endorse or support any particular Confluence plugin.
237
335
 
336
+ If you are running into issues with the pre-rendering approach (e.g. misaligned labels in the generated image), verify if `mermaid-cli` can process the Mermaid source:
337
+
338
+ ```sh
339
+ mmdc -i sample.mmd -o sample.png -b transparent --scale 2
340
+ ```
341
+
342
+ Ensure that `mermaid-cli` is set up, refer to *Installation* for instructions.
343
+
344
+ ### Local output
345
+
346
+ *md2conf* supports local output, in which the tool doesn't communicate with the Confluence REST API. Instead, it reads a single Markdown file or a directory of Markdown files, and writes Confluence Storage Format (`*.csf`) output for each document. (Confluence Storage Format is a derivative of XHTML with Confluence-specific tags for complex elements such as images with captions, code blocks, info panels, collapsed sections, etc.) You can push the generated output to Confluence by invoking the API (e.g. with `curl`).
347
+
238
348
  ### Running the tool
239
349
 
240
350
  You execute the command-line tool `md2conf` to synchronize the Markdown file with Confluence:
@@ -247,8 +357,8 @@ Use the `--help` switch to get a full list of supported command-line options:
247
357
 
248
358
  ```console
249
359
  $ python3 -m md2conf --help
250
- usage: md2conf [-h] [--version] [-d DOMAIN] [-p PATH] [-u USERNAME] [-a APIKEY] [-s SPACE] [-l {debug,info,warning,error,critical}] [-r ROOT_PAGE] [--keep-hierarchy] [--generated-by GENERATED_BY] [--no-generated-by]
251
- [--render-mermaid] [--no-render-mermaid] [--render-mermaid-format {png,svg}] [--heading-anchors] [--ignore-invalid-url] [--local] [--headers [KEY=VALUE ...]] [--webui-links]
360
+ usage: md2conf [-h] [--version] [-d DOMAIN] [-p PATH] [--api-url API_URL] [-u USERNAME] [-a API_KEY] [-s SPACE] [-l {debug,info,warning,error,critical}] [-r ROOT_PAGE] [--keep-hierarchy] [--generated-by GENERATED_BY]
361
+ [--no-generated-by] [--render-mermaid] [--no-render-mermaid] [--render-mermaid-format {png,svg}] [--heading-anchors] [--ignore-invalid-url] [--local] [--headers [KEY=VALUE ...]] [--webui-links]
252
362
  mdpath
253
363
 
254
364
  positional arguments:
@@ -260,9 +370,10 @@ options:
260
370
  -d DOMAIN, --domain DOMAIN
261
371
  Confluence organization domain.
262
372
  -p PATH, --path PATH Base path for Confluence (default: '/wiki/').
373
+ --api-url API_URL Confluence API URL. Required for scoped tokens. Refer to documentation how to obtain one.
263
374
  -u USERNAME, --username USERNAME
264
375
  Confluence user name.
265
- -a APIKEY, --apikey APIKEY
376
+ -a API_KEY, --apikey API_KEY, --api-key API_KEY
266
377
  Confluence API key. Refer to documentation how to obtain one.
267
378
  -s SPACE, --space SPACE
268
379
  Confluence space key for pages to be published. If omitted, will default to user space.
@@ -15,7 +15,10 @@ This Python package
15
15
  * Sections and subsections
16
16
  * Text with **bold**, *italic*, `monospace`, <ins>underline</ins> and ~~strikethrough~~
17
17
  * Link to [sections on the same page](#getting-started) or [external locations](http://example.com/)
18
+ * Subscript and superscript (with HTML tags `<sub>` and `<sup>`)
19
+ * Emoji
18
20
  * Ordered and unordered lists
21
+ * Block quotes
19
22
  * Code blocks (e.g. Python, JSON, XML)
20
23
  * Images (uploaded as Confluence page attachments or hosted externally)
21
24
  * Tables
@@ -61,7 +64,7 @@ In order to get started, you will need
61
64
 
62
65
  Confluence organization domain, base path, username, API token and space key can be specified at runtime or set as Confluence environment variables (e.g. add to your `~/.profile` on Linux, or `~/.bash_profile` or `~/.zshenv` on MacOS):
63
66
 
64
- ```bash
67
+ ```sh
65
68
  export CONFLUENCE_DOMAIN='example.atlassian.net'
66
69
  export CONFLUENCE_PATH='/wiki/'
67
70
  export CONFLUENCE_USER_NAME='levente.hunyadi@instructure.com'
@@ -71,10 +74,29 @@ export CONFLUENCE_SPACE_KEY='SPACE'
71
74
 
72
75
  On Windows, these can be set via system properties.
73
76
 
77
+ If you use Atlassian scoped API tokens, you should set API URL, substituting `CLOUD_ID` with your own Cloud ID:
78
+
79
+ ```sh
80
+ export CONFLUENCE_API_URL='https://api.atlassian.com/ex/confluence/CLOUD_ID/'
81
+ ```
82
+
83
+ In this case, *md2conf* can automatically determine `CONFLUENCE_DOMAIN` and `CONFLUENCE_PATH`.
84
+
74
85
  ### Permissions
75
86
 
76
87
  The tool requires appropriate permissions in Confluence in order to invoke endpoints.
77
88
 
89
+ Required scopes for scoped API tokens are as follows:
90
+
91
+ * `read:page:confluence`
92
+ * `write:page:confluence`
93
+ * `read:space:confluence`
94
+ * `write:space:confluence`
95
+ * `read:attachment:confluence`
96
+ * `write:attachment:confluence`
97
+ * `read:label:confluence`
98
+ * `write:label:confluence`
99
+
78
100
  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.
79
101
 
80
102
  If you lack appropriate permissions, you will get an *Unauthorized* response from Confluence. The tool will emit a message that looks as follows:
@@ -164,6 +186,65 @@ root
164
186
  └── Mean vs. median
165
187
  ```
166
188
 
189
+ ### Emoji
190
+
191
+ The short name notation `:smile:` in a Markdown document is converted into the corresponding emoji 😄 when publishing to Confluence.
192
+
193
+ *md2conf* relies on the [Emoji extension](https://facelessuser.github.io/pymdown-extensions/extensions/emoji/) of [PyMdown Extensions](https://facelessuser.github.io/pymdown-extensions/) to parse the short name notation with colons, and generate Confluence Storage Format output such as
194
+
195
+ ```xml
196
+ <ac:emoticon ac:name="smile" ac:emoji-shortname=":smile:" ac:emoji-id="1f604" ac:emoji-fallback="&#128516;"/>
197
+ ```
198
+
199
+ ### Colors
200
+
201
+ Confluence allows setting text color and highlight color. Even though Markdown doesn't directly support colors, it is possible to set text and highlight color via the HTML element `<span>` and the CSS attributes `color` and `background-color`, respectively:
202
+
203
+ Text in <span style="color: rgb(255,86,48);">red</span>, <span style="color: rgb(54,179,126);">green</span> and <span style="color: rgb(76,154,255);">blue</span>:
204
+
205
+ ```markdown
206
+ Text in <span style="color: rgb(255,86,48);">red</span>, <span style="color: rgb(54,179,126);">green</span> and <span style="color: rgb(76,154,255);">blue</span>.
207
+ ```
208
+
209
+ Highlight in <span style="background-color: rgb(198,237,251);">teal</span>, <span style="background-color: rgb(211,241,167);">lime</span> and <span style="background-color: rgb(254,222,200);">yellow</span>:
210
+
211
+ ```markdown
212
+ Highlight in <span style="background-color: rgb(198,237,251);">teal</span>, <span style="background-color: rgb(211,241,167);">lime</span> and <span style="background-color: rgb(254,222,200);">yellow</span>.
213
+ ```
214
+
215
+ The following table shows standard text colors (CSS `color`) that are available via Confluence UI:
216
+
217
+ | Color name | CSS attribute value |
218
+ | ------------- | ------------------- |
219
+ | bold blue | rgb(7,71,166) |
220
+ | blue | rgb(76,154,255) |
221
+ | subtle blue | rgb(179,212,255) |
222
+ | bold teal | rgb(0,141,166) |
223
+ | teal | rgb(0,184,217) |
224
+ | subtle teal | rgb(179,245,255) |
225
+ | bold green | rgb(0,102,68) |
226
+ | green | rgb(54,179,126) |
227
+ | subtle green | rgb(171,245,209) |
228
+ | bold orange | rgb(255,153,31) |
229
+ | yellow | rgb(255,196,0) |
230
+ | subtle yellow | rgb(255,240,179) |
231
+ | bold red | rgb(191,38,0) |
232
+ | red | rgb(255,86,48) |
233
+ | subtle red | rgb(255,189,173) |
234
+ | bold purple | rgb(64,50,148) |
235
+ | purple | rgb(101,84,192) |
236
+ | subtle purple | rgb(234,230,255) |
237
+
238
+ The following table shows standard highlight colors (CSS `background-color`) that are available via Confluence UI:
239
+
240
+ | Color name | CSS attribute value |
241
+ | ------------- | ------------------- |
242
+ | teal | rgb(198,237,251) |
243
+ | lime | rgb(211,241,167) |
244
+ | yellow | rgb(254,222,200) |
245
+ | magenta | rgb(253,208,236) |
246
+ | purple | rgb(223,216,253) |
247
+
167
248
  ### Lists and tables
168
249
 
169
250
  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.
@@ -188,12 +269,27 @@ Relative paths to items in a nested directory are not supported. You must put `.
188
269
 
189
270
  *md2conf* makes a best-effort attempt at setting the Confluence wiki page title when it publishes a Markdown document the first time. The following are probed in this order:
190
271
 
191
- 1. The `title` attribute set in the [front-matter](https://daily-dev-tips.com/posts/what-exactly-is-frontmatter/). Front-matter is a block delimited by `---` at the beginning of a Markdown document. Currently, only YAML syntax is supported.
272
+ 1. The `title` attribute set in the [front-matter](https://daily-dev-tips.com/posts/what-exactly-is-frontmatter/). Front-matter is a block delimited by `---` at the beginning of a Markdown document. Both JSON and YAML syntax are supported.
192
273
  2. The text of the topmost unique Markdown heading (`#`). For example, if a document has a single first-level heading (e.g. `# My document`), its text is used. However, if there are multiple first-level headings, this step is skipped.
193
274
  3. The file name (without the extension `.md`).
194
275
 
195
276
  If a matching Confluence page already exists for a Markdown file, the page title in Confluence is left unchanged.
196
277
 
278
+ ### Labels
279
+
280
+ If a Markdown document has the front-matter attribute `tags`, *md2conf* assigns the specified tags to the Confluence page as labels.
281
+
282
+ ```yaml
283
+ ---
284
+ title: "Example document"
285
+ tags: ["markdown", "md", "wiki"]
286
+ ---
287
+ ```
288
+
289
+ Any previously assigned labels are discarded. As per Confluence terminology, new labels have the `prefix` of `global`.
290
+
291
+ If a document has no `tags` attribute, existing Confluence labels are left intact.
292
+
197
293
  ### Converting diagrams
198
294
 
199
295
  You can include [Mermaid diagrams](https://mermaid.js.org/) in your Markdown documents to create visual representations of systems, processes, and relationships. When a Markdown document contains a code block with the language specifier `mermaid`, *md2conf* offers two options to publish the diagram:
@@ -201,6 +297,18 @@ You can include [Mermaid diagrams](https://mermaid.js.org/) in your Markdown doc
201
297
  1. Pre-render into an image. The code block is interpreted by and converted into a PNG or SVG image with the Mermaid diagram utility [mermaid-cli](https://github.com/mermaid-js/mermaid-cli). The generated image is then uploaded to Confluence as an attachment to the page. This is the approach we use and support.
202
298
  2. Render on demand. The code block is transformed into a [diagram macro](https://atlasauthority.atlassian.net/wiki/spaces/MARKDOWNCLOUD/pages/2946826241/Diagram+Macro), which is processed by Confluence. You need a [Confluence plugin](https://marketplace.atlassian.com/apps/1211438/markdown-html-plantuml-latex-diagrams-open-api-mermaid) to turn macro definitions into images when a Confluence page is visited. This is a contributed feature. As authors of *md2conf*, we don't endorse or support any particular Confluence plugin.
203
299
 
300
+ If you are running into issues with the pre-rendering approach (e.g. misaligned labels in the generated image), verify if `mermaid-cli` can process the Mermaid source:
301
+
302
+ ```sh
303
+ mmdc -i sample.mmd -o sample.png -b transparent --scale 2
304
+ ```
305
+
306
+ Ensure that `mermaid-cli` is set up, refer to *Installation* for instructions.
307
+
308
+ ### Local output
309
+
310
+ *md2conf* supports local output, in which the tool doesn't communicate with the Confluence REST API. Instead, it reads a single Markdown file or a directory of Markdown files, and writes Confluence Storage Format (`*.csf`) output for each document. (Confluence Storage Format is a derivative of XHTML with Confluence-specific tags for complex elements such as images with captions, code blocks, info panels, collapsed sections, etc.) You can push the generated output to Confluence by invoking the API (e.g. with `curl`).
311
+
204
312
  ### Running the tool
205
313
 
206
314
  You execute the command-line tool `md2conf` to synchronize the Markdown file with Confluence:
@@ -213,8 +321,8 @@ Use the `--help` switch to get a full list of supported command-line options:
213
321
 
214
322
  ```console
215
323
  $ python3 -m md2conf --help
216
- usage: md2conf [-h] [--version] [-d DOMAIN] [-p PATH] [-u USERNAME] [-a APIKEY] [-s SPACE] [-l {debug,info,warning,error,critical}] [-r ROOT_PAGE] [--keep-hierarchy] [--generated-by GENERATED_BY] [--no-generated-by]
217
- [--render-mermaid] [--no-render-mermaid] [--render-mermaid-format {png,svg}] [--heading-anchors] [--ignore-invalid-url] [--local] [--headers [KEY=VALUE ...]] [--webui-links]
324
+ usage: md2conf [-h] [--version] [-d DOMAIN] [-p PATH] [--api-url API_URL] [-u USERNAME] [-a API_KEY] [-s SPACE] [-l {debug,info,warning,error,critical}] [-r ROOT_PAGE] [--keep-hierarchy] [--generated-by GENERATED_BY]
325
+ [--no-generated-by] [--render-mermaid] [--no-render-mermaid] [--render-mermaid-format {png,svg}] [--heading-anchors] [--ignore-invalid-url] [--local] [--headers [KEY=VALUE ...]] [--webui-links]
218
326
  mdpath
219
327
 
220
328
  positional arguments:
@@ -226,9 +334,10 @@ options:
226
334
  -d DOMAIN, --domain DOMAIN
227
335
  Confluence organization domain.
228
336
  -p PATH, --path PATH Base path for Confluence (default: '/wiki/').
337
+ --api-url API_URL Confluence API URL. Required for scoped tokens. Refer to documentation how to obtain one.
229
338
  -u USERNAME, --username USERNAME
230
339
  Confluence user name.
231
- -a APIKEY, --apikey APIKEY
340
+ -a API_KEY, --apikey API_KEY, --api-key API_KEY
232
341
  Confluence API key. Refer to documentation how to obtain one.
233
342
  -s SPACE, --space SPACE
234
343
  Confluence space key for pages to be published. If omitted, will default to user space.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: markdown-to-confluence
3
- Version: 0.3.5
3
+ Version: 0.4.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,15 +21,17 @@ Classifier: Typing :: Typed
21
21
  Requires-Python: >=3.9
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
+ Requires-Dist: json_strong_typing>=0.3.9
24
25
  Requires-Dist: lxml>=5.4
25
26
  Requires-Dist: types-lxml>=2025.3.30
26
27
  Requires-Dist: markdown>=3.8
27
28
  Requires-Dist: types-markdown>=3.8
28
- Requires-Dist: pymdown-extensions>=10.15
29
+ Requires-Dist: pymdown-extensions>=10.16
29
30
  Requires-Dist: PyYAML>=6.0
30
31
  Requires-Dist: types-PyYAML>=6.0
31
32
  Requires-Dist: requests>=2.32
32
33
  Requires-Dist: types-requests>=2.32
34
+ Requires-Dist: typing_extensions>=4.14; python_version < "3.12"
33
35
  Dynamic: license-file
34
36
 
35
37
  # Publish Markdown files to Confluence wiki
@@ -49,7 +51,10 @@ This Python package
49
51
  * Sections and subsections
50
52
  * Text with **bold**, *italic*, `monospace`, <ins>underline</ins> and ~~strikethrough~~
51
53
  * Link to [sections on the same page](#getting-started) or [external locations](http://example.com/)
54
+ * Subscript and superscript (with HTML tags `<sub>` and `<sup>`)
55
+ * Emoji
52
56
  * Ordered and unordered lists
57
+ * Block quotes
53
58
  * Code blocks (e.g. Python, JSON, XML)
54
59
  * Images (uploaded as Confluence page attachments or hosted externally)
55
60
  * Tables
@@ -95,7 +100,7 @@ In order to get started, you will need
95
100
 
96
101
  Confluence organization domain, base path, username, API token and space key can be specified at runtime or set as Confluence environment variables (e.g. add to your `~/.profile` on Linux, or `~/.bash_profile` or `~/.zshenv` on MacOS):
97
102
 
98
- ```bash
103
+ ```sh
99
104
  export CONFLUENCE_DOMAIN='example.atlassian.net'
100
105
  export CONFLUENCE_PATH='/wiki/'
101
106
  export CONFLUENCE_USER_NAME='levente.hunyadi@instructure.com'
@@ -105,10 +110,29 @@ export CONFLUENCE_SPACE_KEY='SPACE'
105
110
 
106
111
  On Windows, these can be set via system properties.
107
112
 
113
+ If you use Atlassian scoped API tokens, you should set API URL, substituting `CLOUD_ID` with your own Cloud ID:
114
+
115
+ ```sh
116
+ export CONFLUENCE_API_URL='https://api.atlassian.com/ex/confluence/CLOUD_ID/'
117
+ ```
118
+
119
+ In this case, *md2conf* can automatically determine `CONFLUENCE_DOMAIN` and `CONFLUENCE_PATH`.
120
+
108
121
  ### Permissions
109
122
 
110
123
  The tool requires appropriate permissions in Confluence in order to invoke endpoints.
111
124
 
125
+ Required scopes for scoped API tokens are as follows:
126
+
127
+ * `read:page:confluence`
128
+ * `write:page:confluence`
129
+ * `read:space:confluence`
130
+ * `write:space:confluence`
131
+ * `read:attachment:confluence`
132
+ * `write:attachment:confluence`
133
+ * `read:label:confluence`
134
+ * `write:label:confluence`
135
+
112
136
  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.
113
137
 
114
138
  If you lack appropriate permissions, you will get an *Unauthorized* response from Confluence. The tool will emit a message that looks as follows:
@@ -198,6 +222,65 @@ root
198
222
  └── Mean vs. median
199
223
  ```
200
224
 
225
+ ### Emoji
226
+
227
+ The short name notation `:smile:` in a Markdown document is converted into the corresponding emoji 😄 when publishing to Confluence.
228
+
229
+ *md2conf* relies on the [Emoji extension](https://facelessuser.github.io/pymdown-extensions/extensions/emoji/) of [PyMdown Extensions](https://facelessuser.github.io/pymdown-extensions/) to parse the short name notation with colons, and generate Confluence Storage Format output such as
230
+
231
+ ```xml
232
+ <ac:emoticon ac:name="smile" ac:emoji-shortname=":smile:" ac:emoji-id="1f604" ac:emoji-fallback="&#128516;"/>
233
+ ```
234
+
235
+ ### Colors
236
+
237
+ Confluence allows setting text color and highlight color. Even though Markdown doesn't directly support colors, it is possible to set text and highlight color via the HTML element `<span>` and the CSS attributes `color` and `background-color`, respectively:
238
+
239
+ Text in <span style="color: rgb(255,86,48);">red</span>, <span style="color: rgb(54,179,126);">green</span> and <span style="color: rgb(76,154,255);">blue</span>:
240
+
241
+ ```markdown
242
+ Text in <span style="color: rgb(255,86,48);">red</span>, <span style="color: rgb(54,179,126);">green</span> and <span style="color: rgb(76,154,255);">blue</span>.
243
+ ```
244
+
245
+ Highlight in <span style="background-color: rgb(198,237,251);">teal</span>, <span style="background-color: rgb(211,241,167);">lime</span> and <span style="background-color: rgb(254,222,200);">yellow</span>:
246
+
247
+ ```markdown
248
+ Highlight in <span style="background-color: rgb(198,237,251);">teal</span>, <span style="background-color: rgb(211,241,167);">lime</span> and <span style="background-color: rgb(254,222,200);">yellow</span>.
249
+ ```
250
+
251
+ The following table shows standard text colors (CSS `color`) that are available via Confluence UI:
252
+
253
+ | Color name | CSS attribute value |
254
+ | ------------- | ------------------- |
255
+ | bold blue | rgb(7,71,166) |
256
+ | blue | rgb(76,154,255) |
257
+ | subtle blue | rgb(179,212,255) |
258
+ | bold teal | rgb(0,141,166) |
259
+ | teal | rgb(0,184,217) |
260
+ | subtle teal | rgb(179,245,255) |
261
+ | bold green | rgb(0,102,68) |
262
+ | green | rgb(54,179,126) |
263
+ | subtle green | rgb(171,245,209) |
264
+ | bold orange | rgb(255,153,31) |
265
+ | yellow | rgb(255,196,0) |
266
+ | subtle yellow | rgb(255,240,179) |
267
+ | bold red | rgb(191,38,0) |
268
+ | red | rgb(255,86,48) |
269
+ | subtle red | rgb(255,189,173) |
270
+ | bold purple | rgb(64,50,148) |
271
+ | purple | rgb(101,84,192) |
272
+ | subtle purple | rgb(234,230,255) |
273
+
274
+ The following table shows standard highlight colors (CSS `background-color`) that are available via Confluence UI:
275
+
276
+ | Color name | CSS attribute value |
277
+ | ------------- | ------------------- |
278
+ | teal | rgb(198,237,251) |
279
+ | lime | rgb(211,241,167) |
280
+ | yellow | rgb(254,222,200) |
281
+ | magenta | rgb(253,208,236) |
282
+ | purple | rgb(223,216,253) |
283
+
201
284
  ### Lists and tables
202
285
 
203
286
  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.
@@ -222,12 +305,27 @@ Relative paths to items in a nested directory are not supported. You must put `.
222
305
 
223
306
  *md2conf* makes a best-effort attempt at setting the Confluence wiki page title when it publishes a Markdown document the first time. The following are probed in this order:
224
307
 
225
- 1. The `title` attribute set in the [front-matter](https://daily-dev-tips.com/posts/what-exactly-is-frontmatter/). Front-matter is a block delimited by `---` at the beginning of a Markdown document. Currently, only YAML syntax is supported.
308
+ 1. The `title` attribute set in the [front-matter](https://daily-dev-tips.com/posts/what-exactly-is-frontmatter/). Front-matter is a block delimited by `---` at the beginning of a Markdown document. Both JSON and YAML syntax are supported.
226
309
  2. The text of the topmost unique Markdown heading (`#`). For example, if a document has a single first-level heading (e.g. `# My document`), its text is used. However, if there are multiple first-level headings, this step is skipped.
227
310
  3. The file name (without the extension `.md`).
228
311
 
229
312
  If a matching Confluence page already exists for a Markdown file, the page title in Confluence is left unchanged.
230
313
 
314
+ ### Labels
315
+
316
+ If a Markdown document has the front-matter attribute `tags`, *md2conf* assigns the specified tags to the Confluence page as labels.
317
+
318
+ ```yaml
319
+ ---
320
+ title: "Example document"
321
+ tags: ["markdown", "md", "wiki"]
322
+ ---
323
+ ```
324
+
325
+ Any previously assigned labels are discarded. As per Confluence terminology, new labels have the `prefix` of `global`.
326
+
327
+ If a document has no `tags` attribute, existing Confluence labels are left intact.
328
+
231
329
  ### Converting diagrams
232
330
 
233
331
  You can include [Mermaid diagrams](https://mermaid.js.org/) in your Markdown documents to create visual representations of systems, processes, and relationships. When a Markdown document contains a code block with the language specifier `mermaid`, *md2conf* offers two options to publish the diagram:
@@ -235,6 +333,18 @@ You can include [Mermaid diagrams](https://mermaid.js.org/) in your Markdown doc
235
333
  1. Pre-render into an image. The code block is interpreted by and converted into a PNG or SVG image with the Mermaid diagram utility [mermaid-cli](https://github.com/mermaid-js/mermaid-cli). The generated image is then uploaded to Confluence as an attachment to the page. This is the approach we use and support.
236
334
  2. Render on demand. The code block is transformed into a [diagram macro](https://atlasauthority.atlassian.net/wiki/spaces/MARKDOWNCLOUD/pages/2946826241/Diagram+Macro), which is processed by Confluence. You need a [Confluence plugin](https://marketplace.atlassian.com/apps/1211438/markdown-html-plantuml-latex-diagrams-open-api-mermaid) to turn macro definitions into images when a Confluence page is visited. This is a contributed feature. As authors of *md2conf*, we don't endorse or support any particular Confluence plugin.
237
335
 
336
+ If you are running into issues with the pre-rendering approach (e.g. misaligned labels in the generated image), verify if `mermaid-cli` can process the Mermaid source:
337
+
338
+ ```sh
339
+ mmdc -i sample.mmd -o sample.png -b transparent --scale 2
340
+ ```
341
+
342
+ Ensure that `mermaid-cli` is set up, refer to *Installation* for instructions.
343
+
344
+ ### Local output
345
+
346
+ *md2conf* supports local output, in which the tool doesn't communicate with the Confluence REST API. Instead, it reads a single Markdown file or a directory of Markdown files, and writes Confluence Storage Format (`*.csf`) output for each document. (Confluence Storage Format is a derivative of XHTML with Confluence-specific tags for complex elements such as images with captions, code blocks, info panels, collapsed sections, etc.) You can push the generated output to Confluence by invoking the API (e.g. with `curl`).
347
+
238
348
  ### Running the tool
239
349
 
240
350
  You execute the command-line tool `md2conf` to synchronize the Markdown file with Confluence:
@@ -247,8 +357,8 @@ Use the `--help` switch to get a full list of supported command-line options:
247
357
 
248
358
  ```console
249
359
  $ python3 -m md2conf --help
250
- usage: md2conf [-h] [--version] [-d DOMAIN] [-p PATH] [-u USERNAME] [-a APIKEY] [-s SPACE] [-l {debug,info,warning,error,critical}] [-r ROOT_PAGE] [--keep-hierarchy] [--generated-by GENERATED_BY] [--no-generated-by]
251
- [--render-mermaid] [--no-render-mermaid] [--render-mermaid-format {png,svg}] [--heading-anchors] [--ignore-invalid-url] [--local] [--headers [KEY=VALUE ...]] [--webui-links]
360
+ usage: md2conf [-h] [--version] [-d DOMAIN] [-p PATH] [--api-url API_URL] [-u USERNAME] [-a API_KEY] [-s SPACE] [-l {debug,info,warning,error,critical}] [-r ROOT_PAGE] [--keep-hierarchy] [--generated-by GENERATED_BY]
361
+ [--no-generated-by] [--render-mermaid] [--no-render-mermaid] [--render-mermaid-format {png,svg}] [--heading-anchors] [--ignore-invalid-url] [--local] [--headers [KEY=VALUE ...]] [--webui-links]
252
362
  mdpath
253
363
 
254
364
  positional arguments:
@@ -260,9 +370,10 @@ options:
260
370
  -d DOMAIN, --domain DOMAIN
261
371
  Confluence organization domain.
262
372
  -p PATH, --path PATH Base path for Confluence (default: '/wiki/').
373
+ --api-url API_URL Confluence API URL. Required for scoped tokens. Refer to documentation how to obtain one.
263
374
  -u USERNAME, --username USERNAME
264
375
  Confluence user name.
265
- -a APIKEY, --apikey APIKEY
376
+ -a API_KEY, --apikey API_KEY, --api-key API_KEY
266
377
  Confluence API key. Refer to documentation how to obtain one.
267
378
  -s SPACE, --space SPACE
268
379
  Confluence space key for pages to be published. If omitted, will default to user space.
@@ -14,9 +14,11 @@ md2conf/__init__.py
14
14
  md2conf/__main__.py
15
15
  md2conf/api.py
16
16
  md2conf/application.py
17
+ md2conf/collection.py
17
18
  md2conf/converter.py
18
19
  md2conf/emoji.py
19
20
  md2conf/entities.dtd
21
+ md2conf/extra.py
20
22
  md2conf/local.py
21
23
  md2conf/matcher.py
22
24
  md2conf/mermaid.py
@@ -1,9 +1,13 @@
1
+ json_strong_typing>=0.3.9
1
2
  lxml>=5.4
2
3
  types-lxml>=2025.3.30
3
4
  markdown>=3.8
4
5
  types-markdown>=3.8
5
- pymdown-extensions>=10.15
6
+ pymdown-extensions>=10.16
6
7
  PyYAML>=6.0
7
8
  types-PyYAML>=6.0
8
9
  requests>=2.32
9
10
  types-requests>=2.32
11
+
12
+ [:python_version < "3.12"]
13
+ typing_extensions>=4.14
@@ -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.3.5"
8
+ __version__ = "0.4.0"
9
9
  __author__ = "Levente Hunyadi"
10
10
  __copyright__ = "Copyright 2022-2025, Levente Hunyadi"
11
11
  __license__ = "MIT"