markdown-to-confluence 0.4.2__tar.gz → 0.4.3__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 (83) hide show
  1. {markdown_to_confluence-0.4.2/markdown_to_confluence.egg-info → markdown_to_confluence-0.4.3}/PKG-INFO +8 -12
  2. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/README.md +7 -11
  3. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3/markdown_to_confluence.egg-info}/PKG-INFO +8 -12
  4. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/markdown_to_confluence.egg-info/SOURCES.txt +4 -0
  5. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/__init__.py +1 -1
  6. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/__main__.py +42 -10
  7. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/application.py +3 -2
  8. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/converter.py +32 -163
  9. markdown_to_confluence-0.4.3/md2conf/domain.py +46 -0
  10. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/drawio.py +49 -0
  11. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/local.py +9 -4
  12. markdown_to_confluence-0.4.3/md2conf/markdown.py +108 -0
  13. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/processor.py +2 -1
  14. markdown_to_confluence-0.4.3/tests/source/table.md +28 -0
  15. markdown_to_confluence-0.4.3/tests/target/table.xml +81 -0
  16. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/test_conversion.py +2 -1
  17. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/test_processor.py +1 -1
  18. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/test_unit.py +8 -1
  19. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/LICENSE +0 -0
  20. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/MANIFEST.in +0 -0
  21. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/markdown_to_confluence.egg-info/dependency_links.txt +0 -0
  22. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/markdown_to_confluence.egg-info/entry_points.txt +0 -0
  23. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/markdown_to_confluence.egg-info/requires.txt +0 -0
  24. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/markdown_to_confluence.egg-info/top_level.txt +0 -0
  25. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/markdown_to_confluence.egg-info/zip-safe +0 -0
  26. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/api.py +0 -0
  27. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/collection.py +0 -0
  28. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/emoji.py +0 -0
  29. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/entities.dtd +0 -0
  30. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/extra.py +0 -0
  31. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/matcher.py +0 -0
  32. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/mermaid.py +0 -0
  33. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/metadata.py +0 -0
  34. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/properties.py +0 -0
  35. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/puppeteer-config.json +0 -0
  36. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/py.typed +0 -0
  37. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/scanner.py +0 -0
  38. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/md2conf/xml.py +0 -0
  39. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/pyproject.toml +0 -0
  40. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/setup.cfg +0 -0
  41. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/setup.py +0 -0
  42. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/__init__.py +0 -0
  43. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/admonition.md +0 -0
  44. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/alert.md +0 -0
  45. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/anchors.md +0 -0
  46. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/basic.md +0 -0
  47. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/code.md +0 -0
  48. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/collapsed.md +0 -0
  49. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/fenced.md +0 -0
  50. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/figure/diagram.drawio +0 -0
  51. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/figure/diagram.drawio.png +0 -0
  52. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/figure/diagram.drawio.svg +0 -0
  53. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/figure/raster.png +0 -0
  54. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/figure/vector.svg +0 -0
  55. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/footnote.md +0 -0
  56. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/ignore.md +0 -0
  57. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/images/images.md +0 -0
  58. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/images.md +0 -0
  59. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/math.md +0 -0
  60. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/mermaid.md +0 -0
  61. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/missing.md +0 -0
  62. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/sections.md +0 -0
  63. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/tags.md +0 -0
  64. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/source/title.md +0 -0
  65. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/target/admonition.xml +0 -0
  66. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/target/alert.xml +0 -0
  67. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/target/anchors.xml +0 -0
  68. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/target/basic.xml +0 -0
  69. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/target/code.xml +0 -0
  70. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/target/collapsed.xml +0 -0
  71. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/target/fenced.xml +0 -0
  72. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/target/footnote.xml +0 -0
  73. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/target/images/images.xml +0 -0
  74. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/target/images.xml +0 -0
  75. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/target/math.xml +0 -0
  76. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/target/mermaid.xml +0 -0
  77. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/target/missing.xml +0 -0
  78. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/target/sections.xml +0 -0
  79. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/target/tags.xml +0 -0
  80. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/test_drawio.py +0 -0
  81. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/test_matcher.py +0 -0
  82. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/test_mermaid.py +0 -0
  83. {markdown_to_confluence-0.4.2 → markdown_to_confluence-0.4.3}/tests/test_scanner.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: markdown-to-confluence
3
- Version: 0.4.2
3
+ Version: 0.4.3
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>
@@ -58,7 +58,7 @@ This Python package
58
58
  * Text with **bold**, *italic*, `monospace`, <ins>underline</ins> and ~~strikethrough~~
