markdown-to-confluence 0.4.3__py3-none-any.whl → 0.4.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {markdown_to_confluence-0.4.3.dist-info → markdown_to_confluence-0.4.5.dist-info}/METADATA +104 -25
- markdown_to_confluence-0.4.5.dist-info/RECORD +33 -0
- {markdown_to_confluence-0.4.3.dist-info → markdown_to_confluence-0.4.5.dist-info}/licenses/LICENSE +1 -1
- md2conf/__init__.py +1 -1
- md2conf/__main__.py +19 -4
- md2conf/api.py +9 -1
- md2conf/application.py +16 -8
- md2conf/converter.py +835 -579
- md2conf/csf.py +217 -0
- md2conf/domain.py +2 -0
- md2conf/drawio.py +18 -14
- md2conf/latex.py +245 -0
- md2conf/local.py +2 -2
- md2conf/markdown.py +19 -11
- md2conf/mermaid.py +21 -27
- md2conf/text.py +54 -0
- md2conf/toc.py +89 -0
- md2conf/uri.py +46 -0
- md2conf/xml.py +84 -14
- markdown_to_confluence-0.4.3.dist-info/RECORD +0 -29
- md2conf/emoji.py +0 -83
- {markdown_to_confluence-0.4.3.dist-info → markdown_to_confluence-0.4.5.dist-info}/WHEEL +0 -0
- {markdown_to_confluence-0.4.3.dist-info → markdown_to_confluence-0.4.5.dist-info}/entry_points.txt +0 -0
- {markdown_to_confluence-0.4.3.dist-info → markdown_to_confluence-0.4.5.dist-info}/top_level.txt +0 -0
- {markdown_to_confluence-0.4.3.dist-info → markdown_to_confluence-0.4.5.dist-info}/zip-safe +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: markdown-to-confluence
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.5
|
|
4
4
|
Summary: Publish Markdown files to Confluence wiki
|
|
5
5
|
Author-email: Levente Hunyadi <hunyadi@gmail.com>
|
|
6
6
|
Maintainer-email: Levente Hunyadi <hunyadi@gmail.com>
|
|
@@ -23,13 +23,13 @@ Classifier: Typing :: Typed
|
|
|
23
23
|
Requires-Python: >=3.9
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
License-File: LICENSE
|
|
26
|
-
Requires-Dist: json_strong_typing>=0.
|
|
26
|
+
Requires-Dist: json_strong_typing>=0.4
|
|
27
27
|
Requires-Dist: lxml>=6.0
|
|
28
28
|
Requires-Dist: markdown>=3.8
|
|
29
29
|
Requires-Dist: pymdown-extensions>=10.16
|
|
30
30
|
Requires-Dist: PyYAML>=6.0
|
|
31
31
|
Requires-Dist: requests>=2.32
|
|
32
|
-
Requires-Dist:
|
|
32
|
+
Requires-Dist: typing-extensions>=4.14; python_version < "3.12"
|
|
33
33
|
Provides-Extra: dev
|
|
34
34
|
Requires-Dist: markdown_doc>=0.1.4; python_version >= "3.10" and extra == "dev"
|
|
35
35
|
Requires-Dist: types-lxml>=2025.3.30; extra == "dev"
|
|
@@ -38,6 +38,8 @@ Requires-Dist: types-PyYAML>=6.0; extra == "dev"
|
|
|
38
38
|
Requires-Dist: types-requests>=2.32; extra == "dev"
|
|
39
39
|
Requires-Dist: mypy>=1.16; extra == "dev"
|
|
40
40
|
Requires-Dist: ruff>=0.12; extra == "dev"
|
|
41
|
+
Provides-Extra: formulas
|
|
42
|
+
Requires-Dist: matplotlib>=3.9; extra == "formulas"
|
|
41
43
|
Dynamic: license-file
|
|
42
44
|
|
|
43
45
|
# Publish Markdown files to Confluence wiki
|
|
@@ -57,7 +59,7 @@ This Python package
|
|
|
57
59
|
* Sections and subsections
|
|
58
60
|
* Text with **bold**, *italic*, `monospace`, <ins>underline</ins> and ~~strikethrough~~
|
|
59
61
|
* Link to [sections on the same page](#getting-started) or [external locations](http://example.com/)
|
|
60
|
-
* Subscript and superscript
|
|
62
|
+
* Subscript and superscript
|
|
61
63
|
* Math formulas with LaTeX notation
|
|
62
64
|
* Emoji
|
|
63
65
|
* Ordered and unordered lists
|
|
@@ -69,8 +71,10 @@ This Python package
|
|
|
69
71
|
* [Table of contents](https://docs.gitlab.com/ee/user/markdown.html#table-of-contents)
|
|
70
72
|
* [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
73
|
* [Collapsed sections](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-collapsed-sections)
|
|
74
|
+
* [Tasklists](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/about-tasklists)
|
|
72
75
|
* draw\.io diagrams
|
|
73
|
-
* [Mermaid diagrams](https://mermaid.live/)
|
|
76
|
+
* [Mermaid diagrams](https://mermaid.live/)
|
|
77
|
+
* Confluence status labels and date widget
|
|
74
78
|
|
|
75
79
|
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
80
|
|
|
@@ -92,13 +96,19 @@ pip install markdown-to-confluence
|
|
|
92
96
|
npm install -g @mermaid-js/mermaid-cli
|
|
93
97
|
```
|
|
94
98
|
|
|
99
|
+
**Optional.** Converting formulas and equations to PNG or SVG images requires [Matplotlib](https://matplotlib.org/):
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
pip install matplotlib
|
|
103
|
+
```
|
|
104
|
+
|
|
95
105
|
### Marketplace apps
|
|
96
106
|
|
|
97
107
|
As authors of *md2conf*, we don't endorse or support any particular Confluence marketplace apps.
|
|
98
108
|
|
|
99
109
|
**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
110
|
|
|
101
|
-
**Optional.** Displaying Mermaid diagrams in Confluence without pre-rendering in the synchronization phase requires a marketplace app. (Refer to `--no-render-mermaid`.)
|
|
111
|
+
**Optional.** Displaying Mermaid diagrams in Confluence without pre-rendering in the synchronization phase requires a [marketplace app](https://marketplace.atlassian.com/apps/1226567/mermaid-diagrams-for-confluence). (Refer to `--no-render-mermaid`.)
|
|
102
112
|
|
|
103
113
|
**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
114
|
|
|
@@ -250,6 +260,12 @@ Root page
|
|
|
250
260
|
└── Ethical considerations
|
|
251
261
|
```
|
|
252
262
|
|
|
263
|
+
### Subscript and superscript
|
|
264
|
+
|
|
265
|
+
Subscripts may either use the character *tilde* (e.g. `CH~3~CH~2~OH`) or the HTML tag `<sub>`.
|
|
266
|
+
|
|
267
|
+
Superscripts may either use the character *caret* (e.g. `e^-ix^`) or the HTML tag `<sup>`.
|
|
268
|
+
|
|
253
269
|
### Emoji
|
|
254
270
|
|
|
255
271
|
The short name notation `:smile:` in a Markdown document is converted into the corresponding emoji 😄 when publishing to Confluence.
|
|
@@ -276,10 +292,12 @@ Highlight in <span style="background-color: rgb(198,237,251);">teal</span>, <spa
|
|
|
276
292
|
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>.
|
|
277
293
|
```
|
|
278
294
|
|
|
295
|
+
Highlighting is also supported via `==marks==`. However, the background color is not customizable.
|
|
296
|
+
|
|
279
297
|
The following table shows standard text colors (CSS `color`) that are available via Confluence UI:
|
|
280
298
|
|
|
281
299
|
| Color name | CSS attribute value |
|
|
282
|
-
|
|
|
300
|
+
| :------------ | :------------------ |
|
|
283
301
|
| bold blue | rgb(7,71,166) |
|
|
284
302
|
| blue | rgb(76,154,255) |
|
|
285
303
|
| subtle blue | rgb(179,212,255) |
|
|
@@ -340,6 +358,47 @@ $$\int _{a}^{b}f(x)dx=F(b)-F(a)$$
|
|
|
340
358
|
|
|
341
359
|
Displaying math formulas in Confluence requires the extension [LaTeX Math for Confluence - Math Formula & Equations](https://help.narva.net/latex-math-for-confluence/).
|
|
342
360
|
|
|
361
|
+
### HTML in Markdown
|
|
362
|
+
|
|
363
|
+
*md2conf* relays HTML elements nested in Markdown content to Confluence (such as `e<sup>x</sup>` for superscript). However, Confluence uses an extension of XHTML, i.e. the content must qualify as valid XML too. In particular, unterminated tags (e.g. `<br>` or `<img ...>`) or inconsistent nesting (e.g. `<b><i></b></i>`) are not permitted, and will raise an XML parsing error. When an HTML element has no content such as `<br>` or `<img>`, use a self-closing tag:
|
|
364
|
+
|
|
365
|
+
```html
|
|
366
|
+
<br/>
|
|
367
|
+
<img src="image.png" width="24" height="24" />
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Confluence widgets
|
|
371
|
+
|
|
372
|
+
*md2conf* supports some Confluence widgets. If the appropriate code is found when a Markdown document is processed, it is automatically replaced with Confluence Storage Format XML that produces the corresponding widget.
|
|
373
|
+
|
|
374
|
+
| Markdown code | Confluence equivalent |
|
|
375
|
+
| :----------------------------------------- | :------------------------------------------------------ |
|
|
376
|
+
| `[[_TOC_]]` | table of contents (based on headings) |
|
|
377
|
+
| `[[_LISTING_]]` | child pages (of current page) |
|
|
378
|
+
| `![My label][STATUS-GRAY]` | gray status label (with specified label text) |
|
|
379
|
+
| `![My label][STATUS-PURPLE]` | purple status label |
|
|
380
|
+
| `![My label][STATUS-BLUE]` | blue status label |
|
|
381
|
+
| `![My label][STATUS-RED]` | red status label |
|
|
382
|
+
| `![My label][STATUS-YELLOW]` | yellow status label |
|
|
383
|
+
| `![My label][STATUS-GREEN]` | green status label |
|
|
384
|
+
| `<input type="date" value="YYYY-MM-DD" />` | date widget (with year, month and day set as specified) |
|
|
385
|
+
|
|
386
|
+
Use the pseudo-language `csf` in a Markdown code block to pass content directly to Confluence. The content must be a single XML node that conforms to Confluence Storage Format (typically an `ac:structured-macro`) but is otherwise not validated. The following example shows how to create a panel similar to an *info panel* but with custom background color and emoji. Notice that `ac:rich-text-body` uses XHTML, not Markdown.
|
|
387
|
+
|
|
388
|
+
````md
|
|
389
|
+
```csf
|
|
390
|
+
<ac:structured-macro ac:name="panel" ac:schema-version="1">
|
|
391
|
+
<ac:parameter ac:name="panelIcon">:slight_smile:</ac:parameter>
|
|
392
|
+
<ac:parameter ac:name="panelIconId">1f642</ac:parameter>
|
|
393
|
+
<ac:parameter ac:name="panelIconText">🙂</ac:parameter>
|
|
394
|
+
<ac:parameter ac:name="bgColor">#FFF0B3</ac:parameter>
|
|
395
|
+
<ac:rich-text-body>
|
|
396
|
+
<p>A <em>custom colored panel</em> with a 🙂 emoji</p>
|
|
397
|
+
</ac:rich-text-body>
|
|
398
|
+
</ac:structured-macro>
|
|
399
|
+
```
|
|
400
|
+
````
|
|
401
|
+
|
|
343
402
|
### Ignoring files
|
|
344
403
|
|
|
345
404
|
Skip files in a directory with rules defined in `.mdignore`. Each rule should occupy a single line. Rules follow the syntax (and constraints) of [fnmatch](https://docs.python.org/3/library/fnmatch.html#fnmatch.fnmatch). Specifically, `?` matches any single character, and `*` matches zero or more characters. For example, use `up-*.md` to exclude Markdown files that start with `up-`. Lines that start with `#` are treated as comments.
|
|
@@ -364,13 +423,13 @@ This is useful if you have a page in a hierarchy that participates in parent-chi
|
|
|
364
423
|
|
|
365
424
|
### Page title
|
|
366
425
|
|
|
367
|
-
*md2conf* makes a best-effort attempt at setting the Confluence wiki page title when it publishes a Markdown document the first time. The following
|
|
426
|
+
*md2conf* makes a best-effort attempt at setting the Confluence wiki page title when it publishes a Markdown document the first time. The following act as sources for deriving a page title:
|
|
368
427
|
|
|
369
428
|
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.
|
|
370
429
|
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.
|
|
371
|
-
3. The file name (without the extension `.md`).
|
|
430
|
+
3. The file name (without the extension `.md`) and a digest. The digest is included to ensure the title is unique across the Confluence space.
|
|
372
431
|
|
|
373
|
-
If
|
|
432
|
+
If the `title` attribute (in the front-matter) or the topmost unique heading (in the document body) changes, the Confluence page title is updated. A warning is raised if the new title conflicts with the title of another page, and thus cannot be updated.
|
|
374
433
|
|
|
375
434
|
### Labels
|
|
376
435
|
|
|
@@ -405,16 +464,21 @@ The attribute `properties` is parsed as a dictionary with keys of type string an
|
|
|
405
464
|
|
|
406
465
|
### draw\.io diagrams
|
|
407
466
|
|
|
408
|
-
With the command-line option `--no-render-drawio` (default), editable diagram data is extracted from images with embedded draw\.io diagrams (`*.drawio.png` and `*.drawio.svg`), and uploaded to Confluence as attachments. `*.drawio`
|
|
467
|
+
With the command-line option `--no-render-drawio` (default), editable diagram data is extracted from images with embedded draw\.io diagrams (`*.drawio.png` and `*.drawio.svg`), and uploaded to Confluence as attachments. Files that match `*.drawio` or `*.drawio.xml` are uploaded as-is. You need a [marketplace app](https://marketplace.atlassian.com/apps/1210933/draw-io-diagrams-uml-bpmn-aws-erd-flowcharts) to view and edit these diagrams on a Confluence page.
|
|
409
468
|
|
|
410
|
-
With the command-line option `--render-drawio`, images with embedded draw\.io diagrams (`*.drawio.png` and `*.drawio.svg`) are uploaded unchanged, and shown on the Confluence page as images. These diagrams are not editable in Confluence. When both an SVG and a PNG image is available, PNG is preferred. `*.drawio`
|
|
469
|
+
With the command-line option `--render-drawio`, images with embedded draw\.io diagrams (`*.drawio.png` and `*.drawio.svg`) are uploaded unchanged, and shown on the Confluence page as images. These diagrams are not editable in Confluence. When both an SVG and a PNG image is available, PNG is preferred. Files that match `*.drawio` or `*.drawio.xml` are converted into PNG or SVG images by invoking draw\.io as a command-line utility, and the generated images are uploaded to Confluence as attachments, and shown as images.
|
|
411
470
|
|
|
412
471
|
### Mermaid diagrams
|
|
413
472
|
|
|
414
|
-
You can
|
|
473
|
+
You can add [Mermaid diagrams](https://mermaid.js.org/) to your Markdown documents to create visual representations of systems, processes, and relationships. There are two ways to include a Mermaid diagram:
|
|
474
|
+
|
|
475
|
+
* an image reference to a `.mmd` or `.mermaid` file, i.e. ``, or
|
|
476
|
+
* a fenced code block with the language specifier `mermaid`.
|
|
415
477
|
|
|
416
|
-
|
|
417
|
-
|
|
478
|
+
*md2conf* offers two options to publish the diagram:
|
|
479
|
+
|
|
480
|
+
1. Pre-render into an image (command-line option `--render-mermaid`). The source file or 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.
|
|
481
|
+
2. Display on demand (command-line option `--no-render-mermaid`). The code block is transformed into a [diagram macro](https://stratus-addons.atlassian.net/wiki/spaces/MDFC/overview), which is processed by Confluence. You need a separate [marketplace app](https://marketplace.atlassian.com/apps/1226567/mermaid-diagrams-for-confluence) to turn macro definitions into images when a Confluence page is visited.
|
|
418
482
|
|
|
419
483
|
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:
|
|
420
484
|
|
|
@@ -424,6 +488,20 @@ mmdc -i sample.mmd -o sample.png -b transparent --scale 2
|
|
|
424
488
|
|
|
425
489
|
Ensure that `mermaid-cli` is set up, refer to *Installation* for instructions.
|
|
426
490
|
|
|
491
|
+
### Links to attachments
|
|
492
|
+
|
|
493
|
+
If *md2conf* encounters a Markdown link that points to a file in the directory hierarchy being synchronized, it automatically uploads the file as an attachment to the Confluence page. Activating the link in Confluence downloads the file. Typical examples include PDFs (`*.pdf`), word processor documents (`*.docx`), spreadsheets (`*.xlsx`), plain text files (`*.txt`) or logs (`*.log`). The MIME type is set based on the file type.
|
|
494
|
+
|
|
495
|
+
### Implicit URLs
|
|
496
|
+
|
|
497
|
+
*md2conf* implicitly defines some URLs, as if you included the following at the start of the Markdown document for each URL:
|
|
498
|
+
|
|
499
|
+
```md
|
|
500
|
+
[CUSTOM-URL]: https://example.com/path/to/resource
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
Specifically, image references for status labels (e.g. `![My label][STATUS-RED]`) are automatically resolved into internally defined URLs via this mechanism.
|
|
504
|
+
|
|
427
505
|
### Local output
|
|
428
506
|
|
|
429
507
|
*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`).
|
|
@@ -440,10 +518,7 @@ Use the `--help` switch to get a full list of supported command-line options:
|
|
|
440
518
|
|
|
441
519
|
```console
|
|
442
520
|
$ python3 -m md2conf --help
|
|
443
|
-
usage: md2conf
|
|
444
|
-
[--generated-by GENERATED_BY] [--no-generated-by] [--render-drawio] [--no-render-drawio] [--render-mermaid] [--no-render-mermaid] [--render-mermaid-format {png,svg}] [--heading-anchors]
|
|
445
|
-
[--no-heading-anchors] [--ignore-invalid-url] [--local] [--headers [KEY=VALUE ...]] [--webui-links]
|
|
446
|
-
mdpath
|
|
521
|
+
usage: md2conf mdpath [OPTIONS]
|
|
447
522
|
|
|
448
523
|
positional arguments:
|
|
449
524
|
mdpath Path to Markdown file or directory to convert and publish.
|
|
@@ -467,17 +542,21 @@ options:
|
|
|
467
542
|
--generated-by GENERATED_BY
|
|
468
543
|
Add prompt to pages (default: 'This page has been generated with a tool.').
|
|
469
544
|
--no-generated-by Do not add 'generated by a tool' prompt to pages.
|
|
470
|
-
--render-drawio Render draw.io diagrams as image files
|
|
471
|
-
--no-render-drawio
|
|
472
|
-
--render-mermaid Render Mermaid diagrams as image files
|
|
473
|
-
--no-render-mermaid
|
|
474
|
-
--render-
|
|
545
|
+
--render-drawio Render draw.io diagrams as image files. (Installed utility required to covert.)
|
|
546
|
+
--no-render-drawio Upload draw.io diagram sources as Confluence page attachments. (Marketplace app required to display.)
|
|
547
|
+
--render-mermaid Render Mermaid diagrams as image files. (Installed utility required to convert.)
|
|
548
|
+
--no-render-mermaid Upload Mermaid diagram sources as Confluence page attachments. (Marketplace app required to display.)
|
|
549
|
+
--render-latex Render LaTeX formulas as image files. (Matplotlib required to convert.)
|
|
550
|
+
--no-render-latex Inline LaTeX formulas in Confluence page. (Marketplace app required to display.)
|
|
551
|
+
--diagram-output-format {png,svg}
|
|
475
552
|
Format for rendering Mermaid and draw.io diagrams (default: 'png').
|
|
553
|
+
--render-mermaid-format FORMAT
|
|
554
|
+
Format for rendering Mermaid diagrams (default: 'png').
|
|
476
555
|
--heading-anchors Place an anchor at each section heading with GitHub-style same-page identifiers.
|
|
477
556
|
--no-heading-anchors Don't place an anchor at each section heading.
|
|
478
557
|
--ignore-invalid-url Emit a warning but otherwise ignore relative URLs that point to ill-specified locations.
|
|
479
558
|
--local Write XHTML-based Confluence Storage Format files locally without invoking Confluence API.
|
|
480
|
-
--headers [KEY=VALUE ...]
|
|
559
|
+
--headers KEY=VALUE [KEY=VALUE ...]
|
|
481
560
|
Apply custom headers to all Confluence API requests.
|
|
482
561
|
--webui-links Enable Confluence Web UI links. (Typically required for on-prem versions of Confluence.)
|
|
483
562
|
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
markdown_to_confluence-0.4.5.dist-info/licenses/LICENSE,sha256=56L-Y0dyZwyVlINRJRz3PNw-ka-oLVaAq-7d8zo6qlc,1077
|
|
2
|
+
md2conf/__init__.py,sha256=uvviya0xS1aCIW7IU3EfeI_QkC_d9T_PiVsLEMXo9S4,402
|
|
3
|
+
md2conf/__main__.py,sha256=gQncJ-mkhRyQyhrZg-uJ1RnN8aGw-sr0c83ydunFNj0,11661
|
|
4
|
+
md2conf/api.py,sha256=VjXD0da4de5YtPCbUCjK0k1oD6vl59IQLItEapj0pyM,37861
|
|
5
|
+
md2conf/application.py,sha256=PZDPUpoKjKBPTHwgVO20pGzTwER3paZuQbI-2_TWBgE,8563
|
|
6
|
+
md2conf/collection.py,sha256=EobgMRJgkYloWlY03NZJ52MRC_SGLpTVCHkltDbQyt0,837
|
|
7
|
+
md2conf/converter.py,sha256=hWqbXYSFymMkvobh-f3uUO6JG28EWHU_7s0QYPI6NKM,61400
|
|
8
|
+
md2conf/csf.py,sha256=WIzGrX-RXAkr4XsgLIUT11WM1qwhjgcXZHI_cALXpyM,6397
|
|
9
|
+
md2conf/domain.py,sha256=NpeGl-I9_rgKYCKKZT1Ygg3nl5U0-jJHYYrzDVpMSGQ,1965
|
|
10
|
+
md2conf/drawio.py,sha256=3RJFFzlp5a7SNVNCnwO_HCDfMy0DqYQeXfHWRPInOVE,8527
|
|
11
|
+
md2conf/entities.dtd,sha256=M6NzqL5N7dPs_eUA_6sDsiSLzDaAacrx9LdttiufvYU,30215
|
|
12
|
+
md2conf/extra.py,sha256=VuMxuOnnC2Qwy6y52ukIxsaYhrZArRqMmRHRE4QZl8g,687
|
|
13
|
+
md2conf/latex.py,sha256=yAClNclguPv-xWBMVWbqvYWLbyUHBVufc2aUzwyKHew,7586
|
|
14
|
+
md2conf/local.py,sha256=mvp2kA_eo6JUQ_rlM7zDdEFgBPVxMr3VKP_X1nsLjHE,3747
|
|
15
|
+
md2conf/markdown.py,sha256=czabU17tUfhSX1JQGiI_TrMrTmtoVThOwFu_To_Oi_w,3176
|
|
16
|
+
md2conf/matcher.py,sha256=m5rZjYZSjhKfdeKS8JdPq7cG861Mc6rVZBkrIOZTHGE,6916
|
|
17
|
+
md2conf/mermaid.py,sha256=7iziRC1Li3D85psR5NlnZ6BOePsOfFELgkNCAxahbZU,2240
|
|
18
|
+
md2conf/metadata.py,sha256=LzZM-oPNnzCULmLhF516tPlV5zZBknccwMHt8Nan-xg,1007
|
|
19
|
+
md2conf/processor.py,sha256=z2d2KMPEYWaxflOtH2UTwrjzpPU8TtLSEUvor85ez1Q,9732
|
|
20
|
+
md2conf/properties.py,sha256=RC1jY_TKVbOv2bJxXn27Fj4fNWzyoNUQt6ltgUyVQAQ,3987
|
|
21
|
+
md2conf/puppeteer-config.json,sha256=-dMTAN_7kNTGbDlfXzApl0KJpAWna9YKZdwMKbpOb60,159
|
|
22
|
+
md2conf/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
+
md2conf/scanner.py,sha256=Cyvjab8tBvKgubttQvNagS8nailuTvFBqUGoiX5MNp8,5351
|
|
24
|
+
md2conf/text.py,sha256=fHOrUaPXAjE4iRhHqFq-CiI-knpo4wvyHCWp0crewqA,1736
|
|
25
|
+
md2conf/toc.py,sha256=hpqqDbFgNJg5-ul8qWjOglI3Am0sbwR-TLwGN5G9Qo0,2447
|
|
26
|
+
md2conf/uri.py,sha256=KbLBdRFtZTQTZd8b4j0LtE8Pb68Ly0WkemF4iW-EAB4,1158
|
|
27
|
+
md2conf/xml.py,sha256=Ybf3Ctt6EurVvel0eb1KezF33_e_cDpMwlUqHi4kNLE,5411
|
|
28
|
+
markdown_to_confluence-0.4.5.dist-info/METADATA,sha256=zhCjkqQkp71Z28iRzGH-vLMczWaELkd-2FU_kiNv61k,33724
|
|
29
|
+
markdown_to_confluence-0.4.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
30
|
+
markdown_to_confluence-0.4.5.dist-info/entry_points.txt,sha256=F1zxa1wtEObtbHS-qp46330WVFLHdMnV2wQ-ZorRmX0,50
|
|
31
|
+
markdown_to_confluence-0.4.5.dist-info/top_level.txt,sha256=_FJfl_kHrHNidyjUOuS01ngu_jDsfc-ZjSocNRJnTzU,8
|
|
32
|
+
markdown_to_confluence-0.4.5.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
33
|
+
markdown_to_confluence-0.4.5.dist-info/RECORD,,
|
md2conf/__init__.py
CHANGED
|
@@ -5,7 +5,7 @@ Parses Markdown files, converts Markdown content into the Confluence Storage For
|
|
|
5
5
|
Confluence API endpoints to upload images and content.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
__version__ = "0.4.
|
|
8
|
+
__version__ = "0.4.5"
|
|
9
9
|
__author__ = "Levente Hunyadi"
|
|
10
10
|
__copyright__ = "Copyright 2022-2025, Levente Hunyadi"
|
|
11
11
|
__license__ = "MIT"
|
md2conf/__main__.py
CHANGED
|
@@ -40,6 +40,7 @@ class Arguments(argparse.Namespace):
|
|
|
40
40
|
generated_by: Optional[str]
|
|
41
41
|
render_drawio: bool
|
|
42
42
|
render_mermaid: bool
|
|
43
|
+
render_latex: bool
|
|
43
44
|
diagram_output_format: Literal["png", "svg"]
|
|
44
45
|
local: bool
|
|
45
46
|
headers: dict[str, str]
|
|
@@ -186,26 +187,39 @@ def main() -> None:
|
|
|
186
187
|
dest="render_drawio",
|
|
187
188
|
action="store_true",
|
|
188
189
|
default=True,
|
|
189
|
-
help="Render draw.io diagrams as image files
|
|
190
|
+
help="Render draw.io diagrams as image files. (Installed utility required to covert.)",
|
|
190
191
|
)
|
|
191
192
|
parser.add_argument(
|
|
192
193
|
"--no-render-drawio",
|
|
193
194
|
dest="render_drawio",
|
|
194
195
|
action="store_false",
|
|
195
|
-
help="
|
|
196
|
+
help="Upload draw.io diagram sources as Confluence page attachments. (Marketplace app required to display.)",
|
|
196
197
|
)
|
|
197
198
|
parser.add_argument(
|
|
198
199
|
"--render-mermaid",
|
|
199
200
|
dest="render_mermaid",
|
|
200
201
|
action="store_true",
|
|
201
202
|
default=True,
|
|
202
|
-
help="Render Mermaid diagrams as image files
|
|
203
|
+
help="Render Mermaid diagrams as image files. (Installed utility required to convert.)",
|
|
203
204
|
)
|
|
204
205
|
parser.add_argument(
|
|
205
206
|
"--no-render-mermaid",
|
|
206
207
|
dest="render_mermaid",
|
|
207
208
|
action="store_false",
|
|
208
|
-
help="
|
|
209
|
+
help="Upload Mermaid diagram sources as Confluence page attachments. (Marketplace app required to display.)",
|
|
210
|
+
)
|
|
211
|
+
parser.add_argument(
|
|
212
|
+
"--render-latex",
|
|
213
|
+
dest="render_latex",
|
|
214
|
+
action="store_true",
|
|
215
|
+
default=True,
|
|
216
|
+
help="Render LaTeX formulas as image files. (Matplotlib required to convert.)",
|
|
217
|
+
)
|
|
218
|
+
parser.add_argument(
|
|
219
|
+
"--no-render-latex",
|
|
220
|
+
dest="render_latex",
|
|
221
|
+
action="store_false",
|
|
222
|
+
help="Inline LaTeX formulas in Confluence page. (Marketplace app required to display.)",
|
|
209
223
|
)
|
|
210
224
|
parser.add_argument(
|
|
211
225
|
"--diagram-output-format",
|
|
@@ -277,6 +291,7 @@ def main() -> None:
|
|
|
277
291
|
keep_hierarchy=args.keep_hierarchy,
|
|
278
292
|
render_drawio=args.render_drawio,
|
|
279
293
|
render_mermaid=args.render_mermaid,
|
|
294
|
+
render_latex=args.render_latex,
|
|
280
295
|
diagram_output_format=args.diagram_output_format,
|
|
281
296
|
webui_links=args.webui_links,
|
|
282
297
|
)
|
md2conf/api.py
CHANGED
|
@@ -27,6 +27,14 @@ from .properties import ArgumentError, ConfluenceConnectionProperties, Confluenc
|
|
|
27
27
|
|
|
28
28
|
T = TypeVar("T")
|
|
29
29
|
|
|
30
|
+
mimetypes.add_type("application/vnd.openxmlformats-officedocument.wordprocessingml.document", ".docx", strict=True)
|
|
31
|
+
mimetypes.add_type("text/vnd.mermaid", ".mmd", strict=True)
|
|
32
|
+
mimetypes.add_type("application/vnd.oasis.opendocument.presentation", ".odp", strict=True)
|
|
33
|
+
mimetypes.add_type("application/vnd.oasis.opendocument.spreadsheet", ".ods", strict=True)
|
|
34
|
+
mimetypes.add_type("application/vnd.oasis.opendocument.text", ".odt", strict=True)
|
|
35
|
+
mimetypes.add_type("application/vnd.openxmlformats-officedocument.presentationml.presentation", ".pptx", strict=True)
|
|
36
|
+
mimetypes.add_type("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ".xlsx", strict=True)
|
|
37
|
+
|
|
30
38
|
|
|
31
39
|
def _json_to_object(
|
|
32
40
|
typ: type[T],
|
|
@@ -642,7 +650,7 @@ class ConfluenceSession:
|
|
|
642
650
|
return
|
|
643
651
|
elif raw_data is not None:
|
|
644
652
|
if not force and attachment.fileSize == len(raw_data):
|
|
645
|
-
LOGGER.info("Up-to-date embedded
|
|
653
|
+
LOGGER.info("Up-to-date embedded file: %s", attachment_name)
|
|
646
654
|
return
|
|
647
655
|
else:
|
|
648
656
|
raise NotImplementedError("parameter match not exhaustive")
|
md2conf/application.py
CHANGED
|
@@ -11,13 +11,14 @@ 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, attachment_name,
|
|
14
|
+
from .converter import ConfluenceDocument, attachment_name, get_volatile_attributes, get_volatile_elements
|
|
15
|
+
from .csf import AC_ATTR, elements_from_string
|
|
15
16
|
from .domain import ConfluenceDocumentOptions, ConfluencePageID
|
|
16
17
|
from .extra import override, path_relative_to
|
|
17
18
|
from .metadata import ConfluencePageMetadata
|
|
18
19
|
from .processor import Converter, DocumentNode, Processor, ProcessorFactory
|
|
19
20
|
from .properties import PageError
|
|
20
|
-
from .xml import is_xml_equal
|
|
21
|
+
from .xml import is_xml_equal, unwrap_substitute
|
|
21
22
|
|
|
22
23
|
LOGGER = logging.getLogger(__name__)
|
|
23
24
|
|
|
@@ -115,18 +116,20 @@ class SynchronizingProcessor(Processor):
|
|
|
115
116
|
"""
|
|
116
117
|
|
|
117
118
|
base_path = path.parent
|
|
118
|
-
for
|
|
119
|
+
for image_data in document.images:
|
|
119
120
|
self.api.upload_attachment(
|
|
120
121
|
page_id.page_id,
|
|
121
|
-
attachment_name(path_relative_to(
|
|
122
|
-
attachment_path=
|
|
122
|
+
attachment_name(path_relative_to(image_data.path, base_path)),
|
|
123
|
+
attachment_path=image_data.path,
|
|
124
|
+
comment=image_data.description,
|
|
123
125
|
)
|
|
124
126
|
|
|
125
|
-
for name,
|
|
127
|
+
for name, file_data in document.embedded_files.items():
|
|
126
128
|
self.api.upload_attachment(
|
|
127
129
|
page_id.page_id,
|
|
128
130
|
name,
|
|
129
|
-
raw_data=data,
|
|
131
|
+
raw_data=file_data.data,
|
|
132
|
+
comment=file_data.description,
|
|
130
133
|
)
|
|
131
134
|
|
|
132
135
|
content = document.xhtml()
|
|
@@ -151,11 +154,16 @@ class SynchronizingProcessor(Processor):
|
|
|
151
154
|
if not title: # empty or `None`
|
|
152
155
|
title = page.title
|
|
153
156
|
|
|
157
|
+
# discard comments
|
|
158
|
+
tree = elements_from_string(page.content)
|
|
159
|
+
unwrap_substitute(AC_ATTR("inline-comment-marker"), tree)
|
|
160
|
+
|
|
154
161
|
# check if page has any changes
|
|
155
162
|
if page.title != title or not is_xml_equal(
|
|
156
163
|
document.root,
|
|
157
|
-
|
|
164
|
+
tree,
|
|
158
165
|
skip_attributes=get_volatile_attributes(),
|
|
166
|
+
skip_elements=get_volatile_elements(),
|
|
159
167
|
):
|
|
160
168
|
self.api.update_page(page_id.page_id, content, title=title, version=page.version.number + 1)
|
|
161
169
|
else:
|