mkdocs2confluence 0.8.0__tar.gz → 0.8.2__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 (85) hide show
  1. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/PKG-INFO +37 -7
  2. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/README.md +36 -6
  3. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/pyproject.toml +1 -1
  4. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs2confluence.egg-info/PKG-INFO +37 -7
  5. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/cli.py +25 -17
  6. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/sync/platform.py +1 -1
  7. mkdocs2confluence-0.8.2/tests/test_sync_command.py +637 -0
  8. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_sync_github.py +21 -0
  9. mkdocs2confluence-0.8.0/tests/test_sync_command.py +0 -283
  10. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/LICENSE +0 -0
  11. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/setup.cfg +0 -0
  12. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs2confluence.egg-info/SOURCES.txt +0 -0
  13. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs2confluence.egg-info/dependency_links.txt +0 -0
  14. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs2confluence.egg-info/entry_points.txt +0 -0
  15. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs2confluence.egg-info/requires.txt +0 -0
  16. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs2confluence.egg-info/top_level.txt +0 -0
  17. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/__init__.py +0 -0
  18. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/emitter/__init__.py +0 -0
  19. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/emitter/xhtml.py +0 -0
  20. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/ir/__init__.py +0 -0
  21. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/ir/document.py +0 -0
  22. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/ir/nodes.py +0 -0
  23. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/ir/treeutil.py +0 -0
  24. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/loader/__init__.py +0 -0
  25. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/loader/config.py +0 -0
  26. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/loader/extra_css.py +0 -0
  27. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/loader/nav.py +0 -0
  28. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/loader/page.py +0 -0
  29. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/parser/__init__.py +0 -0
  30. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/parser/markdown.py +0 -0
  31. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/pdf/__init__.py +0 -0
  32. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/pdf/generator.py +0 -0
  33. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/pdf/render.py +0 -0
  34. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/preprocess/__init__.py +0 -0
  35. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/preprocess/abbrevs.py +0 -0
  36. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/preprocess/fence.py +0 -0
  37. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/preprocess/frontmatter.py +0 -0
  38. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/preprocess/icons.py +0 -0
  39. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/preprocess/includes.py +0 -0
  40. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/preprocess/linkdefs.py +0 -0
  41. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/preview/__init__.py +0 -0
  42. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/preview/render.py +0 -0
  43. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/preview/server.py +0 -0
  44. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/publisher/__init__.py +0 -0
  45. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/publisher/client.py +0 -0
  46. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/publisher/pipeline.py +0 -0
  47. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/sync/__init__.py +0 -0
  48. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/sync/anchoring.py +0 -0
  49. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/sync/command.py +0 -0
  50. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/sync/comments.py +0 -0
  51. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/sync/github.py +0 -0
  52. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/sync/state.py +0 -0
  53. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/transforms/__init__.py +0 -0
  54. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/transforms/abbrevs.py +0 -0
  55. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/transforms/assets.py +0 -0
  56. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/transforms/editlink.py +0 -0
  57. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/transforms/images.py +0 -0
  58. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/transforms/internallinks.py +0 -0
  59. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/src/mkdocs_to_confluence/transforms/mermaid.py +0 -0
  60. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_abbrevs.py +0 -0
  61. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_cli.py +0 -0
  62. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_editlink.py +0 -0
  63. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_emitter.py +0 -0
  64. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_extra_css.py +0 -0
  65. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_frontmatter.py +0 -0
  66. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_icons.py +0 -0
  67. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_images.py +0 -0
  68. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_internallinks.py +0 -0
  69. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_ir.py +0 -0
  70. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_linkdefs.py +0 -0
  71. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_loader.py +0 -0
  72. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_mermaid.py +0 -0
  73. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_page_loader.py +0 -0
  74. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_parser.py +0 -0
  75. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_pdf.py +0 -0
  76. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_preprocess.py +0 -0
  77. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_preview.py +0 -0
  78. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_publish_client.py +0 -0
  79. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_publish_config.py +0 -0
  80. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_publish_pipeline.py +0 -0
  81. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_server.py +0 -0
  82. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_sync_anchoring.py +0 -0
  83. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_sync_comments.py +0 -0
  84. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_sync_state.py +0 -0
  85. {mkdocs2confluence-0.8.0 → mkdocs2confluence-0.8.2}/tests/test_treeutil.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mkdocs2confluence
