mkdocs2confluence 0.7.36__tar.gz → 0.7.38__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 (72) hide show
  1. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/PKG-INFO +1 -1
  2. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/pyproject.toml +1 -1
  3. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs2confluence.egg-info/PKG-INFO +1 -1
  4. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/publisher/pipeline.py +14 -14
  5. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_publish_pipeline.py +77 -0
  6. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/LICENSE +0 -0
  7. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/README.md +0 -0
  8. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/setup.cfg +0 -0
  9. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs2confluence.egg-info/SOURCES.txt +0 -0
  10. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs2confluence.egg-info/dependency_links.txt +0 -0
  11. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs2confluence.egg-info/entry_points.txt +0 -0
  12. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs2confluence.egg-info/requires.txt +0 -0
  13. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs2confluence.egg-info/top_level.txt +0 -0
  14. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/__init__.py +0 -0
  15. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/cli.py +0 -0
  16. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/emitter/__init__.py +0 -0
  17. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/emitter/xhtml.py +0 -0
  18. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/ir/__init__.py +0 -0
  19. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/ir/document.py +0 -0
  20. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/ir/nodes.py +0 -0
  21. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/ir/treeutil.py +0 -0
  22. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/loader/__init__.py +0 -0
  23. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/loader/config.py +0 -0
  24. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/loader/extra_css.py +0 -0
  25. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/loader/nav.py +0 -0
  26. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/loader/page.py +0 -0
  27. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/parser/__init__.py +0 -0
  28. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/parser/markdown.py +0 -0
  29. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/pdf/__init__.py +0 -0
  30. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/pdf/generator.py +0 -0
  31. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/pdf/render.py +0 -0
  32. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/preprocess/__init__.py +0 -0
  33. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/preprocess/abbrevs.py +0 -0
  34. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/preprocess/fence.py +0 -0
  35. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/preprocess/frontmatter.py +0 -0
  36. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/preprocess/icons.py +0 -0
  37. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/preprocess/includes.py +0 -0
  38. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/preprocess/linkdefs.py +0 -0
  39. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/preview/__init__.py +0 -0
  40. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/preview/render.py +0 -0
  41. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/preview/server.py +0 -0
  42. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/publisher/__init__.py +0 -0
  43. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/publisher/client.py +0 -0
  44. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/transforms/__init__.py +0 -0
  45. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/transforms/abbrevs.py +0 -0
  46. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/transforms/assets.py +0 -0
  47. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/transforms/editlink.py +0 -0
  48. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/transforms/images.py +0 -0
  49. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/transforms/internallinks.py +0 -0
  50. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/src/mkdocs_to_confluence/transforms/mermaid.py +0 -0
  51. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_abbrevs.py +0 -0
  52. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_cli.py +0 -0
  53. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_editlink.py +0 -0
  54. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_emitter.py +0 -0
  55. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_extra_css.py +0 -0
  56. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_frontmatter.py +0 -0
  57. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_icons.py +0 -0
  58. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_images.py +0 -0
  59. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_internallinks.py +0 -0
  60. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_ir.py +0 -0
  61. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_linkdefs.py +0 -0
  62. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_loader.py +0 -0
  63. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_mermaid.py +0 -0
  64. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_page_loader.py +0 -0
  65. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_parser.py +0 -0
  66. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_pdf.py +0 -0
  67. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_preprocess.py +0 -0
  68. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_preview.py +0 -0
  69. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_publish_client.py +0 -0
  70. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_publish_config.py +0 -0
  71. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_server.py +0 -0
  72. {mkdocs2confluence-0.7.36 → mkdocs2confluence-0.7.38}/tests/test_treeutil.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mkdocs2confluence
3
- Version: 0.7.36
3
+ Version: 0.7.38
4
4
  Summary: Publish MkDocs Material pages to Confluence Cloud — admonitions, Mermaid diagrams, tabs, page properties and more
5
5
  Author: Anders Hybertz
