markdown-to-confluence 0.3.5__tar.gz → 0.4.1__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 (77) hide show
  1. markdown_to_confluence-0.4.1/MANIFEST.in +7 -0
  2. {markdown_to_confluence-0.3.5/markdown_to_confluence.egg-info → markdown_to_confluence-0.4.1}/PKG-INFO +150 -17
  3. markdown_to_confluence-0.3.5/PKG-INFO → markdown_to_confluence-0.4.1/README.md +130 -39
  4. markdown_to_confluence-0.3.5/README.md → markdown_to_confluence-0.4.1/markdown_to_confluence.egg-info/PKG-INFO +172 -5
  5. markdown_to_confluence-0.4.1/markdown_to_confluence.egg-info/SOURCES.txt +67 -0
  6. markdown_to_confluence-0.4.1/markdown_to_confluence.egg-info/requires.txt +20 -0
  7. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/md2conf/__init__.py +1 -1
  8. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/md2conf/__main__.py +20 -17
  9. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/md2conf/api.py +529 -216
  10. markdown_to_confluence-0.4.1/md2conf/application.py +202 -0
  11. markdown_to_confluence-0.4.1/md2conf/collection.py +31 -0
  12. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/md2conf/converter.py +99 -78
  13. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/md2conf/emoji.py +28 -3
  14. markdown_to_confluence-0.4.1/md2conf/extra.py +27 -0
  15. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/md2conf/local.py +28 -41
  16. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/md2conf/matcher.py +1 -3
  17. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/md2conf/mermaid.py +2 -7
  18. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/md2conf/metadata.py +0 -2
  19. markdown_to_confluence-0.4.1/md2conf/processor.py +294 -0
  20. markdown_to_confluence-0.4.1/md2conf/properties.py +135 -0
  21. markdown_to_confluence-0.4.1/md2conf/scanner.py +150 -0
  22. markdown_to_confluence-0.4.1/pyproject.toml +76 -0
  23. markdown_to_confluence-0.4.1/setup.cfg +4 -0
  24. markdown_to_confluence-0.4.1/tests/__init__.py +0 -0
  25. markdown_to_confluence-0.4.1/tests/source/admonition.md +20 -0
  26. markdown_to_confluence-0.4.1/tests/source/alert.md +56 -0
  27. markdown_to_confluence-0.4.1/tests/source/anchors.md +13 -0
  28. markdown_to_confluence-0.4.1/tests/source/basic.md +65 -0
  29. markdown_to_confluence-0.4.1/tests/source/code.md +38 -0
  30. markdown_to_confluence-0.4.1/tests/source/collapsed.md +24 -0
  31. markdown_to_confluence-0.4.1/tests/source/fenced.md +25 -0
  32. markdown_to_confluence-0.4.1/tests/source/figure/raster.png +0 -0
  33. markdown_to_confluence-0.4.1/tests/source/figure/vector.svg +4 -0
  34. markdown_to_confluence-0.4.1/tests/source/ignore.md +3 -0
  35. markdown_to_confluence-0.4.1/tests/source/images/images.md +5 -0
  36. markdown_to_confluence-0.4.1/tests/source/images.md +11 -0
  37. markdown_to_confluence-0.4.1/tests/source/mermaid.md +135 -0
  38. markdown_to_confluence-0.4.1/tests/source/missing.md +7 -0
  39. markdown_to_confluence-0.4.1/tests/source/sections.md +18 -0
  40. markdown_to_confluence-0.4.1/tests/source/tags.md +21 -0
  41. markdown_to_confluence-0.4.1/tests/source/title.md +19 -0
  42. markdown_to_confluence-0.4.1/tests/target/admonition.xml +37 -0
  43. markdown_to_confluence-0.4.1/tests/target/alert.xml +67 -0
  44. markdown_to_confluence-0.4.1/tests/target/anchors.xml +11 -0
  45. markdown_to_confluence-0.4.1/tests/target/basic.xml +59 -0
  46. markdown_to_confluence-0.4.1/tests/target/code.xml +39 -0
  47. markdown_to_confluence-0.4.1/tests/target/collapsed.xml +25 -0
  48. markdown_to_confluence-0.4.1/tests/target/fenced.xml +32 -0
  49. markdown_to_confluence-0.4.1/tests/target/images/images.xml +12 -0
  50. markdown_to_confluence-0.4.1/tests/target/images.xml +27 -0
  51. markdown_to_confluence-0.4.1/tests/target/mermaid.xml +113 -0
  52. markdown_to_confluence-0.4.1/tests/target/missing.xml +13 -0
  53. markdown_to_confluence-0.4.1/tests/target/sections.xml +11 -0
  54. markdown_to_confluence-0.4.1/tests/target/tags.xml +31 -0
  55. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/tests/test_conversion.py +34 -20
  56. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/tests/test_matcher.py +2 -10
  57. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/tests/test_mermaid.py +3 -0
  58. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/tests/test_processor.py +5 -4
  59. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/tests/test_scanner.py +11 -1
  60. markdown_to_confluence-0.4.1/tests/test_unit.py +33 -0
  61. markdown_to_confluence-0.3.5/markdown_to_confluence.egg-info/SOURCES.txt +0 -33
  62. markdown_to_confluence-0.3.5/markdown_to_confluence.egg-info/requires.txt +0 -9
  63. markdown_to_confluence-0.3.5/md2conf/application.py +0 -213
  64. markdown_to_confluence-0.3.5/md2conf/processor.py +0 -216
  65. markdown_to_confluence-0.3.5/md2conf/properties.py +0 -83
  66. markdown_to_confluence-0.3.5/md2conf/scanner.py +0 -117
  67. markdown_to_confluence-0.3.5/pyproject.toml +0 -3
  68. markdown_to_confluence-0.3.5/setup.cfg +0 -62
  69. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/LICENSE +0 -0
  70. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/markdown_to_confluence.egg-info/dependency_links.txt +0 -0
  71. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/markdown_to_confluence.egg-info/entry_points.txt +0 -0
  72. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/markdown_to_confluence.egg-info/top_level.txt +0 -0
  73. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/markdown_to_confluence.egg-info/zip-safe +0 -0
  74. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/md2conf/entities.dtd +0 -0
  75. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/md2conf/puppeteer-config.json +0 -0
  76. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/md2conf/py.typed +0 -0
  77. {markdown_to_confluence-0.3.5 → markdown_to_confluence-0.4.1}/setup.py +0 -0
