markdown-to-confluence 0.4.7__py3-none-any.whl → 0.4.8__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: markdown-to-confluence
3
- Version: 0.4.7
3
+ Version: 0.4.8
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>
@@ -26,20 +26,20 @@ License-File: LICENSE
26
26
  Requires-Dist: certifi>=2025.8.3; python_version < "3.10"
27
27
  Requires-Dist: json_strong_typing>=0.4
28
28
  Requires-Dist: lxml>=6.0
29
- Requires-Dist: markdown>=3.8
29
+ Requires-Dist: markdown>=3.9
30
30
  Requires-Dist: pymdown-extensions>=10.16
31
31
  Requires-Dist: PyYAML>=6.0
32
32
  Requires-Dist: requests>=2.32
33
33
  Requires-Dist: truststore>=0.10; python_version >= "3.10"
34
- Requires-Dist: typing-extensions>=4.14; python_version < "3.12"
34
+ Requires-Dist: typing-extensions>=4.15; python_version < "3.12"
35
35
  Provides-Extra: dev
36
- Requires-Dist: markdown_doc>=0.1.4; python_version >= "3.10" and extra == "dev"
37
- Requires-Dist: types-lxml>=2025.3.30; extra == "dev"
38
- Requires-Dist: types-markdown>=3.8; extra == "dev"
36
+ Requires-Dist: markdown_doc>=0.1.5; python_version >= "3.10" and extra == "dev"
37
+ Requires-Dist: types-lxml>=2025.8.25; extra == "dev"
38
+ Requires-Dist: types-markdown>=3.9; extra == "dev"
39
39
  Requires-Dist: types-PyYAML>=6.0; extra == "dev"
40
40
  Requires-Dist: types-requests>=2.32; extra == "dev"
41
- Requires-Dist: mypy>=1.16; extra == "dev"
42
- Requires-Dist: ruff>=0.12; extra == "dev"
41
+ Requires-Dist: mypy>=1.18; extra == "dev"
42
+ Requires-Dist: ruff>=0.13; extra == "dev"
43
43
  Provides-Extra: formulas
44
44
  Requires-Dist: matplotlib>=3.9; extra == "formulas"
45
45
  Dynamic: license-file
@@ -425,9 +425,9 @@ Use the pseudo-language `csf` in a Markdown code block to pass content directly
425
425
 
426
426
  ### Ignoring files
427
427
 
428
- 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.
428
+ Skip files and subdirectories 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.
429
429
 
430
- Files that don't have the extension `*.md` are skipped automatically. Hidden directories (whose name starts with `.`) are not recursed into.
430
+ Files that don't have the extension `*.md` are skipped automatically. Hidden directories (whose name starts with `.`) are not recursed into. To skip an entire directory, add the name of the directory without a trailing `/`.
431
431
 
432
432
  Relative paths to items in a nested directory are not supported. You must put `.mdignore` in the same directory where the items to be skipped reside.
433
433
 