59
59
  * Link to [sections on the same page](#getting-started) or [external locations](http://example.com/)
60
60
  * Subscript and superscript (with HTML tags `<sub>` and `<sup>`)
61
- * Math formulas with LaTeX notation [^math]
61
+ * Math formulas with LaTeX notation
62
62
  * Emoji
63
63
  * Ordered and unordered lists
64
64
  * Block quotes
@@ -69,8 +69,8 @@ This Python package
69
69
  * [Table of contents](https://docs.gitlab.com/ee/user/markdown.html#table-of-contents)
70
70
  * [Admonitions](https://python-markdown.github.io/extensions/admonition/) and alert boxes in [GitHub](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) and [GitLab](https://docs.gitlab.com/ee/development/documentation/styleguide/#alert-boxes)
71
71
  * [Collapsed sections](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-collapsed-sections)
72
- * draw\.io diagrams [^drawio]
73
- * [Mermaid diagrams](https://mermaid.live/) in code blocks (converted to images) [^mermaid]
72
+ * draw\.io diagrams
73
+ * [Mermaid diagrams](https://mermaid.live/) in code blocks (converted to images)
74
74
 
75
75
  Whenever possible, the implementation uses [Confluence REST API v2](https://developer.atlassian.com/cloud/confluence/rest/v2/) to fetch space properties, and get, create or update page content.
76
76
 
@@ -84,9 +84,9 @@ pip install markdown-to-confluence
84
84
 
85
85
  ### Command-line utilities
86
86
 
87
- **Optional.** Converting `*.drawio` diagrams into PNG or SVG images requires installing [draw.io](https://www.drawio.com/). (Refer to `--render-drawio`.)
87
+ **Optional.** Converting `*.drawio` diagrams to PNG or SVG images before uploading to Confluence as attachments requires installing [draw.io](https://www.drawio.com/). (Refer to `--render-drawio`.)
88
88
 
89
- **Optional.** Converting code blocks of Mermaid diagrams into PNG or SVG images requires [mermaid-cli](https://github.com/mermaid-js/mermaid-cli). (Refer to `--render-mermaid`.)
89
+ **Optional.** Converting code blocks of Mermaid diagrams to PNG or SVG images before uploading to Confluence as attachments requires [mermaid-cli](https://github.com/mermaid-js/mermaid-cli). (Refer to `--render-mermaid`.)
90
90
 
91
91
  ```sh
92
92
  npm install -g @mermaid-js/mermaid-cli
@@ -98,9 +98,9 @@ As authors of *md2conf*, we don't endorse or support any particular Confluence m
98
98
 
99
99
  **Optional.** Editable draw\.io diagrams require [draw.io Diagrams marketplace app](https://marketplace.atlassian.com/apps/1210933/draw-io-diagrams-uml-bpmn-aws-erd-flowcharts). (Refer to `--no-render-drawio`.)
100
100
 
101
- **Optional.** Displaying Mermaid diagrams in Confluence without pre-rendering requires a marketplace app. (Refer to `--no-render-mermaid`.)
101
+ **Optional.** Displaying Mermaid diagrams in Confluence without pre-rendering in the synchronization phase requires a marketplace app. (Refer to `--no-render-mermaid`.)
102
102
 
103
- **Optional.** Displaying formulas and equations requires [LaTeX Math marketplace app](https://marketplace.atlassian.com/apps/1226109/latex-math-for-confluence-math-formula-equations).
103
+ **Optional.** Displaying formulas and equations in Confluence requires [marketplace app](https://marketplace.atlassian.com/apps/1226109/latex-math-for-confluence-math-formula-equations), refer to [LaTeX Math for Confluence - Math Formula & Equations](https://help.narva.net/latex-math-for-confluence/).
104
104
 
105
105
  ## Getting started
106
106
 
@@ -523,7 +523,3 @@ FROM leventehunyadi/md2conf:latest
523
523
 
524
524
  CMD ["-d", "example.atlassian.net", "-u", "levente.hunyadi@instructure.com", "-a", "0123456789abcdef", "-s", "SPACE", "./"]
525
525
  ```
526
-
527
- [^math]: Requires installing Confluence plugin [LaTeX Math for Confluence - Math Formula & Equations](https://help.narva.net/latex-math-for-confluence/).
528
- [^drawio]: Converting draw\.io diagrams to images before uploading to Confluence requires an installation of [draw.io](https://www.drawio.com/). Editable draw\.io diagrams require separate marketplace app.
529
- [^mermaid]: Converting Mermaid diagrams to images before uploading to Confluence requires [mermaid-cli](https://github.com/mermaid-js/mermaid-cli). Displaying Mermaid diagrams on the fly requires separate marketplace app.
@@ -16,7 +16,7 @@ This Python package
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
18
  * Subscript and superscript (with HTML tags `<sub>` and `<sup>`)
19
- * Math formulas with LaTeX notation [^math]
19
+ * Math formulas with LaTeX notation
20
20
  * Emoji
21
21
  * Ordered and unordered lists
22
22
  * Block quotes
@@ -27,8 +27,8 @@ This Python package
27
27
  * [Table of contents](https://docs.gitlab.com/ee/user/markdown.html#table-of-contents)
28
28
  * [Admonitions](https://python-markdown.github.io/extensions/admonition/) and alert boxes in [GitHub](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) and [GitLab](https://docs.gitlab.com/ee/development/documentation/styleguide/#alert-boxes)
29
29
  * [Collapsed sections](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-collapsed-sections)
30
- * draw\.io diagrams [^drawio]
31
- * [Mermaid diagrams](https://mermaid.live/) in code blocks (converted to images) [^mermaid]
30
+ * draw\.io diagrams
31
+ * [Mermaid diagrams](https://mermaid.live/) in code blocks (converted to images)
32
32
 
33
33
  Whenever possible, the implementation uses [Confluence REST API v2](https://developer.atlassian.com/cloud/confluence/rest/v2/) to fetch space properties, and get, create or update page content.
34
34
 
@@ -42,9 +42,9 @@ pip install markdown-to-confluence
42
42
 
43
43
  ### Command-line utilities
44
44
 
45
- **Optional.** Converting `*.drawio` diagrams into PNG or SVG images requires installing [draw.io](https://www.drawio.com/). (Refer to `--render-drawio`.)
45
+ **Optional.** Converting `*.drawio` diagrams to PNG or SVG images before uploading to Confluence as attachments requires installing [draw.io](https://www.drawio.com/). (Refer to `--render-drawio`.)
46
46
 
47
- **Optional.** Converting code blocks of Mermaid diagrams into PNG or SVG images requires [mermaid-cli](https://github.com/mermaid-js/mermaid-cli). (Refer to `--render-mermaid`.)
47
+ **Optional.** Converting code blocks of Mermaid diagrams to PNG or SVG images before uploading to Confluence as attachments requires [mermaid-cli](https://github.com/mermaid-js/mermaid-cli). (Refer to `--render-mermaid`.)
48
48
 
49
49
  ```sh
50
50
  npm install -g @mermaid-js/mermaid-cli
@@ -56,9 +56,9 @@ As authors of *md2conf*, we don't endorse or support any particular Confluence m
56
56
 
57
57
  **Optional.** Editable draw\.io diagrams require [draw.io Diagrams marketplace app](https://marketplace.atlassian.com/apps/1210933/draw-io-diagrams-uml-bpmn-aws-erd-flowcharts). (Refer to `--no-render-drawio`.)
58
58
 
59
- **Optional.** Displaying Mermaid diagrams in Confluence without pre-rendering requires a marketplace app. (Refer to `--no-render-mermaid`.)
59
+ **Optional.** Displaying Mermaid diagrams in Confluence without pre-rendering in the synchronization phase requires a marketplace app. (Refer to `--no-render-mermaid`.)
60
60
 
61
- **Optional.** Displaying formulas and equations requires [LaTeX Math marketplace app](https://marketplace.atlassian.com/apps/1226109/latex-math-for-confluence-math-formula-equations).
61
+ **Optional.** Displaying formulas and equations in Confluence requires [marketplace app](https://marketplace.atlassian.com/apps/1226109/latex-math-for-confluence-math-formula-equations), refer to [LaTeX Math for Confluence - Math Formula & Equations](https://help.narva.net/latex-math-for-confluence/).
62
62
 
63
63
  ## Getting started
64
64
 
@@ -481,7 +481,3 @@ FROM leventehunyadi/md2conf:latest
481
481
 
482
482
  CMD ["-d", "example.atlassian.net", "-u", "levente.hunyadi@instructure.com", "-a", "0123456789abcdef", "-s", "SPACE", "./"]
483
483
  ```
484
-
485
- [^math]: Requires installing Confluence plugin [LaTeX Math for Confluence - Math Formula & Equations](https://help.narva.net/latex-math-for-confluence/).
486
- [^drawio]: Converting draw\.io diagrams to images before uploading to Confluence requires an installation of [draw.io](https://www.drawio.com/). Editable draw\.io diagrams require separate marketplace app.
487
- [^mermaid]: Converting Mermaid diagrams to images before uploading to Confluence requires [mermaid-cli](https://github.com/mermaid-js/mermaid-cli). Displaying Mermaid diagrams on the fly requires separate marketplace app.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: markdown-to-confluence
3
- Version: 0.4.2
3
+ Version: 0.4.3
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>
@@ -58,7 +58,7 @@ This Python package
58
58
  * Text with **bold**, *italic*, `monospace`, <ins>underline</ins> and ~~strikethrough~~
59
59
  * Link to [sections on the same page](#getting-started) or [external locations](http://example.com/)
60
60
  * Subscript and superscript (with HTML tags `<sub>` and `<sup>`)
61
- * Math formulas with LaTeX notation [^math]
61
+ * Math formulas with LaTeX notation
62
62
  * Emoji
63
63
  * Ordered and unordered lists
64
64
  * Block quotes
@@ -69,8 +69,8 @@ This Python package
69
69
  * [Table of contents](https://docs.gitlab.com/ee/user/markdown.html#table-of-contents)
70
70
  * [Admonitions](https://python-markdown.github.io/extensions/admonition/) and alert boxes in [GitHub](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) and [GitLab](https://docs.gitlab.com/ee/development/documentation/styleguide/#alert-boxes)
71
71
  * [Collapsed sections](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-collapsed-sections)
72
- * draw\.io diagrams [^drawio]
73
- * [Mermaid diagrams](https://mermaid.live/) in code blocks (converted to images) [^mermaid]
72
+ * draw\.io diagrams
73
+ * [Mermaid diagrams](https://mermaid.live/) in code blocks (converted to images)
74
74
 
75
75
  Whenever possible, the implementation uses [Confluence REST API v2](https://developer.atlassian.com/cloud/confluence/rest/v2/) to fetch space properties, and get, create or update page content.
76
76
 
@@ -84,9 +84,9 @@ pip install markdown-to-confluence
84
84
 
85
85
  ### Command-line utilities
86
86
 
87
- **Optional.** Converting `*.drawio` diagrams into PNG or SVG images requires installing [draw.io](https://www.drawio.com/). (Refer to `--render-drawio`.)
87
+ **Optional.** Converting `*.drawio` diagrams to PNG or SVG images before uploading to Confluence as attachments requires installing [draw.io](https://www.drawio.com/). (Refer to `--render-drawio`.)
88
88
 
89
- **Optional.** Converting code blocks of Mermaid diagrams into PNG or SVG images requires [mermaid-cli](https://github.com/mermaid-js/mermaid-cli). (Refer to `--render-mermaid`.)
89
+ **Optional.** Converting code blocks of Mermaid diagrams to PNG or SVG images before uploading to Confluence as attachments requires [mermaid-cli](https://github.com/mermaid-js/mermaid-cli). (Refer to `--render-mermaid`.)
90
90
 
91
91
  ```sh
92
92
  npm install -g @mermaid-js/mermaid-cli
@@ -98,9 +98,9 @@ As authors of *md2conf*, we don't endorse or support any particular Confluence m
98
98
 
99
99
  **Optional.** Editable draw\.io diagrams require [draw.io Diagrams marketplace app](https://marketplace.atlassian.com/apps/1210933/draw-io-diagrams-uml-bpmn-aws-erd-flowcharts). (Refer to `--no-render-drawio`.)
100
100
 
101
- **Optional.** Displaying Mermaid diagrams in Confluence without pre-rendering requires a marketplace app. (Refer to `--no-render-mermaid`.)
101
+ **Optional.** Displaying Mermaid diagrams in Confluence without pre-rendering in the synchronization phase requires a marketplace app. (Refer to `--no-render-mermaid`.)
102
102
 
103
- **Optional.** Displaying formulas and equations requires [LaTeX Math marketplace app](https://marketplace.atlassian.com/apps/1226109/latex-math-for-confluence-math-formula-equations).
103
+ **Optional.** Displaying formulas and equations in Confluence requires [marketplace app](https://marketplace.atlassian.com/apps/1226109/latex-math-for-confluence-math-formula-equations), refer to [LaTeX Math for Confluence - Math Formula & Equations](https://help.narva.net/latex-math-for-confluence/).
104
104
 
105
105
  ## Getting started
106
106
 
@@ -523,7 +523,3 @@ FROM leventehunyadi/md2conf:latest
523
523
 
524
524
  CMD ["-d", "example.atlassian.net", "-u", "levente.hunyadi@instructure.com", "-a", "0123456789abcdef", "-s", "SPACE", "./"]
525
525
  ```
526
-
527
- [^math]: Requires installing Confluence plugin [LaTeX Math for Confluence - Math Formula & Equations](https://help.narva.net/latex-math-for-confluence/).
528
- [^drawio]: Converting draw\.io diagrams to images before uploading to Confluence requires an installation of [draw.io](https://www.drawio.com/). Editable draw\.io diagrams require separate marketplace app.
529
- [^mermaid]: Converting Mermaid diagrams to images before uploading to Confluence requires [mermaid-cli](https://github.com/mermaid-js/mermaid-cli). Displaying Mermaid diagrams on the fly requires separate marketplace app.
@@ -16,11 +16,13 @@ md2conf/api.py
16
16
  md2conf/application.py
17
17
  md2conf/collection.py
18
18
  md2conf/converter.py
19
+ md2conf/domain.py
19
20
  md2conf/drawio.py
20
21
  md2conf/emoji.py
21
22
  md2conf/entities.dtd
22
23
  md2conf/extra.py
23
24
  md2conf/local.py
25
+ md2conf/markdown.py
24
26
  md2conf/matcher.py
25
27
  md2conf/mermaid.py
26
28
  md2conf/metadata.py
@@ -52,6 +54,7 @@ tests/source/math.md
52
54
  tests/source/mermaid.md
53
55
  tests/source/missing.md
54
56
  tests/source/sections.md
57
+ tests/source/table.md
55
58
  tests/source/tags.md
56
59
  tests/source/title.md
57
60
  tests/source/figure/diagram.drawio
@@ -73,5 +76,6 @@ tests/target/math.xml
73
76
  tests/target/mermaid.xml
74
77
  tests/target/missing.xml
75
78
  tests/target/sections.xml
79
+ tests/target/table.xml
76
80
  tests/target/tags.xml
77
81
  tests/target/images/images.xml
@@ -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.2"
8
+ __version__ = "0.4.3"
9
9
  __author__ = "Levente Hunyadi"
10
10
  __copyright__ = "Copyright 2022-2025, Levente Hunyadi"
11
11
  __license__ = "MIT"
@@ -17,14 +17,9 @@ import typing
17
17
  from pathlib import Path
18
18
  from typing import Any, Iterable, Literal, Optional, Sequence, Union
19
19
 
20
- import requests
21
-
22
20
  from . import __version__
23
- from .api import ConfluenceAPI
24
- from .application import Application
25
- from .converter import ConfluenceDocumentOptions, ConfluencePageID
21
+ from .domain import ConfluenceDocumentOptions, ConfluencePageID
26
22
  from .extra import override
27
- from .local import LocalConverter
28
23
  from .metadata import ConfluenceSiteMetadata
29
24
  from .properties import ArgumentError, ConfluenceConnectionProperties, ConfluenceSiteProperties
30
25
 
@@ -52,7 +47,7 @@ class Arguments(argparse.Namespace):
52
47
 
53
48
 
54
49
  class KwargsAppendAction(argparse.Action):
55
- """Append key-value pairs to a dictionary"""
50
+ """Append key-value pairs to a dictionary."""
56
51
 
57
52
  @override
58
53
  def __call__(
@@ -72,6 +67,30 @@ class KwargsAppendAction(argparse.Action):
72
67
  setattr(namespace, self.dest, d)
73
68
 
74
69
 
70
+ def unsupported(prefer: str) -> type[argparse.Action]:
71
+ class UnsupportedAction(argparse.Action):
72
+ """Display an error for unsupported command-line options."""
73
+
74
+ @override
75
+ def __call__(
76
+ self,
77
+ parser: argparse.ArgumentParser,
78
+ namespace: argparse.Namespace,
79
+ values: Union[None, str, Sequence[Any]],
80
+ option_string: Optional[str] = None,
81
+ ) -> None:
82
+ raise argparse.ArgumentError(
83
+ self,
84
+ f"this command-line option is no longer supported, use `--{prefer}`",
85
+ )
86
+
87
+ @override
88
+ def __repr__(self) -> str:
89
+ return f"{unsupported.__name__}({repr(prefer)})"
90
+
91
+ return UnsupportedAction
92
+
93
+
75
94
  class PositionalOnlyHelpFormatter(argparse.HelpFormatter):
76
95
  def _format_usage(
77
96
  self,
@@ -189,12 +208,18 @@ def main() -> None:
189
208
  help="Inline Mermaid diagram in Confluence page. (Marketplace app required.)",
190
209
  )
191
210
  parser.add_argument(
192
- "--render-mermaid-format",
211
+ "--diagram-output-format",
193
212
  dest="diagram_output_format",
194
213
  choices=["png", "svg"],
195
214
  default="png",
196
215
  help="Format for rendering Mermaid and draw.io diagrams (default: 'png').",
197
216
  )
217
+ parser.add_argument(
218
+ "--render-mermaid-format",
219
+ action=unsupported("diagram-output-format"),
220
+ metavar="FORMAT",
221
+ help="Format for rendering Mermaid diagrams (default: 'png').",
222
+ )
198
223
  parser.add_argument(
199
224
  "--heading-anchors",
200
225
  action="store_true",
@@ -256,6 +281,8 @@ def main() -> None:
256
281
  webui_links=args.webui_links,
257
282
  )
258
283
  if args.local:
284
+ from .local import LocalConverter
285
+
259
286
  try:
260
287
  site_properties = ConfluenceSiteProperties(
261
288
  domain=args.domain,
@@ -271,6 +298,11 @@ def main() -> None:
271
298
  )
272
299
  LocalConverter(options, site_metadata).process(args.mdpath)
273
300
  else:
301
+ from requests import HTTPError, JSONDecodeError
302
+
303
+ from .api import ConfluenceAPI
304
+ from .application import Application
305
+
274
306
  try:
275
307
  properties = ConfluenceConnectionProperties(
276
308
  api_url=args.api_url,
@@ -289,14 +321,14 @@ def main() -> None:
289
321
  api,
290
322
  options,
291
323
  ).process(args.mdpath)
292
- except requests.exceptions.HTTPError as err:
324
+ except HTTPError as err:
293
325
  logging.error(err)
294
326
 
295
327
  # print details for a response with JSON body
296
328
  if err.response is not None:
297
329
  try:
298
330
  logging.error(err.response.json())
299
- except requests.exceptions.JSONDecodeError:
331
+ except JSONDecodeError:
300
332
  pass
301
333
 
302
334
  sys.exit(1)
@@ -11,7 +11,8 @@ from pathlib import Path
11
11
  from typing import Optional
12
12
 
13
13
  from .api import ConfluenceContentProperty, ConfluenceLabel, ConfluenceSession, ConfluenceStatus
14
- from .converter import ConfluenceDocument, ConfluenceDocumentOptions, ConfluencePageID, attachment_name, elements_from_string, get_volatile_attributes
14
+ from .converter import ConfluenceDocument, attachment_name, elements_from_string, get_volatile_attributes
15
+ from .domain import ConfluenceDocumentOptions, ConfluencePageID
15
16
  from .extra import override, path_relative_to
16
17
  from .metadata import ConfluencePageMetadata
17
18
  from .processor import Converter, DocumentNode, Processor, ProcessorFactory
@@ -158,7 +159,7 @@ class SynchronizingProcessor(Processor):
158
159
  ):
159
160
  self.api.update_page(page_id.page_id, content, title=title, version=page.version.number + 1)
160
161
  else:
161
- LOGGER.info("Up-to-date page: %s", page_id)
162
+ LOGGER.info("Up-to-date page: %s", page_id.page_id)
162
163
 
163
164
  if document.labels is not None:
164
165
  self.api.update_labels(
@@ -8,28 +8,27 @@ Copyright 2022-2025, Levente Hunyadi
8
8
 
9
9
  # mypy: disable-error-code="dict-item"
10
10
 
11
+ import dataclasses
11
12
  import hashlib
12
13
  import importlib.resources as resources
13
14
  import logging
14
15
  import os.path
15
16
  import re
16
17
  import uuid
17
- import xml.etree.ElementTree
18
18
  from dataclasses import dataclass
19
19
  from pathlib import Path
20
20
  from typing import Any, Literal, Optional, Union
21
21
  from urllib.parse import ParseResult, quote_plus, urlparse, urlunparse
22
22
 
23
23
  import lxml.etree as ET
24
- import markdown
25
24
  from lxml.builder import ElementMaker
26
25
  from strong_typing.core import JsonType
27
26
 
28
- from md2conf.drawio import extract_diagram
29
-
27
+ from . import drawio, mermaid
30
28
  from .collection import ConfluencePageCollection
29
+ from .domain import ConfluenceDocumentOptions, ConfluencePageID
31
30
  from .extra import path_relative_to
32
- from .mermaid import render_diagram
31
+ from .markdown import markdown_to_html
33
32
  from .metadata import ConfluenceSiteMetadata
34
33
  from .properties import PageError
35
34
  from .scanner import ScannedDocument, Scanner
@@ -101,90 +100,6 @@ def encode_title(text: str) -> str:
101
100
  return quote_plus(text.strip())
102
101
 
103
102
 
104
- def emoji_generator(
105
- index: str,
106
- shortname: str,
107
- alias: Optional[str],
108
- uc: Optional[str],
109
- alt: str,
110
- title: Optional[str],
111
- category: Optional[str],
112
- options: dict[str, Any],
113
- md: markdown.Markdown,
114
- ) -> xml.etree.ElementTree.Element:
115
- """
116
- Custom generator for `pymdownx.emoji`.
117
- """
118
-
119
- name = (alias or shortname).strip(":")
120
- span = xml.etree.ElementTree.Element("span", {"data-emoji-shortname": name})
121
- if uc is not None:
122
- span.attrib["data-emoji-unicode"] = uc
123
-
124
- # convert series of Unicode code point hexadecimal values into characters
125
- span.text = "".join(chr(int(item, base=16)) for item in uc.split("-"))
126
- else:
127
- span.text = alt
128
- return span
129
-
130
-
131
- def math_formatter(
132
- source: str,
133
- language: str,
134
- css_class: str,
135
- options: dict[str, Any],
136
- md: markdown.Markdown,
137
- classes: Optional[list[str]] = None,
138
- id_value: str = "",
139
- attrs: Optional[dict[str, str]] = None,
140
- **kwargs: Any,
141
- ) -> str:
142
- """
143
- Custom formatter for language `math` in `pymdownx.superfences`.
144
- """
145
-
146
- if classes is None:
147
- classes = [css_class]
148
- else:
149
- classes.insert(0, css_class)
150
-
151
- html_id = f' id="{id_value}"' if id_value else ""
152
- html_class = ' class="{}"'.format(" ".join(classes))
153
- html_attrs = " " + " ".join(f'{k}="{v}"' for k, v in attrs.items()) if attrs else ""
154
-
155
- return f"<div{html_id}{html_class}{html_attrs}>{source}</div>"
156
-
157
-
158
- def markdown_to_html(content: str) -> str:
159
- return markdown.markdown(
160
- content,
161
- extensions=[
162
- "admonition",
163
- "footnotes",
164
- "markdown.extensions.tables",
165
- "md_in_html",
166
- "pymdownx.arithmatex",
167
- "pymdownx.emoji",
168
- "pymdownx.highlight", # required by `pymdownx.superfences`
169
- "pymdownx.magiclink",
170
- "pymdownx.superfences",
171
- "pymdownx.tilde",
172
- "sane_lists",
173
- ],
174
- extension_configs={
175
- "footnotes": {"BACKLINK_TITLE": ""},
176
- "pymdownx.arithmatex": {"generic": True, "preview": False, "tex_inline_wrap": ["", ""], "tex_block_wrap": ["", ""]},
177
- "pymdownx.emoji": {
178
- "emoji_generator": emoji_generator,
179
- },
180
- "pymdownx.highlight": {
181
- "use_pygments": False,
182
- },
183
- "pymdownx.superfences": {"custom_fences": [{"name": "math", "class": "arithmatex", "format": math_formatter}]},
184
- },
185
- )
186
-
187
-
188
103
  def _elements_from_strings(dtd_path: Path, items: list[str]) -> ET._Element:
189
104
  """
190
105
  Creates a fragment of several XML nodes from their string representation wrapped in a root element.
@@ -333,8 +248,8 @@ def title_to_identifier(title: str) -> str:
333
248
  "Converts a section heading title to a GitHub-style Markdown same-page anchor."
334
249
 
335
250
  s = title.strip().lower()
336
- s = re.sub("[^ A-Za-z0-9]", "", s)
337
- s = s.replace(" ", "-")
251
+ s = re.sub(r"[^\sA-Za-z0-9_\-]", "", s)
252
+ s = re.sub(r"\s+", "-", s)
338
253
  return s
339
254
 
340
255
 
@@ -594,9 +509,7 @@ class ConfluenceStorageFormatConverter(NodeVisitor):
594
509
  if absolute_path.name.endswith(".drawio.png") or absolute_path.name.endswith(".drawio.svg"):
595
510
  return self._transform_drawio_image(absolute_path, attrs)
596
511
  elif absolute_path.name.endswith(".drawio.xml") or absolute_path.name.endswith(".drawio"):
597
- self.images.append(absolute_path)
598
- image_filename = attachment_name(path_relative_to(absolute_path, self.base_dir))
599
- return self._create_drawio(image_filename, attrs)
512
+ return self._transform_drawio(absolute_path, attrs)
600
513
  else:
601
514
  return self._transform_attached_image(absolute_path, attrs)
602
515
 
@@ -651,10 +564,28 @@ class ConfluenceStorageFormatConverter(NodeVisitor):
651
564
  absolute_path = png_file
652
565
 
653
566
  self.images.append(absolute_path)
654
- return self._create_image(absolute_path, attrs)
567
+ image_name = attachment_name(path_relative_to(absolute_path, self.base_dir))
568
+ return self._create_attached_image(image_name, attrs)
569
+
570
+ def _transform_drawio(self, absolute_path: Path, attrs: ImageAttributes) -> ET._Element:
571
+ "Emits Confluence Storage Format XHTML for a draw.io diagram."
572
+
573
+ if not absolute_path.name.endswith(".drawio.xml") and not absolute_path.name.endswith(".drawio"):
574
+ raise DocumentError("invalid image format; expected: `*.drawio.xml` or `*.drawio`")
575
+
576
+ if self.options.render_drawio:
577
+ image_data = drawio.render_diagram(absolute_path, self.options.diagram_output_format)
578
+ image_hash = hashlib.md5(image_data).hexdigest()
579
+ image_filename = attachment_name(f"embedded_{image_hash}.{self.options.diagram_output_format}")
580
+ self.embedded_images[image_filename] = image_data
581
+ return self._create_attached_image(image_filename, attrs)
582
+ else:
583
+ self.images.append(absolute_path)
584
+ image_filename = attachment_name(path_relative_to(absolute_path, self.base_dir))
585
+ return self._create_drawio(image_filename, attrs)
655
586
 
656
587
  def _transform_drawio_image(self, absolute_path: Path, attrs: ImageAttributes) -> ET._Element:
657
- "Emits Confluence Storage Format XHTML for a draw.io image."
588
+ "Emits Confluence Storage Format XHTML for a draw.io diagram embedded in a PNG or SVG image."
658
589
 
659
590
  if not absolute_path.name.endswith(".drawio.png") and not absolute_path.name.endswith(".drawio.svg"):
660
591
  raise DocumentError("invalid image format; expected: `*.drawio.png` or `*.drawio.svg`")
@@ -663,17 +594,15 @@ class ConfluenceStorageFormatConverter(NodeVisitor):
663
594
  return self._transform_attached_image(absolute_path, attrs)
664
595
  else:
665
596
  # extract embedded editable diagram and upload as *.drawio
666
- image_data = extract_diagram(absolute_path)
597
+ image_data = drawio.extract_diagram(absolute_path)
667
598
  image_filename = attachment_name(path_relative_to(absolute_path.with_suffix(".xml"), self.base_dir))
668
599
  self.embedded_images[image_filename] = image_data
669
600
 
670
601
  return self._create_drawio(image_filename, attrs)
671
602
 
672
- def _create_image(self, absolute_path: Path, attrs: ImageAttributes) -> ET._Element:
603
+ def _create_attached_image(self, image_name: str, attrs: ImageAttributes) -> ET._Element:
673
604
  "An image embedded into the page, linking to an attachment."
674
605
 
675
- image_name = attachment_name(path_relative_to(absolute_path, self.base_dir))
676
-
677
606
  attributes: dict[str, Any] = {
678
607
  ET.QName(namespaces["ac"], "align"): "center",
679
608
  ET.QName(namespaces["ac"], "layout"): "center",
@@ -803,21 +732,11 @@ class ConfluenceStorageFormatConverter(NodeVisitor):
803
732
  "Transforms a Mermaid diagram code block."
804
733
 
805
734
  if self.options.render_mermaid:
806
- image_data = render_diagram(content, self.options.diagram_output_format)
735
+ image_data = mermaid.render_diagram(content, self.options.diagram_output_format)
807
736
  image_hash = hashlib.md5(image_data).hexdigest()
808
737
  image_filename = attachment_name(f"embedded_{image_hash}.{self.options.diagram_output_format}")
809
738
  self.embedded_images[image_filename] = image_data
810
- return AC(
811
- "image",
812
- {
813
- ET.QName(namespaces["ac"], "align"): "center",
814
- ET.QName(namespaces["ac"], "layout"): "center",
815
- },
816
- RI(
817
- "attachment",
818
- {ET.QName(namespaces["ri"], "filename"): image_filename},
819
- ),
820
- )
739
+ return self._create_attached_image(image_filename, ImageAttributes(None, None, None))
821
740
  else:
822
741
  local_id = str(uuid.uuid4())
823
742
  macro_id = str(uuid.uuid4())
@@ -1388,48 +1307,6 @@ class DocumentError(RuntimeError):
1388
1307
  "Raised when a converted Markdown document has an unexpected element or attribute."
1389
1308
 
1390
1309
 
1391
- @dataclass
1392
- class ConfluencePageID:
1393
- page_id: str
1394
-
1395
-
1396
- @dataclass
1397
- class ConfluenceQualifiedID:
1398
- page_id: str
1399
- space_key: str
1400
-
1401
-
1402
- @dataclass
1403
- class ConfluenceDocumentOptions:
1404
- """
1405
- Options that control the generated page content.
1406
-
1407
- :param ignore_invalid_url: When true, ignore invalid URLs in input, emit a warning and replace the anchor with
1408
- plain text; when false, raise an exception.
1409
- :param heading_anchors: When true, emit a structured macro *anchor* for each section heading using GitHub
1410
- conversion rules for the identifier.
1411
- :param generated_by: Text to use as the generated-by prompt (or `None` to omit a prompt).
1412
- :param root_page_id: Confluence page to assume root page role for publishing a directory of Markdown files.
1413
- :param keep_hierarchy: Whether to maintain source directory structure when exporting to Confluence.
1414
- :param prefer_raster: Whether to choose PNG files over SVG files when available.
1415
- :param render_drawio: Whether to pre-render (or use the pre-rendered version of) draw.io diagrams.
1416
- :param render_mermaid: Whether to pre-render Mermaid diagrams into PNG/SVG images.
1417
- :param diagram_output_format: Target image format for diagrams.
1418
- :param webui_links: When true, convert relative URLs to Confluence Web UI links.
1419
- """
1420
-
1421
- ignore_invalid_url: bool = False
1422
- heading_anchors: bool = False
1423
- generated_by: Optional[str] = "This page has been generated with a tool."
1424
- root_page_id: Optional[ConfluencePageID] = None
1425
- keep_hierarchy: bool = False
1426
- prefer_raster: bool = True
1427
- render_drawio: bool = False
1428
- render_mermaid: bool = False
1429
- diagram_output_format: Literal["png", "svg"] = "png"
1430
- webui_links: bool = False
1431
-
1432
-
1433
1310
  class ConversionError(RuntimeError):
1434
1311
  "Raised when a Markdown document cannot be converted to Confluence Storage Format."
1435
1312
 
@@ -1507,15 +1384,7 @@ class ConfluenceDocument:
1507
1384
  raise ConversionError(path) from ex
1508
1385
 
1509
1386
  converter = ConfluenceStorageFormatConverter(
1510
- ConfluenceConverterOptions(
1511
- ignore_invalid_url=self.options.ignore_invalid_url,
1512
- heading_anchors=self.options.heading_anchors,
1513
- prefer_raster=self.options.prefer_raster,
1514
- render_drawio=self.options.render_drawio,
1515
- render_mermaid=self.options.render_mermaid,
1516
- diagram_output_format=self.options.diagram_output_format,
1517
- webui_links=self.options.webui_links,
1518
- ),
1387
+ ConfluenceConverterOptions(**{field.name: getattr(self.options, field.name) for field in dataclasses.fields(ConfluenceConverterOptions)}),
1519
1388
  path,
1520
1389
  root_dir,
1521
1390
  site_metadata,