@@ -0,0 +1,7 @@
1
+ recursive-include tests *.py
2
+ recursive-include tests *.md
3
+ recursive-include tests *.png
4
+ recursive-include tests *.svg
5
+ recursive-include tests *.xml
6
+ exclude tests/source/emoji.md
7
+ exclude tests/target/emoji.xml
@@ -1,15 +1,16 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: markdown-to-confluence
3
- Version: 0.3.5
3
+ Version: 0.4.1
4
4
  Summary: Publish Markdown files to Confluence wiki
5
- Home-page: https://github.com/hunyadi/md2conf
6
- Author: Levente Hunyadi
7
- Author-email: hunyadi@gmail.com
8
- License: MIT
5
+ Author-email: Levente Hunyadi <hunyadi@gmail.com>
6
+ Maintainer-email: Levente Hunyadi <hunyadi@gmail.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/hunyadi/md2conf
9
+ Project-URL: Source, https://github.com/hunyadi/md2conf
10
+ Keywords: markdown,converter,confluence
9
11
  Classifier: Development Status :: 5 - Production/Stable
10
12
  Classifier: Environment :: Console
11
13
  Classifier: Intended Audience :: End Users/Desktop
12
- Classifier: License :: OSI Approved :: MIT License
13
14
  Classifier: Operating System :: OS Independent
14
15
  Classifier: Programming Language :: Python :: 3
15
16
  Classifier: Programming Language :: Python :: 3.9
@@ -17,19 +18,26 @@ Classifier: Programming Language :: Python :: 3.10
17
18
  Classifier: Programming Language :: Python :: 3.11