6
6
  License: GPL-3.0-or-later
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mkdocs2confluence"
3
- version = "0.7.36"
3
+ version = "0.7.38"
4
4
  description = "Publish MkDocs Material pages to Confluence Cloud — admonitions, Mermaid diagrams, tabs, page properties and more"
5
5
  readme = "README.md"
6
6
  license = { text = "GPL-3.0-or-later" }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mkdocs2confluence
3
- Version: 0.7.36
3
+ Version: 0.7.38
4
4
  Summary: Publish MkDocs Material pages to Confluence Cloud — admonitions, Mermaid diagrams, tabs, page properties and more
5
5
  Author: Anders Hybertz
6
6
  License: GPL-3.0-or-later
@@ -647,13 +647,6 @@ def _post_process_action(
647
647
  except Exception:
648
648
  pass # non-fatal
649
649
 
650
- # Set full-width layout on created/updated pages (not folders).
651
- if full_width and action.page_id and not action.is_folder:
652
- try:
653
- client.set_page_full_width(action.page_id)
654
- except Exception:
655
- pass # non-fatal — page is published, layout is cosmetic
656
-
657
650
  # Apply labels (tags) from front matter — non-fatal on failure.
658
651
  if action.page_id and action.labels and not action.is_folder:
659
652
  try:
@@ -671,6 +664,13 @@ def _post_process_action(
671
664
  # Always print status errors — user configured status explicitly
672
665
  print(f" [warn] could not set page status '{action.confluence_status}': {exc}")
673
666
 
667
+ # Set full-width LAST — Confluence's state/label PUTs can reset the appearance property.
668
+ if full_width and action.page_id and not action.is_folder:
669
+ try:
670
+ client.set_page_full_width(action.page_id)
671
+ except Exception:
672
+ pass # non-fatal — page is published, layout is cosmetic
673
+
674
674
  # Upload assets — skip files whose mtime is not newer than Confluence.
675
675
  if action.page_id and action.attachments:
676
676
  uploaded, asset_skipped, asset_errors = _upload_assets(
@@ -729,13 +729,8 @@ def execute_publish(
729
729
  for action in plan:
730
730
  if action.action == "skip":
731
731
  report.skipped += 1
732
- # Still apply full-width and status even for unchanged pages so that
733
- # Confluence appearance resets (e.g. after manual edits) are corrected.
734
- if full_width and action.page_id and not action.is_folder:
735
- try:
736
- client.set_page_full_width(action.page_id)
737
- except Exception as exc:
738
- print(f" [warn] could not set full-width on page {action.page_id!r}: {exc}")
732
+ # Still apply status and full-width even for unchanged pages.
733
+ # full-width is applied LAST status PUT can reset the appearance property.
739
734
  if action.page_id and action.confluence_status and not action.is_folder:
740
735
  try:
741
736
  print(
@@ -747,6 +742,11 @@ def execute_publish(
747
742
  print(
748
743
  f" [warn] could not set page status '{action.confluence_status}': {exc}",
749
744
  )
745
+ if full_width and action.page_id and not action.is_folder:
746
+ try:
747
+ client.set_page_full_width(action.page_id)
748
+ except Exception as exc:
749
+ print(f" [warn] could not set full-width on page {action.page_id!r}: {exc}")
750
750
  continue
751
751
 
752
752
  counter += 1
@@ -1338,6 +1338,34 @@ class TestExecutePublishNonFatal:
1338
1338
  assert report.created == 1
1339
1339
  assert report.errors == []
1340
1340
 
1341
+ def test_set_page_full_width_called_after_status_on_skip(self, tmp_path: Path) -> None:
1342
+ """On skip actions, set_page_full_width must be called after set_page_status.
1343
+
1344
+ Regression test: Confluence's state PUT resets content-appearance-published,
1345
+ so full-width must always be the last post-process write.
1346
+ """
1347
+ from mkdocs_to_confluence.publisher.pipeline import PageAction, execute_publish
1348
+
1349
+ docs_dir = tmp_path / "docs"
1350
+ docs_dir.mkdir()
1351
+ page = _make_page_node("P", tmp_path, docs_dir)
1352
+ plan = [PageAction(node=page, title="P", action="skip", parent_id="ROOT",
1353
+ page_id="pid-skip", confluence_status="In Review")]
1354
+ client = self._make_client()
1355
+ client.set_page_full_width = MagicMock()
1356
+ client.set_page_status = MagicMock()
1357
+
1358
+ execute_publish(plan, client, space_id="~42", docs_dir=docs_dir, full_width=True)
1359
+
1360
+ calls = [c[0] for c in client.mock_calls]
1361
+ assert "set_page_full_width" in calls
1362
+ assert "set_page_status" in calls
1363
+ fw_idx = calls.index("set_page_full_width")
1364
+ st_idx = calls.index("set_page_status")
1365
+ assert fw_idx > st_idx, (
1366
+ "set_page_full_width must be called after set_page_status on skip actions"
1367
+ )
1368
+
1341
1369
  def test_stamp_managed_after_fallback_create_is_non_fatal(self, tmp_path: Path) -> None:
1342
1370
  """stamp_managed after the update-fallback-to-create path is also non-fatal."""
1343
1371
  from mkdocs_to_confluence.publisher.client import ConfluenceError
@@ -1886,6 +1914,55 @@ class TestExecutePublishHelpers:
1886
1914
  _post_process_action(action, client, full_width=True,
1887
1915
  docs_dir=tmp_path, report=report)
1888
1916
 
1917
+ def test_post_full_width_called_after_status(self, tmp_path: Path) -> None:
1918
+ """set_page_full_width must be called AFTER set_page_status.
1919
+
1920
+ Confluence's state PUT resets content-appearance-published, so
1921
+ full-width must always be the last write.
1922
+ """
1923
+ from mkdocs_to_confluence.publisher.pipeline import PublishReport
1924
+
1925
+ node = _make_section_node("P", [])
1926
+ action = PageAction(node=node, title="P", action="create",
1927
+ parent_id="ROOT", page_id="pid-9",
1928
+ confluence_status="In Review")
1929
+ parent = MagicMock()
1930
+ parent.set_page_full_width = MagicMock()
1931
+ parent.set_page_status = MagicMock()
1932
+ report = PublishReport()
1933
+
1934
+ _post_process_action(action, parent, full_width=True,
1935
+ docs_dir=tmp_path, report=report,
1936
+ space_key="DS")
1937
+
1938
+ calls = [c[0] for c in parent.mock_calls]
1939
+ fw_idx = calls.index("set_page_full_width")
1940
+ st_idx = calls.index("set_page_status")
1941
+ assert fw_idx > st_idx, (
1942
+ "set_page_full_width must be called after set_page_status"
1943
+ )
1944
+
1945
+ def test_post_full_width_called_after_labels(self, tmp_path: Path) -> None:
1946
+ """set_page_full_width must be called AFTER set_page_labels."""
1947
+ from mkdocs_to_confluence.publisher.pipeline import PublishReport
1948
+
1949
+ node = _make_section_node("P", [])
1950
+ action = PageAction(node=node, title="P", action="create",
1951
+ parent_id="ROOT", page_id="pid-10",
1952
+ labels=("foo",))
1953
+ parent = MagicMock()
1954
+ report = PublishReport()
1955
+
1956
+ _post_process_action(action, parent, full_width=True,
1957
+ docs_dir=tmp_path, report=report)
1958
+
1959
+ calls = [c[0] for c in parent.mock_calls]
1960
+ fw_idx = calls.index("set_page_full_width")
1961
+ lbl_idx = calls.index("set_page_labels")
1962
+ assert fw_idx > lbl_idx, (
1963
+ "set_page_full_width must be called after set_page_labels"
1964
+ )
1965
+
1889
1966
 
1890
1967
  # ── Quiet flag: stdout suppression ───────────────────────────────────────────
1891
1968