3
- Version: 0.8.0
3
+ Version: 0.8.2
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
@@ -54,6 +54,8 @@ Dynamic: license-file
54
54
 
55
55
  A Python CLI tool that compiles MkDocs-flavoured Markdown into native Confluence storage XHTML and publishes it directly to Confluence Cloud. It is a **compiler/transpiler**, not an HTML converter — every construct maps to its native Confluence equivalent, so pages look and behave like hand-authored Confluence content.
56
56
 
57
+ It also bridges the gap between Confluence reviewers and developers: the `sync-comments` command turns open Confluence page comments into GitHub pull request review threads, and auto-resolves them in Confluence when the PR is merged.
58
+
57
59
  > **Zensical compatible** — [Zensical](https://zensical.org/) is the modern successor to MkDocs + Material for MkDocs. Since it uses the same `mkdocs.yml` format and Python Markdown extensions, your Zensical project works with mk2conf today with no changes required.
58
60
 
59
61
  ---
@@ -109,6 +111,12 @@ mk2conf publish
109
111
 
110
112
  # Export a nav section to a stand-alone PDF document
111
113
  mk2conf pdf --section Guide --out guide.pdf
114
+
115
+ # Sync open Confluence comments to GitHub review PRs
116
+ mk2conf sync-comments
117
+
118
+ # Resolve Confluence comments when their review PRs are merged
119
+ mk2conf sync-comments --check-merges
112
120
  ```
113
121
 
114
122
  ---
@@ -128,12 +136,32 @@ confluence:
128
136
  full_width: true # default: true
129
137
  ```
130
138
 
139
+ The `confluence:` block is also accepted under `extra:` (MkDocs strict-mode compatible):
140
+
141
+ ```yaml
142
+ extra:
143
+ confluence:
144
+ base_url: https://yourorg.atlassian.net
145
+ space_key: TECH
146
+ ...
147
+ ```
148
+
131
149
  The API token is read from (in priority order):
132
150
 
133
151
  1. `token:` in `mkdocs.yml` — typically via `!ENV CONFLUENCE_API_TOKEN`
134
152
  2. `CONFLUENCE_API_TOKEN` environment variable
135
153
  3. `MK2CONF_TOKEN` environment variable
136
154
 
155
+ ### Additional fields for `sync-comments`
156
+
157
+ ```yaml
158
+ confluence:
159
+ # ... base fields above ...
160
+ github_repo: owner/repo # required for sync-comments
161
+ github_token: !ENV GITHUB_TOKEN # falls back to GITHUB_TOKEN env var
162
+ github_base_branch: main # default: main
163
+ ```
164
+
137
165
  ---
138
166
 
139
167
  ## Your first publish
@@ -286,14 +314,14 @@ mk2conf sync-comments [--config PATH] [--check-merges] [--force] [--dry-run] [--
286
314
  | `--dry-run` | off | Print what would be synced without making any API calls |
287
315
  | `--quiet` | off | Suppress progress output |
288
316
 
289
- **Required config** (under `extra.confluence` in `mkdocs.yml`):
317
+ **Required config** (add to the `confluence:` block in `mkdocs.yml`):
290
318
 
291
319
  ```yaml
292
- extra:
293
- confluence:
294
- github_repo: owner/repo # required for sync-comments
295
- github_token: ${GITHUB_TOKEN} # falls back to GITHUB_TOKEN env var
296
- github_base_branch: main # default: main
320
+ confluence:
321
+ # ... base fields ...
322
+ github_repo: owner/repo # required for sync-comments
323
+ github_token: !ENV GITHUB_TOKEN # falls back to GITHUB_TOKEN env var
324
+ github_base_branch: main # default: main
297
325
  ```
298
326
 
299
327
  **Workflow:**
@@ -421,6 +449,8 @@ MkDocs abbreviation definitions (`*[ABBR]: Full term`) are rendered as inline su
421
449
 
422
450
  Each stage is a separate Python module under `src/mkdocs_to_confluence/`. The **plan** phase makes all API read calls (find existing pages); the **execute** phase makes all write calls, ensuring parent pages always exist before their children.
423
451
 
452
+ The `sync/` package is a self-contained pipeline for the `sync-comments` command: it fetches Confluence comments, anchors them to source lines, posts them as GitHub review threads via GraphQL, and resolves them on PR merge. The `ReviewPlatformClient` Protocol keeps GitHub-specific code isolated so future GitLab or Azure DevOps adapters slot in without touching the core.
453
+
424
454
  ---
425
455
 
426
456
  ## Development
@@ -14,6 +14,8 @@
14
14
 
15
15
  A Python CLI tool that compiles MkDocs-flavoured Markdown into native Confluence storage XHTML and publishes it directly to Confluence Cloud. It is a **compiler/transpiler**, not an HTML converter — every construct maps to its native Confluence equivalent, so pages look and behave like hand-authored Confluence content.
16
16
 
17
+ It also bridges the gap between Confluence reviewers and developers: the `sync-comments` command turns open Confluence page comments into GitHub pull request review threads, and auto-resolves them in Confluence when the PR is merged.
18
+
17
19
  > **Zensical compatible** — [Zensical](https://zensical.org/) is the modern successor to MkDocs + Material for MkDocs. Since it uses the same `mkdocs.yml` format and Python Markdown extensions, your Zensical project works with mk2conf today with no changes required.
18
20
 
19
21
  ---
@@ -69,6 +71,12 @@ mk2conf publish
69
71
 
70
72
  # Export a nav section to a stand-alone PDF document
71
73
  mk2conf pdf --section Guide --out guide.pdf
74
+
75
+ # Sync open Confluence comments to GitHub review PRs
76
+ mk2conf sync-comments
77
+
78
+ # Resolve Confluence comments when their review PRs are merged
79
+ mk2conf sync-comments --check-merges
72
80
  ```
73
81
 
74
82
  ---
@@ -88,12 +96,32 @@ confluence:
88
96
  full_width: true # default: true
89
97
  ```
90
98
 
99
+ The `confluence:` block is also accepted under `extra:` (MkDocs strict-mode compatible):
100
+
101
+ ```yaml
102
+ extra:
103
+ confluence:
104
+ base_url: https://yourorg.atlassian.net
105
+ space_key: TECH
106
+ ...
107
+ ```
108
+
91
109
  The API token is read from (in priority order):
92
110
 
93
111
  1. `token:` in `mkdocs.yml` — typically via `!ENV CONFLUENCE_API_TOKEN`
94
112
  2. `CONFLUENCE_API_TOKEN` environment variable
95
113
  3. `MK2CONF_TOKEN` environment variable
96
114
 
115
+ ### Additional fields for `sync-comments`
116
+
117
+ ```yaml
118
+ confluence:
119
+ # ... base fields above ...
120
+ github_repo: owner/repo # required for sync-comments
121
+ github_token: !ENV GITHUB_TOKEN # falls back to GITHUB_TOKEN env var
122
+ github_base_branch: main # default: main
123
+ ```
124
+
97
125
  ---
98
126
 
99
127
  ## Your first publish
@@ -246,14 +274,14 @@ mk2conf sync-comments [--config PATH] [--check-merges] [--force] [--dry-run] [--
246
274
  | `--dry-run` | off | Print what would be synced without making any API calls |
247
275
  | `--quiet` | off | Suppress progress output |
248
276
 
249
- **Required config** (under `extra.confluence` in `mkdocs.yml`):
277
+ **Required config** (add to the `confluence:` block in `mkdocs.yml`):
250
278
 
251
279
  ```yaml
252
- extra:
253
- confluence:
254
- github_repo: owner/repo # required for sync-comments
255
- github_token: ${GITHUB_TOKEN} # falls back to GITHUB_TOKEN env var
256
- github_base_branch: main # default: main
280
+ confluence:
281
+ # ... base fields ...
282
+ github_repo: owner/repo # required for sync-comments
283
+ github_token: !ENV GITHUB_TOKEN # falls back to GITHUB_TOKEN env var
284
+ github_base_branch: main # default: main
257
285
  ```
258
286
 
259
287
  **Workflow:**
@@ -381,6 +409,8 @@ MkDocs abbreviation definitions (`*[ABBR]: Full term`) are rendered as inline su
381
409
 
382
410
  Each stage is a separate Python module under `src/mkdocs_to_confluence/`. The **plan** phase makes all API read calls (find existing pages); the **execute** phase makes all write calls, ensuring parent pages always exist before their children.
383
411
 
412
+ The `sync/` package is a self-contained pipeline for the `sync-comments` command: it fetches Confluence comments, anchors them to source lines, posts them as GitHub review threads via GraphQL, and resolves them on PR merge. The `ReviewPlatformClient` Protocol keeps GitHub-specific code isolated so future GitLab or Azure DevOps adapters slot in without touching the core.
413
+
384
414
  ---
385
415
 
386
416
  ## Development
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mkdocs2confluence"
3
- version = "0.8.0"
3
+ version = "0.8.2"
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.8.0
3
+ Version: 0.8.2
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
@@ -54,6 +54,8 @@ Dynamic: license-file
54
54
 
55
55
  A Python CLI tool that compiles MkDocs-flavoured Markdown into native Confluence storage XHTML and publishes it directly to Confluence Cloud. It is a **compiler/transpiler**, not an HTML converter — every construct maps to its native Confluence equivalent, so pages look and behave like hand-authored Confluence content.
56
56
 
57
+ It also bridges the gap between Confluence reviewers and developers: the `sync-comments` command turns open Confluence page comments into GitHub pull request review threads, and auto-resolves them in Confluence when the PR is merged.
58
+
57
59
  > **Zensical compatible** — [Zensical](https://zensical.org/) is the modern successor to MkDocs + Material for MkDocs. Since it uses the same `mkdocs.yml` format and Python Markdown extensions, your Zensical project works with mk2conf today with no changes required.
58
60
 
59
61
  ---
@@ -109,6 +111,12 @@ mk2conf publish
109
111
 
110
112
  # Export a nav section to a stand-alone PDF document
111
113
  mk2conf pdf --section Guide --out guide.pdf
114
+
115
+ # Sync open Confluence comments to GitHub review PRs
116
+ mk2conf sync-comments
117
+
118
+ # Resolve Confluence comments when their review PRs are merged
119
+ mk2conf sync-comments --check-merges
112
120
  ```
113
121
 
114
122
  ---
@@ -128,12 +136,32 @@ confluence:
128
136
  full_width: true # default: true
129
137
  ```
130
138
 
139
+ The `confluence:` block is also accepted under `extra:` (MkDocs strict-mode compatible):
140
+
141
+ ```yaml
142
+ extra:
143
+ confluence:
144
+ base_url: https://yourorg.atlassian.net
145
+ space_key: TECH
146
+ ...
147
+ ```
148
+
131
149
  The API token is read from (in priority order):
132
150
 
133
151
  1. `token:` in `mkdocs.yml` — typically via `!ENV CONFLUENCE_API_TOKEN`
134
152
  2. `CONFLUENCE_API_TOKEN` environment variable
135
153
  3. `MK2CONF_TOKEN` environment variable
136
154
 
155
+ ### Additional fields for `sync-comments`
156
+
157
+ ```yaml
158
+ confluence:
159
+ # ... base fields above ...
160
+ github_repo: owner/repo # required for sync-comments
161
+ github_token: !ENV GITHUB_TOKEN # falls back to GITHUB_TOKEN env var
162
+ github_base_branch: main # default: main
163
+ ```
164
+
137
165
  ---
138
166
 
139
167
  ## Your first publish
@@ -286,14 +314,14 @@ mk2conf sync-comments [--config PATH] [--check-merges] [--force] [--dry-run] [--
286
314
  | `--dry-run` | off | Print what would be synced without making any API calls |
287
315
  | `--quiet` | off | Suppress progress output |
288
316
 
289
- **Required config** (under `extra.confluence` in `mkdocs.yml`):
317
+ **Required config** (add to the `confluence:` block in `mkdocs.yml`):
290
318
 
291
319
  ```yaml
292
- extra:
293
- confluence:
294
- github_repo: owner/repo # required for sync-comments
295
- github_token: ${GITHUB_TOKEN} # falls back to GITHUB_TOKEN env var
296
- github_base_branch: main # default: main
320
+ confluence:
321
+ # ... base fields ...
322
+ github_repo: owner/repo # required for sync-comments
323
+ github_token: !ENV GITHUB_TOKEN # falls back to GITHUB_TOKEN env var
324
+ github_base_branch: main # default: main
297
325
  ```
298
326
 
299
327
  **Workflow:**
@@ -421,6 +449,8 @@ MkDocs abbreviation definitions (`*[ABBR]: Full term`) are rendered as inline su
421
449
 
422
450
  Each stage is a separate Python module under `src/mkdocs_to_confluence/`. The **plan** phase makes all API read calls (find existing pages); the **execute** phase makes all write calls, ensuring parent pages always exist before their children.
423
451
 
452
+ The `sync/` package is a self-contained pipeline for the `sync-comments` command: it fetches Confluence comments, anchors them to source lines, posts them as GitHub review threads via GraphQL, and resolves them on PR merge. The `ReviewPlatformClient` Protocol keeps GitHub-specific code isolated so future GitLab or Azure DevOps adapters slot in without touching the core.
453
+
424
454
  ---
425
455
 
426
456
  ## Development
@@ -548,25 +548,33 @@ def _cmd_publish(args: argparse.Namespace) -> None:
548
548
  print(str(report))
549
549
 
550
550
  # Write page map so sync-comments can match source files to Confluence pages.
551
- if not (getattr(args, "page", None) or getattr(args, "section", None)):
552
- import json as _json_pm
551
+ # Always merge into the existing map so partial runs (--page/--section) and
552
+ # multiple configs pointing to the same repo root all accumulate correctly.
553
+ import json as _json_pm
554
+ try:
555
+ repo_root = config_path.parent
553
556
  try:
554
- repo_root = config_path.parent
557
+ docs_rel = config.docs_dir.relative_to(repo_root)
558
+ except ValueError:
559
+ docs_rel = Path("docs")
560
+ new_entries = {
561
+ str(docs_rel / action.node.docs_path): action.page_id
562
+ for action in plan
563
+ if action.node.docs_path and action.page_id and not action.is_folder
564
+ }
565
+ pm_path = repo_root / ".mk2conf-pages.json"
566
+ existing: dict[str, str] = {}
567
+ if pm_path.exists():
555
568
  try:
556
- docs_rel = config.docs_dir.relative_to(repo_root)
557
- except ValueError:
558
- docs_rel = Path("docs")
559
- page_map = {
560
- str(docs_rel / action.node.docs_path): action.page_id
561
- for action in plan
562
- if action.node.docs_path and action.page_id and not action.is_folder
563
- }
564
- pm_path = repo_root / ".mk2conf-pages.json"
565
- pm_path.write_text(_json_pm.dumps(page_map, indent=2), encoding="utf-8")
566
- if not getattr(args, "quiet", False):
567
- print(f"Page map: {len(page_map)} page(s) → {pm_path.name}")
568
- except Exception as exc:
569
- print(f" [warn] could not write page map: {exc}", file=sys.stderr)
569
+ existing = _json_pm.loads(pm_path.read_text(encoding="utf-8"))
570
+ except Exception:
571
+ pass
572
+ existing.update(new_entries)
573
+ pm_path.write_text(_json_pm.dumps(existing, indent=2), encoding="utf-8")
574
+ if not getattr(args, "quiet", False):
575
+ print(f"Page map: {len(existing)} page(s) {pm_path.name}")
576
+ except Exception as exc:
577
+ print(f" [warn] could not write page map: {exc}", file=sys.stderr)
570
578
 
571
579
  if getattr(args, "report", None):
572
580
  import json as _json
@@ -5,7 +5,7 @@ from __future__ import annotations
5
5
  from typing import Protocol
6
6
 
7
7
 
8
- class ReviewPlatformClient(Protocol):
8
+ class ReviewPlatformClient(Protocol): # pragma: no cover
9
9
  """Interface for posting review comments on a hosted git platform.
10
10
 
11
11
  Implement this protocol to add support for GitLab, Azure DevOps, etc.