18
19
  Classifier: Programming Language :: Python :: 3.12
19
20
  Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3 :: Only
20
22
  Classifier: Typing :: Typed
21
23
  Requires-Python: >=3.9
22
24
  Description-Content-Type: text/markdown
23
25
  License-File: LICENSE
24
- Requires-Dist: lxml>=5.4
25
- Requires-Dist: types-lxml>=2025.3.30
26
+ Requires-Dist: json_strong_typing>=0.3.9
27
+ Requires-Dist: lxml>=6.0
26
28
  Requires-Dist: markdown>=3.8
27
- 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
- Requires-Dist: types-PyYAML>=6.0
31
31
  Requires-Dist: requests>=2.32
32
- Requires-Dist: types-requests>=2.32
32
+ Requires-Dist: typing_extensions>=4.14; python_version < "3.12"
33
+ Provides-Extra: dev
34
+ Requires-Dist: markdown_doc>=0.1.4; python_version >= "3.10" and extra == "dev"
35
+ Requires-Dist: types-lxml>=2025.3.30; extra == "dev"
36
+ Requires-Dist: types-markdown>=3.8; extra == "dev"
37
+ Requires-Dist: types-PyYAML>=6.0; extra == "dev"
38
+ Requires-Dist: types-requests>=2.32; extra == "dev"
39
+ Requires-Dist: mypy>=1.16; extra == "dev"
40
+ Requires-Dist: ruff>=0.12; extra == "dev"
33
41
  Dynamic: license-file
34
42
 
35
43
  # Publish Markdown files to Confluence wiki
@@ -49,7 +57,10 @@ This Python package
49
57
  * Sections and subsections
50
58
  * Text with **bold**, *italic*, `monospace`, <ins>underline</ins> and ~~strikethrough~~