@@ -501,7 +501,7 @@ You can add [Mermaid diagrams](https://mermaid.js.org/) to your Markdown documen
501
501
 
502
502
  *md2conf* offers two options to publish the diagram:
503
503
 
504
- 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.
504
+ 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.
505
505
  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.
506
506
 
507
507
  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:
@@ -512,6 +512,14 @@ mmdc -i sample.mmd -o sample.png -b transparent --scale 2
512
512
 
513
513
  Ensure that `mermaid-cli` is set up, refer to *Installation* for instructions.
514
514
 
515
+ Note that `mermaid-cli` has some implicit dependencies (e.g. a headless browser) that may not be immediately available in a CI/CD environment such as GitHub Actions. Refer to the `Dockerfile` in the *md2conf* project root, or [mermaid-cli documentation](https://github.com/mermaid-js/mermaid-cli) on how to install these dependencies such as a `chromium-browser` and various fonts.
516
+
517
+ ### Alignment
518
+
519
+ You can configure diagram and image alignment using the JSON/YAML front-matter attribute `alignment` or the command-line argument of the same name. Possible values are `center` (default), `left` and `right`. The value configured in the Markdown file front-matter takes precedence.
520
+
521
+ Unfortunately, not every third-party app supports every alignment variant. For example, the draw\.io marketplace app supports left and center but not right alignment; and diagrams produced by the Mermaid marketplace app are always centered, ignoring the setting for alignment.
522
+
515
523
  ### Links to attachments
516
524
 
517
525
  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.
@@ -586,6 +594,12 @@ options:
586
594
  --use-panel Transform admonitions and alerts into a Confluence custom panel.
587
595
  ```
588
596
 
597
+ ### Confluence REST API v1 vs. v2
598
+
599
+ *md2conf* version 0.3.0 has switched to using [Confluence REST API v2](https://developer.atlassian.com/cloud/confluence/rest/v2/) for API calls such as retrieving current page content. Earlier versions used [Confluence REST API v1](https://developer.atlassian.com/cloud/confluence/rest/v1/) exclusively. Unfortunately, Atlassian has decommissioned Confluence REST API v1 for several endpoints in Confluence Cloud as of due date March 31, 2025, and we don't have access to an environment where we could test retired v1 endpoints.
600
+
601
+ If you are restricted to an environment with Confluence REST API v1, we recommend *md2conf* [version 0.2.7](https://pypi.org/project/markdown-to-confluence/0.2.7/). Even though we don't actively support it, we are not aware of any major issues, making it a viable option in an on-premise environment with only Confluence REST API v1 support.
602
+
589
603
  ### Using the Docker container
590
604
 
591
605
  You can run the Docker container via `docker run` or via `Dockerfile`. Either can accept the environment variables or arguments similar to the Python options. The final argument `./` corresponds to `mdpath` in the command-line utility.
@@ -1,9 +1,9 @@
1
- markdown_to_confluence-0.4.7.dist-info/licenses/LICENSE,sha256=56L-Y0dyZwyVlINRJRz3PNw-ka-oLVaAq-7d8zo6qlc,1077
2
- md2conf/__init__.py,sha256=3R4-8WktKk6Q4JGEjAHqEU8S4u_w39RdcpBl-yL-0Tc,402
1
+ markdown_to_confluence-0.4.8.dist-info/licenses/LICENSE,sha256=56L-Y0dyZwyVlINRJRz3PNw-ka-oLVaAq-7d8zo6qlc,1077
2
+ md2conf/__init__.py,sha256=TJ8zRe5RlBILNw8pD-Rt3pUrUYCUfh8o4qSdv3ulu2U,402
3
3
  md2conf/__main__.py,sha256=pp3Zi60gmhXRqK0uoR4lZMVLlOO8ryAmk8UMPiI-Cew,11527
4
4
  md2conf/api.py,sha256=uEPMcR4B-07MMFM96m92z7Znnj7pzhkLLAGcOIseERY,41398
5
5
  md2conf/collection.py,sha256=EobgMRJgkYloWlY03NZJ52MRC_SGLpTVCHkltDbQyt0,837
6
- md2conf/converter.py,sha256=wghwaa_07cN-xXY1DIOJgy6VJjfnJWDjbT4aB5NAL08,68845
6
+ md2conf/converter.py,sha256=WMtwfnU50-y-LyENbaxKI7Br9gmoLxBCIZIvpeXxli8,69532
7
7
  md2conf/csf.py,sha256=rugs3qC2aJQCJSTczeBw9WhqSZZtMq14LjwT0V1b6Hc,6476
8
8
  md2conf/domain.py,sha256=rN6QSuoP3JMj-WE8BAggHqHEO8nJbnQDf0b0uhStNZk,2221
9
9
  md2conf/drawio.py,sha256=0FoCl0BWxyxO-KLPlDZPyYvSTRpgu9Z6yFKl10TGGMI,8594
@@ -26,9 +26,9 @@ md2conf/text.py,sha256=fHOrUaPXAjE4iRhHqFq-CiI-knpo4wvyHCWp0crewqA,1736
26
26
  md2conf/toc.py,sha256=hpqqDbFgNJg5-ul8qWjOglI3Am0sbwR-TLwGN5G9Qo0,2447
27
27
  md2conf/uri.py,sha256=KbLBdRFtZTQTZd8b4j0LtE8Pb68Ly0WkemF4iW-EAB4,1158
28
28
  md2conf/xml.py,sha256=SpFfcfZm1BPbB4zZM2UC1K-GkzHRhFiotiPMPt5_XPI,5541
29
- markdown_to_confluence-0.4.7.dist-info/METADATA,sha256=iHeyUxkIuoI9_g9dvCLlxC4BCqnH3JStloGAfP-bWsY,34628
30
- markdown_to_confluence-0.4.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
31
- markdown_to_confluence-0.4.7.dist-info/entry_points.txt,sha256=F1zxa1wtEObtbHS-qp46330WVFLHdMnV2wQ-ZorRmX0,50
32
- markdown_to_confluence-0.4.7.dist-info/top_level.txt,sha256=_FJfl_kHrHNidyjUOuS01ngu_jDsfc-ZjSocNRJnTzU,8
33
- markdown_to_confluence-0.4.7.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
34
- markdown_to_confluence-0.4.7.dist-info/RECORD,,
29
+ markdown_to_confluence-0.4.8.dist-info/METADATA,sha256=9qSXRbEN4QV6hAhzdIQAW_Bj8iW__Go_vhqBbVFrAJE,36555
30
+ markdown_to_confluence-0.4.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
31
+ markdown_to_confluence-0.4.8.dist-info/entry_points.txt,sha256=F1zxa1wtEObtbHS-qp46330WVFLHdMnV2wQ-ZorRmX0,50
32
+ markdown_to_confluence-0.4.8.dist-info/top_level.txt,sha256=_FJfl_kHrHNidyjUOuS01ngu_jDsfc-ZjSocNRJnTzU,8
33
+ markdown_to_confluence-0.4.8.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
34
+ markdown_to_confluence-0.4.8.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.7"
8
+ __version__ = "0.4.8"
9
9
  __author__ = "Levente Hunyadi"
10
10
  __copyright__ = "Copyright 2022-2025, Levente Hunyadi"
11
11
  __license__ = "MIT"
md2conf/converter.py CHANGED
@@ -405,18 +405,18 @@ class ConfluencePanel:
405
405
 
406
406
 
407
407
  ConfluencePanel.from_class = {
408
- "attention": ConfluencePanel("❗", "exclamation", "#F9F9F9"), # rST admonition
409
- "caution": ConfluencePanel("❌", "x", "#FFEBE9"),
410
- "danger": ConfluencePanel("☠️", "skull_crossbones", "#FFE5E5"), # rST admonition
411
- "disclaimer": ConfluencePanel("❗", "exclamation", "#F9F9F9"), # GitLab
412
- "error": ConfluencePanel("❌", "x", "#FFEBE9"), # rST admonition
413
- "flag": ConfluencePanel("🚩", "triangular_flag_on_post", "#FDECEA"), # GitLab
414
- "hint": ConfluencePanel("💡", "bulb", "#DAFBE1"), # rST admonition
415
- "info": ConfluencePanel("ℹ️", "information_source", "#DDF4FF"),
416
- "note": ConfluencePanel("📝", "pencil", "#DDF4FF"),
417
- "tip": ConfluencePanel("💡", "bulb", "#DAFBE1"),
418
- "important": ConfluencePanel("❗", "exclamation", "#FBEFFF"),
419
- "warning": ConfluencePanel("⚠️", "warning", "#FFF8C5"),
408
+ "attention": ConfluencePanel("❗", "exclamation", "var(--ds-background-accent-gray-subtlest)"), # rST admonition
409
+ "caution": ConfluencePanel("❌", "x", "var(--ds-background-accent-orange-subtlest)"),
410
+ "danger": ConfluencePanel("☠️", "skull_crossbones", "var(--ds-background-accent-red-subtlest)"), # rST admonition
411
+ "disclaimer": ConfluencePanel("❗", "exclamation", "var(--ds-background-accent-gray-subtlest)"), # GitLab
412
+ "error": ConfluencePanel("❌", "x", "var(--ds-background-accent-red-subtlest)"), # rST admonition
413
+ "flag": ConfluencePanel("🚩", "triangular_flag_on_post", "var(--ds-background-accent-orange-subtlest"), # GitLab
414
+ "hint": ConfluencePanel("💡", "bulb", "var(--ds-background-accent-green-subtlest)"), # rST admonition
415
+ "info": ConfluencePanel("ℹ️", "information_source", "var(--ds-background-accent-blue-subtlest)"),
416
+ "note": ConfluencePanel("📝", "pencil", "var(--ds-background-accent-teal-subtlest)"),
417
+ "tip": ConfluencePanel("💡", "bulb", "var(--ds-background-accent-green-subtlest)"),
418
+ "important": ConfluencePanel("❗", "exclamation", "var(--ds-background-accent-purple-subtlest)"),
419
+ "warning": ConfluencePanel("⚠️", "warning", "var(--ds-background-accent-yellow-subtlest)"),
420
420
  }
421
421
 
422
422
 
@@ -817,6 +817,14 @@ class ConfluenceStorageFormatConverter(NodeVisitor):
817
817
  str(attrs.height),
818
818
  ),
819
819
  )
820
+ if attrs.alignment is ImageAlignment.CENTER:
821
+ parameters.append(
822
+ AC_ELEM(
823
+ "parameter",
824
+ {AC_ATTR("name"): "pCenter"},
825
+ str(1),
826
+ ),
827
+ )
820
828
 
821
829
  local_id = str(uuid.uuid4())
822
830
  macro_id = str(uuid.uuid4())
@@ -1650,7 +1658,7 @@ class ConfluenceStorageFormatConverter(NodeVisitor):
1650
1658
  # <li>[x] ...</li>
1651
1659
  # </ul>
1652
1660
  elif child.tag == "ul":
1653
- if len(child) > 0 and element_text_starts_with_any(child[0], ["[ ]", "[x]", "[X]"]):
1661
+ if len(child) > 0 and all(element_text_starts_with_any(item, ["[ ]", "[x]", "[X]"]) for item in child):
1654
1662
  return self._transform_tasklist(child)
1655
1663
 
1656
1664
  return None