51
59
  * Link to [sections on the same page](#getting-started) or [external locations](http://example.com/)
60
+ * Subscript and superscript (with HTML tags `<sub>` and `<sup>`)
61
+ * Emoji
52
62
  * Ordered and unordered lists
63
+ * Block quotes
53
64
  * Code blocks (e.g. Python, JSON, XML)
54
65
  * Images (uploaded as Confluence page attachments or hosted externally)
55
66
  * Tables
@@ -95,7 +106,7 @@ In order to get started, you will need
95
106
 
96
107
  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
108
 
98
- ```bash
109
+ ```sh
99
110
  export CONFLUENCE_DOMAIN='example.atlassian.net'
100
111
  export CONFLUENCE_PATH='/wiki/'
101
112
  export CONFLUENCE_USER_NAME='levente.hunyadi@instructure.com'
@@ -105,10 +116,29 @@ export CONFLUENCE_SPACE_KEY='SPACE'
105
116
 
106
117
  On Windows, these can be set via system properties.
107
118
 
119
+ If you use Atlassian scoped API tokens, you should set API URL, substituting `CLOUD_ID` with your own Cloud ID:
120
+
121
+ ```sh
122
+ export CONFLUENCE_API_URL='https://api.atlassian.com/ex/confluence/CLOUD_ID/'
123
+ ```
124
+
125
+ In this case, *md2conf* can automatically determine `CONFLUENCE_DOMAIN` and `CONFLUENCE_PATH`.
126
+
108
127
  ### Permissions
109
128
 
110
129
  The tool requires appropriate permissions in Confluence in order to invoke endpoints.
111
130
 
131
+ Required scopes for scoped API tokens are as follows:
132
+
133
+ * `read:page:confluence`
134
+ * `write:page:confluence`
135
+ * `read:space:confluence`
136
+ * `write:space:confluence`
137
+ * `read:attachment:confluence`
138
+ * `write:attachment:confluence`
139
+ * `read:label:confluence`
140
+ * `write:label:confluence`
141
+
112
142
  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
143
 
114
144
  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 +228,65 @@ root
198
228
  └── Mean vs. median
199
229
  ```
200
230
 
231
+ ### Emoji
232
+
233
+ The short name notation `:smile:` in a Markdown document is converted into the corresponding emoji 😄 when publishing to Confluence.
234
+
235
+ *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
236
+
237
+ ```xml
238
+ <ac:emoticon ac:name="smile" ac:emoji-shortname=":smile:" ac:emoji-id="1f604" ac:emoji-fallback="&#128516;"/>
239
+ ```
240
+
241
+ ### Colors
242
+
243
+ 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:
244
+
245
+ 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>:
246
+
247
+ ```markdown
248
+ 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>.
249
+ ```
250
+
251
+ 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>:
252
+
253
+ ```markdown
254
+ 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>.
255
+ ```
256
+
257
+ The following table shows standard text colors (CSS `color`) that are available via Confluence UI:
258
+
259
+ | Color name | CSS attribute value |
260
+ | ------------- | ------------------- |
261
+ | bold blue | rgb(7,71,166) |
262
+ | blue | rgb(76,154,255) |
263
+ | subtle blue | rgb(179,212,255) |
264
+ | bold teal | rgb(0,141,166) |
265
+ | teal | rgb(0,184,217) |
266
+ | subtle teal | rgb(179,245,255) |
267
+ | bold green | rgb(0,102,68) |
268
+ | green | rgb(54,179,126) |
269
+ | subtle green | rgb(171,245,209) |
270
+ | bold orange | rgb(255,153,31) |
271
+ | yellow | rgb(255,196,0) |
272
+ | subtle yellow | rgb(255,240,179) |
273
+ | bold red | rgb(191,38,0) |
274
+ | red | rgb(255,86,48) |
275
+ | subtle red | rgb(255,189,173) |
276
+ | bold purple | rgb(64,50,148) |
277
+ | purple | rgb(101,84,192) |
278
+ | subtle purple | rgb(234,230,255) |
279
+
280
+ The following table shows standard highlight colors (CSS `background-color`) that are available via Confluence UI:
281
+
282
+ | Color name | CSS attribute value |
283
+ | ------------- | ------------------- |
284
+ | teal | rgb(198,237,251) |
285
+ | lime | rgb(211,241,167) |
286
+ | yellow | rgb(254,222,200) |
287
+ | magenta | rgb(253,208,236) |
288
+ | purple | rgb(223,216,253) |
289
+
201
290
  ### Lists and tables
202
291
 
203
292
  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 +311,43 @@ Relative paths to items in a nested directory are not supported. You must put `.
222
311
 
223
312
  *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
313
 
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.
314
+ 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
315
  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
316
  3. The file name (without the extension `.md`).
228
317
 
229
318
  If a matching Confluence page already exists for a Markdown file, the page title in Confluence is left unchanged.
230
319
 
320
+ ### Labels
321
+
322
+ If a Markdown document has the front-matter attribute `tags`, *md2conf* assigns the specified tags to the Confluence page as labels.
323
+
324
+ ```yaml
325
+ ---
326
+ title: "Example document"
327
+ tags: ["markdown", "md", "wiki"]
328
+ ---
329
+ ```
330
+
331
+ Any previously assigned labels are discarded. As per Confluence terminology, new labels have the `prefix` of `global`.
332
+
333
+ If a document has no `tags` attribute, existing Confluence labels are left intact.
334
+
335
+ ### Content properties
336
+
337
+ The front-matter attribute `properties` in a Markdown document allows setting Confluence content properties on a page. Confluence content properties are a way to store structured metadata in the form of key-value pairs directly on Confluence content. The values in content properties are represented as JSON objects.
338
+
339
+ Some content properties have special meaning to Confluence. For example, the following properties cause Confluence to display a wiki page with content confined to a fixed width in regular view mode, and taking the full page width in draft mode:
340
+
341
+ ```yaml
342
+ ---
343
+ properties:
344
+ content-appearance-published: fixed-width
345
+ content-appearance-draft: full-width
346
+ ---
347
+ ```
348
+
349
+ The attribute `properties` is parsed as a dictionary with keys of type string and values of type JSON. *md2conf* passes JSON values to Confluence REST API unchanged.
350
+
231
351
  ### Converting diagrams
232
352
 
233
353
  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 +355,18 @@ You can include [Mermaid diagrams](https://mermaid.js.org/) in your Markdown doc
235
355
  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
356
  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
357
 
358
+ 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:
359
+
360
+ ```sh
361
+ mmdc -i sample.mmd -o sample.png -b transparent --scale 2
362
+ ```
363
+
364
+ Ensure that `mermaid-cli` is set up, refer to *Installation* for instructions.
365
+
366
+ ### Local output
367
+
368
+ *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`).
369
+
238
370
  ### Running the tool
239
371
 
240
372
  You execute the command-line tool `md2conf` to synchronize the Markdown file with Confluence:
@@ -247,8 +379,8 @@ Use the `--help` switch to get a full list of supported command-line options:
247
379
 
248
380
  ```console
249
381
  $ 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]
382
+ 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]
383
+ [--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
384
  mdpath
253
385
 
254
386
  positional arguments:
@@ -260,9 +392,10 @@ options:
260
392
  -d DOMAIN, --domain DOMAIN
261
393
  Confluence organization domain.
262
394
  -p PATH, --path PATH Base path for Confluence (default: '/wiki/').
395
+ --api-url API_URL Confluence API URL. Required for scoped tokens. Refer to documentation how to obtain one.
263
396
  -u USERNAME, --username USERNAME
264
397
  Confluence user name.
265
- -a APIKEY, --apikey APIKEY
398
+ -a API_KEY, --apikey API_KEY, --api-key API_KEY
266
399
  Confluence API key. Refer to documentation how to obtain one.
267
400
  -s SPACE, --space SPACE
268
401
  Confluence space key for pages to be published. If omitted, will default to user space.
@@ -1,37 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: markdown-to-confluence
3
- Version: 0.3.5
4
- Summary: Publish Markdown files to Confluence wiki
5
- Home-page: https://github.com/hunyadi/md2conf
6
- Author: Levente Hunyadi
7
- Author-email: hunyadi@gmail.com
8
- License: MIT
9
- Classifier: Development Status :: 5 - Production/Stable
10
- Classifier: Environment :: Console
11
- Classifier: Intended Audience :: End Users/Desktop
12
- Classifier: License :: OSI Approved :: MIT License
13
- Classifier: Operating System :: OS Independent
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.9
16
- Classifier: Programming Language :: Python :: 3.10
17
- Classifier: Programming Language :: Python :: 3.11
18
- Classifier: Programming Language :: Python :: 3.12
19
- Classifier: Programming Language :: Python :: 3.13
20
- Classifier: Typing :: Typed
21
- Requires-Python: >=3.9
22
- Description-Content-Type: text/markdown
23
- License-File: LICENSE
24
- Requires-Dist: lxml>=5.4
25
- Requires-Dist: types-lxml>=2025.3.30
26
- Requires-Dist: markdown>=3.8
27
- Requires-Dist: types-markdown>=3.8
28
- Requires-Dist: pymdown-extensions>=10.15
29
- Requires-Dist: PyYAML>=6.0
30
- Requires-Dist: types-PyYAML>=6.0
31
- Requires-Dist: requests>=2.32
32
- Requires-Dist: types-requests>=2.32
33
- Dynamic: license-file
34
-
35
1
  # Publish Markdown files to Confluence wiki
36
2
 
37
3
  Contributors to software projects typically write documentation in Markdown format and host Markdown files in collaborative version control systems (VCS) such as GitHub or GitLab to track changes and facilitate the review process. However, not everyone at a company has access to VCS, and documents are often circulated in Confluence wiki instead.
@@ -49,7 +15,10 @@ This Python package
49
15
  * Sections and subsections
50
16
  * Text with **bold**, *italic*, `monospace`, <ins>underline</ins> and ~~strikethrough~~
51
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
52
20
  * Ordered and unordered lists
21
+ * Block quotes
53
22
  * Code blocks (e.g. Python, JSON, XML)
54
23
  * Images (uploaded as Confluence page attachments or hosted externally)
55
24
  * Tables
@@ -95,7 +64,7 @@ In order to get started, you will need
95
64
 
96
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):
97
66
 
98
- ```bash
67
+ ```sh
99
68
  export CONFLUENCE_DOMAIN='example.atlassian.net'
100
69
  export CONFLUENCE_PATH='/wiki/'
101
70
  export CONFLUENCE_USER_NAME='levente.hunyadi@instructure.com'
@@ -105,10 +74,29 @@ export CONFLUENCE_SPACE_KEY='SPACE'
105
74
 
106
75
  On Windows, these can be set via system properties.
107
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
+
108
85
  ### Permissions
109
86
 
110
87
  The tool requires appropriate permissions in Confluence in order to invoke endpoints.
111
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
+
112
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.
113
101
 
114
102
  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 +186,65 @@ root
198
186
  └── Mean vs. median
199
187
  ```
200
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
+
201
248
  ### Lists and tables
202
249
 
203
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.
@@ -222,12 +269,43 @@ Relative paths to items in a nested directory are not supported. You must put `.
222
269
 
223
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:
224
271
 
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.
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.
226
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.
227
274
  3. The file name (without the extension `.md`).
228
275
 
229
276
  If a matching Confluence page already exists for a Markdown file, the page title in Confluence is left unchanged.
230
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
+
293
+ ### Content properties
294
+
295
+ The front-matter attribute `properties` in a Markdown document allows setting Confluence content properties on a page. Confluence content properties are a way to store structured metadata in the form of key-value pairs directly on Confluence content. The values in content properties are represented as JSON objects.
296
+
297
+ Some content properties have special meaning to Confluence. For example, the following properties cause Confluence to display a wiki page with content confined to a fixed width in regular view mode, and taking the full page width in draft mode:
298
+
299
+ ```yaml
300
+ ---
301
+ properties:
302
+ content-appearance-published: fixed-width
303
+ content-appearance-draft: full-width
304
+ ---
305
+ ```
306
+
307
+ The attribute `properties` is parsed as a dictionary with keys of type string and values of type JSON. *md2conf* passes JSON values to Confluence REST API unchanged.
308
+
231
309
  ### Converting diagrams
232
310
 
233
311
  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 +313,18 @@ You can include [Mermaid diagrams](https://mermaid.js.org/) in your Markdown doc
235
313
  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
314
  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
315
 
316
+ 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:
317
+
318
+ ```sh
319
+ mmdc -i sample.mmd -o sample.png -b transparent --scale 2
320
+ ```
321
+
322
+ Ensure that `mermaid-cli` is set up, refer to *Installation* for instructions.
323
+
324
+ ### Local output
325
+
326
+ *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`).
327
+
238
328
  ### Running the tool
239
329
 
240
330
  You execute the command-line tool `md2conf` to synchronize the Markdown file with Confluence:
@@ -247,8 +337,8 @@ Use the `--help` switch to get a full list of supported command-line options:
247
337
 
248
338
  ```console
249
339
  $ 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]
340
+ 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]
341
+ [--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
342
  mdpath
253
343
 
254
344
  positional arguments:
@@ -260,9 +350,10 @@ options:
260
350
  -d DOMAIN, --domain DOMAIN
261
351
  Confluence organization domain.
262
352
  -p PATH, --path PATH Base path for Confluence (default: '/wiki/').
353
+ --api-url API_URL Confluence API URL. Required for scoped tokens. Refer to documentation how to obtain one.
263
354
  -u USERNAME, --username USERNAME
264
355
  Confluence user name.
265
- -a APIKEY, --apikey APIKEY
356
+ -a API_KEY, --apikey API_KEY, --api-key API_KEY
266
357
  Confluence API key. Refer to documentation how to obtain one.
267
358
  -s SPACE, --space SPACE
268
359
  Confluence space key for pages to be published. If omitted, will default to user space.