mkdocs2confluence 0.12.2__tar.gz → 0.13.1__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.
- {mkdocs2confluence-0.12.2/src/mkdocs2confluence.egg-info → mkdocs2confluence-0.13.1}/PKG-INFO +20 -2
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/README.md +19 -1
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/pyproject.toml +4 -1
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1/src/mkdocs2confluence.egg-info}/PKG-INFO +20 -2
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs2confluence.egg-info/SOURCES.txt +6 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/cli.py +68 -3
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/loader/config.py +18 -0
- mkdocs2confluence-0.13.1/src/mkdocs_to_confluence/publisher/changelog.py +131 -0
- mkdocs2confluence-0.13.1/src/mkdocs_to_confluence/skill_installer.py +99 -0
- mkdocs2confluence-0.13.1/src/mkdocs_to_confluence/skills/mkdocs-changelog/SKILL.md +78 -0
- mkdocs2confluence-0.13.1/tests/test_changelog_config.py +62 -0
- mkdocs2confluence-0.13.1/tests/test_changelog_publish.py +194 -0
- mkdocs2confluence-0.13.1/tests/test_skill_installer.py +126 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/LICENSE +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/setup.cfg +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs2confluence.egg-info/dependency_links.txt +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs2confluence.egg-info/entry_points.txt +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs2confluence.egg-info/requires.txt +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs2confluence.egg-info/top_level.txt +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/__init__.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/compiler/__init__.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/compiler/models.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/compiler/page.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/emitter/__init__.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/emitter/xhtml.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/ir/__init__.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/ir/document.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/ir/nodes.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/ir/treeutil.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/loader/__init__.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/loader/extra_css.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/loader/nav.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/loader/page.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/parser/__init__.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/parser/markdown.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/pdf/__init__.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/pdf/generator.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/pdf/render.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/preprocess/__init__.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/preprocess/abbrevs.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/preprocess/fence.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/preprocess/frontmatter.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/preprocess/icons.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/preprocess/includes.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/preprocess/linkdefs.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/preview/__init__.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/preview/render.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/preview/server.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/publisher/__init__.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/publisher/client.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/publisher/executor.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/publisher/http_retry.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/publisher/models.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/publisher/pipeline.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/publisher/planner.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/sync/__init__.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/sync/anchoring.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/sync/command.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/sync/comments.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/sync/github.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/sync/platform.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/sync/state.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/transforms/__init__.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/transforms/abbrevs.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/transforms/assets.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/transforms/editlink.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/transforms/footer.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/transforms/images.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/transforms/internallinks.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/transforms/mermaid.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_abbrevs.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_children_macro.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_cli.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_editlink.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_emitter.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_extra_css.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_footer.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_frontmatter.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_icons.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_images.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_internallinks.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_ir.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_linkdefs.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_loader.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_mermaid.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_page_loader.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_parser.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_pdf.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_preprocess.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_preview.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_publish_client.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_publish_config.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_publish_pipeline.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_server.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_sync_anchoring.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_sync_command.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_sync_comments.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_sync_github.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_sync_state.py +0 -0
- {mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/tests/test_treeutil.py +0 -0
{mkdocs2confluence-0.12.2/src/mkdocs2confluence.egg-info → mkdocs2confluence-0.13.1}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mkdocs2confluence
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.13.1
|
|
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
|
|
@@ -153,10 +153,28 @@ confluence:
|
|
|
153
153
|
parent_page_id: "123456" # optional root page
|
|
154
154
|
mermaid_render: kroki # "kroki" (default) | "kroki:https://your-kroki" | "none"
|
|
155
155
|
full_width: true # default: true
|
|
156
|
+
changelog: CHANGELOG.md # optional: publish as a top-level "What's New" page
|
|
156
157
|
```
|
|
157
158
|
|
|
158
159
|
The `confluence:` block is also accepted under `extra:` for MkDocs strict-mode compatibility. The API token is read from `token:` in `mkdocs.yml`, then `CONFLUENCE_API_TOKEN`, then `MK2CONF_TOKEN`.
|
|
159
160
|
|
|
161
|
+
### Changelog / What's New page
|
|
162
|
+
|
|
163
|
+
Set `changelog:` to a Markdown file path (relative to `docs_dir`) to have mk2conf publish it as a permanent top-level page on every full `mk2conf publish` run. The page title comes from YAML front matter `title:`; it defaults to `"What's New"` if absent.
|
|
164
|
+
|
|
165
|
+
```yaml
|
|
166
|
+
confluence:
|
|
167
|
+
changelog: CHANGELOG.md # relative to docs_dir
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
- The page does **not** need to appear in `nav:` — it is always placed at the top level of the space (or under `parent_page_id` if set).
|
|
171
|
+
- If it also appears in `nav:`, it is published once; no duplication.
|
|
172
|
+
- `--prune` never deletes it — it is a pinned page, not a nav-derived page.
|
|
173
|
+
- Partial runs (`--page` / `--section`) skip the changelog page, consistent with other publish behaviour.
|
|
174
|
+
- Omit the key, or set it to an empty string, to disable the feature entirely.
|
|
175
|
+
|
|
176
|
+
Run `mk2conf install-skill` once after setting `changelog:` to install the changelog AI skill into your AI tool (Claude Code, Copilot, Cursor, Hermes). The skill analyses git changes to your docs since the last `CHANGELOG.md` commit and drafts an entry when the changes qualify as significant.
|
|
177
|
+
|
|
160
178
|
**Your first publish:**
|
|
161
179
|
|
|
162
180
|
```bash
|
|
@@ -172,7 +190,7 @@ mk2conf publish # go live
|
|
|
172
190
|
|
|
173
191
|
| | |
|
|
174
192
|
|---|---|
|
|
175
|
-
| [docs/commands.md](docs/commands.md) | Full flag reference for all
|
|
193
|
+
| [docs/commands.md](docs/commands.md) | Full flag reference for all five commands |
|
|
176
194
|
| [docs/features.md](docs/features.md) | Supported Markdown / Material features and known limitations |
|
|
177
195
|
| [Setup.md](Setup.md) | Development environment setup |
|
|
178
196
|
|
|
@@ -111,10 +111,28 @@ confluence:
|
|
|
111
111
|
parent_page_id: "123456" # optional root page
|
|
112
112
|
mermaid_render: kroki # "kroki" (default) | "kroki:https://your-kroki" | "none"
|
|
113
113
|
full_width: true # default: true
|
|
114
|
+
changelog: CHANGELOG.md # optional: publish as a top-level "What's New" page
|
|
114
115
|
```
|
|
115
116
|
|
|
116
117
|
The `confluence:` block is also accepted under `extra:` for MkDocs strict-mode compatibility. The API token is read from `token:` in `mkdocs.yml`, then `CONFLUENCE_API_TOKEN`, then `MK2CONF_TOKEN`.
|
|
117
118
|
|
|
119
|
+
### Changelog / What's New page
|
|
120
|
+
|
|
121
|
+
Set `changelog:` to a Markdown file path (relative to `docs_dir`) to have mk2conf publish it as a permanent top-level page on every full `mk2conf publish` run. The page title comes from YAML front matter `title:`; it defaults to `"What's New"` if absent.
|
|
122
|
+
|
|
123
|
+
```yaml
|
|
124
|
+
confluence:
|
|
125
|
+
changelog: CHANGELOG.md # relative to docs_dir
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
- The page does **not** need to appear in `nav:` — it is always placed at the top level of the space (or under `parent_page_id` if set).
|
|
129
|
+
- If it also appears in `nav:`, it is published once; no duplication.
|
|
130
|
+
- `--prune` never deletes it — it is a pinned page, not a nav-derived page.
|
|
131
|
+
- Partial runs (`--page` / `--section`) skip the changelog page, consistent with other publish behaviour.
|
|
132
|
+
- Omit the key, or set it to an empty string, to disable the feature entirely.
|
|
133
|
+
|
|
134
|
+
Run `mk2conf install-skill` once after setting `changelog:` to install the changelog AI skill into your AI tool (Claude Code, Copilot, Cursor, Hermes). The skill analyses git changes to your docs since the last `CHANGELOG.md` commit and drafts an entry when the changes qualify as significant.
|
|
135
|
+
|
|
118
136
|
**Your first publish:**
|
|
119
137
|
|
|
120
138
|
```bash
|
|
@@ -130,7 +148,7 @@ mk2conf publish # go live
|
|
|
130
148
|
|
|
131
149
|
| | |
|
|
132
150
|
|---|---|
|
|
133
|
-
| [docs/commands.md](docs/commands.md) | Full flag reference for all
|
|
151
|
+
| [docs/commands.md](docs/commands.md) | Full flag reference for all five commands |
|
|
134
152
|
| [docs/features.md](docs/features.md) | Supported Markdown / Material features and known limitations |
|
|
135
153
|
| [Setup.md](Setup.md) | Development environment setup |
|
|
136
154
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mkdocs2confluence"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.13.1"
|
|
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" }
|
|
@@ -67,6 +67,9 @@ build-backend = "setuptools.build_meta"
|
|
|
67
67
|
[tool.setuptools.packages.find]
|
|
68
68
|
where = ["src"]
|
|
69
69
|
|
|
70
|
+
[tool.setuptools.package-data]
|
|
71
|
+
"mkdocs_to_confluence" = ["skills/**/*.md"]
|
|
72
|
+
|
|
70
73
|
[tool.ruff]
|
|
71
74
|
line-length = 120
|
|
72
75
|
|
{mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1/src/mkdocs2confluence.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mkdocs2confluence
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.13.1
|
|
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
|
|
@@ -153,10 +153,28 @@ confluence:
|
|
|
153
153
|
parent_page_id: "123456" # optional root page
|
|
154
154
|
mermaid_render: kroki # "kroki" (default) | "kroki:https://your-kroki" | "none"
|
|
155
155
|
full_width: true # default: true
|
|
156
|
+
changelog: CHANGELOG.md # optional: publish as a top-level "What's New" page
|
|
156
157
|
```
|
|
157
158
|
|
|
158
159
|
The `confluence:` block is also accepted under `extra:` for MkDocs strict-mode compatibility. The API token is read from `token:` in `mkdocs.yml`, then `CONFLUENCE_API_TOKEN`, then `MK2CONF_TOKEN`.
|
|
159
160
|
|
|
161
|
+
### Changelog / What's New page
|
|
162
|
+
|
|
163
|
+
Set `changelog:` to a Markdown file path (relative to `docs_dir`) to have mk2conf publish it as a permanent top-level page on every full `mk2conf publish` run. The page title comes from YAML front matter `title:`; it defaults to `"What's New"` if absent.
|
|
164
|
+
|
|
165
|
+
```yaml
|
|
166
|
+
confluence:
|
|
167
|
+
changelog: CHANGELOG.md # relative to docs_dir
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
- The page does **not** need to appear in `nav:` — it is always placed at the top level of the space (or under `parent_page_id` if set).
|
|
171
|
+
- If it also appears in `nav:`, it is published once; no duplication.
|
|
172
|
+
- `--prune` never deletes it — it is a pinned page, not a nav-derived page.
|
|
173
|
+
- Partial runs (`--page` / `--section`) skip the changelog page, consistent with other publish behaviour.
|
|
174
|
+
- Omit the key, or set it to an empty string, to disable the feature entirely.
|
|
175
|
+
|
|
176
|
+
Run `mk2conf install-skill` once after setting `changelog:` to install the changelog AI skill into your AI tool (Claude Code, Copilot, Cursor, Hermes). The skill analyses git changes to your docs since the last `CHANGELOG.md` commit and drafts an entry when the changes qualify as significant.
|
|
177
|
+
|
|
160
178
|
**Your first publish:**
|
|
161
179
|
|
|
162
180
|
```bash
|
|
@@ -172,7 +190,7 @@ mk2conf publish # go live
|
|
|
172
190
|
|
|
173
191
|
| | |
|
|
174
192
|
|---|---|
|
|
175
|
-
| [docs/commands.md](docs/commands.md) | Full flag reference for all
|
|
193
|
+
| [docs/commands.md](docs/commands.md) | Full flag reference for all five commands |
|
|
176
194
|
| [docs/features.md](docs/features.md) | Supported Markdown / Material features and known limitations |
|
|
177
195
|
| [Setup.md](Setup.md) | Development environment setup |
|
|
178
196
|
|
{mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs2confluence.egg-info/SOURCES.txt
RENAMED
|
@@ -9,6 +9,7 @@ src/mkdocs2confluence.egg-info/requires.txt
|
|
|
9
9
|
src/mkdocs2confluence.egg-info/top_level.txt
|
|
10
10
|
src/mkdocs_to_confluence/__init__.py
|
|
11
11
|
src/mkdocs_to_confluence/cli.py
|
|
12
|
+
src/mkdocs_to_confluence/skill_installer.py
|
|
12
13
|
src/mkdocs_to_confluence/compiler/__init__.py
|
|
13
14
|
src/mkdocs_to_confluence/compiler/models.py
|
|
14
15
|
src/mkdocs_to_confluence/compiler/page.py
|
|
@@ -39,12 +40,14 @@ src/mkdocs_to_confluence/preview/__init__.py
|
|
|
39
40
|
src/mkdocs_to_confluence/preview/render.py
|
|
40
41
|
src/mkdocs_to_confluence/preview/server.py
|
|
41
42
|
src/mkdocs_to_confluence/publisher/__init__.py
|
|
43
|
+
src/mkdocs_to_confluence/publisher/changelog.py
|
|
42
44
|
src/mkdocs_to_confluence/publisher/client.py
|
|
43
45
|
src/mkdocs_to_confluence/publisher/executor.py
|
|
44
46
|
src/mkdocs_to_confluence/publisher/http_retry.py
|
|
45
47
|
src/mkdocs_to_confluence/publisher/models.py
|
|
46
48
|
src/mkdocs_to_confluence/publisher/pipeline.py
|
|
47
49
|
src/mkdocs_to_confluence/publisher/planner.py
|
|
50
|
+
src/mkdocs_to_confluence/skills/mkdocs-changelog/SKILL.md
|
|
48
51
|
src/mkdocs_to_confluence/sync/__init__.py
|
|
49
52
|
src/mkdocs_to_confluence/sync/anchoring.py
|
|
50
53
|
src/mkdocs_to_confluence/sync/command.py
|
|
@@ -61,6 +64,8 @@ src/mkdocs_to_confluence/transforms/images.py
|
|
|
61
64
|
src/mkdocs_to_confluence/transforms/internallinks.py
|
|
62
65
|
src/mkdocs_to_confluence/transforms/mermaid.py
|
|
63
66
|
tests/test_abbrevs.py
|
|
67
|
+
tests/test_changelog_config.py
|
|
68
|
+
tests/test_changelog_publish.py
|
|
64
69
|
tests/test_children_macro.py
|
|
65
70
|
tests/test_cli.py
|
|
66
71
|
tests/test_editlink.py
|
|
@@ -84,6 +89,7 @@ tests/test_publish_client.py
|
|
|
84
89
|
tests/test_publish_config.py
|
|
85
90
|
tests/test_publish_pipeline.py
|
|
86
91
|
tests/test_server.py
|
|
92
|
+
tests/test_skill_installer.py
|
|
87
93
|
tests/test_sync_anchoring.py
|
|
88
94
|
tests/test_sync_command.py
|
|
89
95
|
tests/test_sync_comments.py
|
|
@@ -265,6 +265,33 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
265
265
|
help="Suppress progress output.",
|
|
266
266
|
)
|
|
267
267
|
|
|
268
|
+
# --- install-skill ---
|
|
269
|
+
is_ = sub.add_parser(
|
|
270
|
+
"install-skill",
|
|
271
|
+
help="Install the mkdocs-changelog AI skill into detected tool directories.",
|
|
272
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
273
|
+
epilog=(
|
|
274
|
+
"Detected targets (all installed when no --tool given):\n"
|
|
275
|
+
" hermes ~/.hermes/skills/tooling/mkdocs-changelog/SKILL.md\n"
|
|
276
|
+
" github-skills .github/skills/tooling/mkdocs-changelog/SKILL.md\n"
|
|
277
|
+
" claude .claude/commands/changelog.md (frontmatter stripped)\n"
|
|
278
|
+
" copilot .github/instructions/mk2conf-changelog.instructions.md\n"
|
|
279
|
+
" cursor .cursor/rules/mk2conf-changelog.mdc\n"
|
|
280
|
+
"\n"
|
|
281
|
+
"Examples:\n"
|
|
282
|
+
" mk2conf install-skill\n"
|
|
283
|
+
" mk2conf install-skill --tool claude\n"
|
|
284
|
+
" mk2conf install-skill --tool hermes\n"
|
|
285
|
+
),
|
|
286
|
+
)
|
|
287
|
+
is_.add_argument(
|
|
288
|
+
"--tool",
|
|
289
|
+
metavar="NAME",
|
|
290
|
+
default=None,
|
|
291
|
+
choices=["hermes", "github-skills", "claude", "copilot", "cursor"],
|
|
292
|
+
help="Install only to a specific tool (hermes, github-skills, claude, copilot, cursor).",
|
|
293
|
+
)
|
|
294
|
+
|
|
268
295
|
return parser
|
|
269
296
|
|
|
270
297
|
|
|
@@ -288,6 +315,8 @@ def main(argv: list[str] | None = None) -> None:
|
|
|
288
315
|
_cmd_pdf(args)
|
|
289
316
|
elif args.command == "sync-comments":
|
|
290
317
|
_cmd_sync_comments(args)
|
|
318
|
+
elif args.command == "install-skill":
|
|
319
|
+
_cmd_install_skill(args)
|
|
291
320
|
except (ValueError, FileNotFoundError) as exc:
|
|
292
321
|
print(f"error: {exc}", file=sys.stderr)
|
|
293
322
|
sys.exit(1)
|
|
@@ -499,6 +528,8 @@ def _cmd_publish(args: argparse.Namespace) -> None:
|
|
|
499
528
|
sys.exit(1)
|
|
500
529
|
nav_nodes = [node]
|
|
501
530
|
|
|
531
|
+
partial = bool(getattr(args, "page", None) or getattr(args, "section", None))
|
|
532
|
+
|
|
502
533
|
if args.dry_run:
|
|
503
534
|
# When a section is given, show what node was matched so the user can
|
|
504
535
|
# verify the section resolved correctly (section vs. leaf page).
|
|
@@ -513,8 +544,14 @@ def _cmd_publish(args: argparse.Namespace) -> None:
|
|
|
513
544
|
print(f"Dry run: would publish {len(pages)} page(s) to {conf_config.base_url}")
|
|
514
545
|
for page in pages:
|
|
515
546
|
print(f" {page.docs_path} → '{page.title}'")
|
|
547
|
+
if conf_config.changelog_file and not partial:
|
|
548
|
+
from mkdocs_to_confluence.publisher.changelog import _extract_title
|
|
549
|
+
cl_path = config.docs_dir / conf_config.changelog_file
|
|
550
|
+
cl_title = _extract_title(cl_path) or "What's New"
|
|
551
|
+
print(f" {conf_config.changelog_file} → '{cl_title}' (changelog, top-level)")
|
|
516
552
|
return
|
|
517
553
|
|
|
554
|
+
from mkdocs_to_confluence.publisher.changelog import publish_changelog
|
|
518
555
|
from mkdocs_to_confluence.publisher.client import ConfluenceClient, ConfluenceError
|
|
519
556
|
from mkdocs_to_confluence.publisher.pipeline import execute_publish, plan_publish
|
|
520
557
|
|
|
@@ -535,9 +572,6 @@ def _cmd_publish(args: argparse.Namespace) -> None:
|
|
|
535
572
|
nav_nodes, client, config, conf_config,
|
|
536
573
|
space_id=space_id, quiet=args.quiet, full_nav_nodes=all_nav_nodes,
|
|
537
574
|
)
|
|
538
|
-
# --prune is silently disabled for partial publishes (--page / --section)
|
|
539
|
-
# because published_ids would only cover the subset, not the full nav.
|
|
540
|
-
partial = bool(getattr(args, "page", None) or getattr(args, "section", None))
|
|
541
575
|
report = execute_publish(
|
|
542
576
|
plan, client, dry_run=False, space_id=space_id,
|
|
543
577
|
space_key=conf_config.space_key,
|
|
@@ -546,6 +580,13 @@ def _cmd_publish(args: argparse.Namespace) -> None:
|
|
|
546
580
|
prune=getattr(args, "prune", False) and not partial,
|
|
547
581
|
quiet=args.quiet,
|
|
548
582
|
)
|
|
583
|
+
# Changelog is a pinned top-level page — always publish on full runs,
|
|
584
|
+
# skip on partial runs (--page / --section) like all other publish behaviour.
|
|
585
|
+
if not partial:
|
|
586
|
+
publish_changelog(
|
|
587
|
+
config, conf_config, client, space_id,
|
|
588
|
+
space_key=conf_config.space_key, quiet=args.quiet,
|
|
589
|
+
)
|
|
549
590
|
except ConfluenceError as exc:
|
|
550
591
|
print(f"error: {exc}", file=sys.stderr)
|
|
551
592
|
sys.exit(1)
|
|
@@ -599,6 +640,30 @@ def _cmd_publish(args: argparse.Namespace) -> None:
|
|
|
599
640
|
sys.exit(1)
|
|
600
641
|
|
|
601
642
|
|
|
643
|
+
def _cmd_install_skill(args: argparse.Namespace) -> None:
|
|
644
|
+
from mkdocs_to_confluence.skill_installer import install_skill
|
|
645
|
+
|
|
646
|
+
installed = install_skill(tool=getattr(args, "tool", None))
|
|
647
|
+
|
|
648
|
+
if not installed:
|
|
649
|
+
print(
|
|
650
|
+
"No AI tool directories detected and no --tool specified.\n"
|
|
651
|
+
"Run with --tool to install to a specific tool, e.g.:\n"
|
|
652
|
+
" mk2conf install-skill --tool claude",
|
|
653
|
+
file=sys.stderr,
|
|
654
|
+
)
|
|
655
|
+
sys.exit(1)
|
|
656
|
+
|
|
657
|
+
for tool_name, dest in installed:
|
|
658
|
+
print(f" installed [{tool_name}] {dest}")
|
|
659
|
+
|
|
660
|
+
if any(name == "fallback" for name, _ in installed):
|
|
661
|
+
print(
|
|
662
|
+
"\nNo AI tool directories were detected. Skill written to .mk2conf/changelog-skill.md.\n"
|
|
663
|
+
"Copy its contents to your AI tool's custom instructions or skill directory.",
|
|
664
|
+
)
|
|
665
|
+
|
|
666
|
+
|
|
602
667
|
def _cmd_pdf(args: argparse.Namespace) -> None:
|
|
603
668
|
# On macOS with uv/non-system Python, Homebrew libs are not on the dyld search
|
|
604
669
|
# path. Re-exec once with DYLD_LIBRARY_PATH set — the sentinel prevents loops.
|
{mkdocs2confluence-0.12.2 → mkdocs2confluence-0.13.1}/src/mkdocs_to_confluence/loader/config.py
RENAMED
|
@@ -34,6 +34,7 @@ class ConfluenceConfig:
|
|
|
34
34
|
github_token: str | None = None # GitHub PAT (falls back to GITHUB_TOKEN env var)
|
|
35
35
|
github_base_branch: str = "main" # base branch for review PRs
|
|
36
36
|
allow_any_host: bool = False # set True to allow non-Atlassian Cloud base_url hosts
|
|
37
|
+
changelog_file: str | None = None # path relative to docs_dir; None means disabled
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
@dataclass(frozen=True)
|
|
@@ -259,6 +260,22 @@ def load_config(mkdocs_yml: Path) -> MkDocsConfig:
|
|
|
259
260
|
if not token:
|
|
260
261
|
token = os.environ.get("MK2CONF_TOKEN", "")
|
|
261
262
|
|
|
263
|
+
# changelog (optional) — path relative to docs_dir
|
|
264
|
+
changelog_file: str | None = None
|
|
265
|
+
raw_changelog = raw_conf.get("changelog")
|
|
266
|
+
if raw_changelog is not None:
|
|
267
|
+
cl_str = str(raw_changelog).strip()
|
|
268
|
+
if cl_str:
|
|
269
|
+
candidate = (docs_dir / cl_str).resolve()
|
|
270
|
+
try:
|
|
271
|
+
candidate.relative_to(docs_dir)
|
|
272
|
+
except ValueError:
|
|
273
|
+
raise ConfigError(
|
|
274
|
+
f"mkdocs.yml: 'confluence.changelog' path {cl_str!r} "
|
|
275
|
+
"escapes docs_dir. The path must be relative to the docs directory."
|
|
276
|
+
)
|
|
277
|
+
changelog_file = cl_str
|
|
278
|
+
|
|
262
279
|
confluence = ConfluenceConfig(
|
|
263
280
|
base_url=base_url.rstrip("/"),
|
|
264
281
|
space_key=space_key,
|
|
@@ -273,6 +290,7 @@ def load_config(mkdocs_yml: Path) -> MkDocsConfig:
|
|
|
273
290
|
else os.environ.get("GITHUB_TOKEN") or None),
|
|
274
291
|
github_base_branch=str(raw_conf.get("github_base_branch", "main")),
|
|
275
292
|
allow_any_host=allow_any_host,
|
|
293
|
+
changelog_file=changelog_file,
|
|
276
294
|
)
|
|
277
295
|
|
|
278
296
|
# --- extra_css (optional) ---
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""Compile and publish the standalone changelog page."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
import yaml
|
|
11
|
+
|
|
12
|
+
from mkdocs_to_confluence.loader.nav import NavNode
|
|
13
|
+
from mkdocs_to_confluence.publisher.executor import _upload_assets
|
|
14
|
+
from mkdocs_to_confluence.publisher.planner import _xhtml_hash, compile_page
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from mkdocs_to_confluence.loader.config import ConfluenceConfig, MkDocsConfig
|
|
18
|
+
from mkdocs_to_confluence.publisher.client import ConfluenceClient
|
|
19
|
+
|
|
20
|
+
_FRONT_MATTER_RE = re.compile(r"\A---\s*\n(.*?\n?)---\s*\n?", re.DOTALL)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _extract_title(source_path: Path) -> str | None:
|
|
24
|
+
"""Return the ``title`` value from YAML front matter, or ``None`` if absent."""
|
|
25
|
+
try:
|
|
26
|
+
raw = source_path.read_text(encoding="utf-8")
|
|
27
|
+
except OSError:
|
|
28
|
+
return None
|
|
29
|
+
m = _FRONT_MATTER_RE.match(raw)
|
|
30
|
+
if not m:
|
|
31
|
+
return None
|
|
32
|
+
try:
|
|
33
|
+
fm: object = yaml.safe_load(m.group(1))
|
|
34
|
+
except yaml.YAMLError:
|
|
35
|
+
return None
|
|
36
|
+
if not isinstance(fm, dict):
|
|
37
|
+
return None
|
|
38
|
+
val = fm.get("title")
|
|
39
|
+
return str(val).strip() if val else None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def publish_changelog(
|
|
43
|
+
config: MkDocsConfig,
|
|
44
|
+
conf_config: ConfluenceConfig,
|
|
45
|
+
client: ConfluenceClient,
|
|
46
|
+
space_id: str,
|
|
47
|
+
*,
|
|
48
|
+
space_key: str | None = None,
|
|
49
|
+
quiet: bool = False,
|
|
50
|
+
) -> None:
|
|
51
|
+
"""Compile and publish the changelog page if ``conf_config.changelog_file`` is set."""
|
|
52
|
+
if not conf_config.changelog_file:
|
|
53
|
+
return
|
|
54
|
+
|
|
55
|
+
changelog_path = config.docs_dir / conf_config.changelog_file
|
|
56
|
+
if not changelog_path.exists():
|
|
57
|
+
print(
|
|
58
|
+
f" [warn] changelog: file not found: {changelog_path}",
|
|
59
|
+
file=sys.stderr,
|
|
60
|
+
)
|
|
61
|
+
return
|
|
62
|
+
|
|
63
|
+
title = _extract_title(changelog_path) or "What's New"
|
|
64
|
+
|
|
65
|
+
node = NavNode(
|
|
66
|
+
title=title,
|
|
67
|
+
docs_path=str(changelog_path.relative_to(config.docs_dir)),
|
|
68
|
+
source_path=changelog_path,
|
|
69
|
+
level=0,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
if not quiet:
|
|
73
|
+
print(f" compiling '{title}' (changelog)")
|
|
74
|
+
|
|
75
|
+
xhtml, attachments, labels, confluence_status, version_message = compile_page(
|
|
76
|
+
node, config, quiet=quiet
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
xhtml_hash = _xhtml_hash(xhtml)
|
|
80
|
+
existing = client.find_page(space_id, title)
|
|
81
|
+
|
|
82
|
+
if existing is not None and client.get_content_hash(str(existing["id"])) == xhtml_hash:
|
|
83
|
+
if not quiet:
|
|
84
|
+
print(f" unchanged '{title}' (changelog)")
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
parent_id = conf_config.parent_page_id
|
|
88
|
+
|
|
89
|
+
if existing is None:
|
|
90
|
+
page = client.create_page(space_id, title, xhtml, parent_id=parent_id)
|
|
91
|
+
page_id = str(page["id"])
|
|
92
|
+
# Do NOT stamp as managed: _prune_orphans skips unmanaged pages, so
|
|
93
|
+
# this ensures --prune never deletes the changelog page.
|
|
94
|
+
if not quiet:
|
|
95
|
+
print(f" created '{title}' (changelog)")
|
|
96
|
+
else:
|
|
97
|
+
page_id = str(existing["id"])
|
|
98
|
+
version: int = existing["version"]["number"]
|
|
99
|
+
client.update_page(
|
|
100
|
+
page_id, title, xhtml, version + 1,
|
|
101
|
+
parent_id=parent_id,
|
|
102
|
+
version_message=version_message,
|
|
103
|
+
)
|
|
104
|
+
if not quiet:
|
|
105
|
+
print(f" updated '{title}' (changelog)")
|
|
106
|
+
|
|
107
|
+
if attachments:
|
|
108
|
+
_upload_assets(page_id, attachments, config.docs_dir, client, quiet=quiet)
|
|
109
|
+
|
|
110
|
+
try:
|
|
111
|
+
client.set_content_hash(page_id, xhtml_hash)
|
|
112
|
+
except Exception:
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
if labels:
|
|
116
|
+
try:
|
|
117
|
+
client.set_page_labels(page_id, labels)
|
|
118
|
+
except Exception:
|
|
119
|
+
pass
|
|
120
|
+
|
|
121
|
+
if conf_config.full_width:
|
|
122
|
+
try:
|
|
123
|
+
client.set_page_full_width(page_id)
|
|
124
|
+
except Exception:
|
|
125
|
+
pass
|
|
126
|
+
|
|
127
|
+
if confluence_status:
|
|
128
|
+
try:
|
|
129
|
+
client.set_page_status(page_id, confluence_status, space_key=space_key)
|
|
130
|
+
except Exception:
|
|
131
|
+
pass
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Install the bundled mkdocs-changelog skill into detected AI tool directories."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
_FRONT_MATTER_RE = re.compile(r"\A---\s*\n.*?\n---\s*\n?", re.DOTALL)
|
|
9
|
+
_SKILL_NAME = "mkdocs-changelog"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _read_skill() -> str:
|
|
13
|
+
from importlib.resources import files
|
|
14
|
+
return files("mkdocs_to_confluence").joinpath(f"skills/{_SKILL_NAME}/SKILL.md").read_text(encoding="utf-8")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _strip_front_matter(content: str) -> str:
|
|
18
|
+
return _FRONT_MATTER_RE.sub("", content).lstrip("\n")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def install_skill(
|
|
22
|
+
project_dir: Path | None = None,
|
|
23
|
+
tool: str | None = None,
|
|
24
|
+
) -> list[tuple[str, Path]]:
|
|
25
|
+
"""Detect AI tools and install the changelog skill.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
project_dir: Root of the current project (default: ``Path.cwd()``).
|
|
29
|
+
tool: If given, install only to this tool name (``hermes``, ``claude``,
|
|
30
|
+
``copilot``, ``cursor``). Skips detection and always writes.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
List of ``(tool_name, install_path)`` pairs for each file written.
|
|
34
|
+
"""
|
|
35
|
+
if project_dir is None:
|
|
36
|
+
project_dir = Path.cwd()
|
|
37
|
+
|
|
38
|
+
content_full = _read_skill()
|
|
39
|
+
content_body = _strip_front_matter(content_full)
|
|
40
|
+
|
|
41
|
+
installed: list[tuple[str, Path]] = []
|
|
42
|
+
explicit = tool is not None
|
|
43
|
+
|
|
44
|
+
def _want(name: str) -> bool:
|
|
45
|
+
return tool is None or tool == name
|
|
46
|
+
|
|
47
|
+
# Hermes — user-level, installed regardless of project directory
|
|
48
|
+
if _want("hermes"):
|
|
49
|
+
hermes_dir = Path.home() / ".hermes"
|
|
50
|
+
if explicit or hermes_dir.exists():
|
|
51
|
+
dest = hermes_dir / "skills" / "tooling" / _SKILL_NAME / "SKILL.md"
|
|
52
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
53
|
+
dest.write_text(content_full, encoding="utf-8")
|
|
54
|
+
installed.append(("hermes", dest))
|
|
55
|
+
|
|
56
|
+
# .github/skills — project-level, skills repo format (full SKILL.md)
|
|
57
|
+
if _want("github-skills"):
|
|
58
|
+
gh_skills = project_dir / ".github" / "skills"
|
|
59
|
+
if explicit or gh_skills.exists():
|
|
60
|
+
dest = gh_skills / "tooling" / _SKILL_NAME / "SKILL.md"
|
|
61
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
62
|
+
dest.write_text(content_full, encoding="utf-8")
|
|
63
|
+
installed.append(("github-skills", dest))
|
|
64
|
+
|
|
65
|
+
# Claude Code — project-level, YAML frontmatter stripped
|
|
66
|
+
if _want("claude"):
|
|
67
|
+
claude_dir = project_dir / ".claude"
|
|
68
|
+
if explicit or claude_dir.exists():
|
|
69
|
+
dest = claude_dir / "commands" / "changelog.md"
|
|
70
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
71
|
+
dest.write_text(content_body, encoding="utf-8")
|
|
72
|
+
installed.append(("claude", dest))
|
|
73
|
+
|
|
74
|
+
# GitHub Copilot — project-level, body only as .instructions.md
|
|
75
|
+
if _want("copilot"):
|
|
76
|
+
copilot_marker = project_dir / ".github" / "copilot-instructions.md"
|
|
77
|
+
if explicit or copilot_marker.exists():
|
|
78
|
+
dest = project_dir / ".github" / "instructions" / "mk2conf-changelog.instructions.md"
|
|
79
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
80
|
+
dest.write_text(content_body, encoding="utf-8")
|
|
81
|
+
installed.append(("copilot", dest))
|
|
82
|
+
|
|
83
|
+
# Cursor — project-level, body as .mdc
|
|
84
|
+
if _want("cursor"):
|
|
85
|
+
cursor_dir = project_dir / ".cursor"
|
|
86
|
+
if explicit or cursor_dir.exists():
|
|
87
|
+
dest = cursor_dir / "rules" / "mk2conf-changelog.mdc"
|
|
88
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
89
|
+
dest.write_text(content_body, encoding="utf-8")
|
|
90
|
+
installed.append(("cursor", dest))
|
|
91
|
+
|
|
92
|
+
# Fallback — no markers detected in auto mode
|
|
93
|
+
if not installed and not explicit:
|
|
94
|
+
dest = project_dir / ".mk2conf" / "changelog-skill.md"
|
|
95
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
96
|
+
dest.write_text(content_full, encoding="utf-8")
|
|
97
|
+
installed.append(("fallback", dest))
|
|
98
|
+
|
|
99
|
+
return installed
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mkdocs-changelog
|
|
3
|
+
description: Analyse doc changes since the last CHANGELOG.md update and draft a major-change entry if the changes qualify.
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
tags: [documentation, git, changelog, mkdocs, confluence]
|
|
6
|
+
specificity: context-specific
|
|
7
|
+
tool_agnostic: true
|
|
8
|
+
authors: [Anders Hybertz]
|
|
9
|
+
tested_on: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# MkDocs Changelog Entry
|
|
13
|
+
|
|
14
|
+
Analyse git changes to the docs directory since the last `CHANGELOG.md` commit. If any changes qualify as **MAJOR**, draft a dated changelog entry and prepend it to `CHANGELOG.md`. If not, explain why and exit without modifying any file.
|
|
15
|
+
|
|
16
|
+
## When to Use
|
|
17
|
+
|
|
18
|
+
- After making one or more documentation changes and before running `mk2conf publish`
|
|
19
|
+
- Any point in the writing flow when you want to assess whether a "What's New" entry is warranted
|
|
20
|
+
|
|
21
|
+
## Steps
|
|
22
|
+
|
|
23
|
+
1. **Find the baseline** — run `git log --follow -1 --format="%H" -- <docs_dir>/CHANGELOG.md` to get the last commit that touched `CHANGELOG.md`. If no commit is found, use the root commit as the baseline.
|
|
24
|
+
|
|
25
|
+
2. **Collect doc changes** — run `git diff <baseline>..HEAD -- <docs_dir>/` to see everything that changed in the docs directory since that baseline.
|
|
26
|
+
|
|
27
|
+
3. **Read the existing changelog** — read `<docs_dir>/CHANGELOG.md` for context on what was previously recorded.
|
|
28
|
+
|
|
29
|
+
4. **Decide: is this MAJOR?**
|
|
30
|
+
|
|
31
|
+
**MAJOR criteria — any one of these qualifies:**
|
|
32
|
+
- A new top-level documentation area or section added (a new folder or nav section that didn't exist before)
|
|
33
|
+
- A significant area deleted or substantially restructured (not just moved or renamed)
|
|
34
|
+
- A fundamental definition, concept, or policy changed in a way that affects how readers understand the subject
|
|
35
|
+
|
|
36
|
+
**NOT major — do not draft an entry for:**
|
|
37
|
+
- Typo fixes, grammar corrections, spelling
|
|
38
|
+
- Formatting, diagram adjustments, image swaps
|
|
39
|
+
- Small additions (a paragraph, a note, a clarification) that do not change the substance
|
|
40
|
+
- Rewordings that preserve the original meaning
|
|
41
|
+
- Internal restructuring with no reader-facing impact
|
|
42
|
+
|
|
43
|
+
5. **If NOT MAJOR** — report what was found, explain in one sentence why it did not qualify, and stop. Do not modify any file.
|
|
44
|
+
|
|
45
|
+
6. **If MAJOR** — draft an entry using this format and prepend it to `CHANGELOG.md`:
|
|
46
|
+
|
|
47
|
+
```markdown
|
|
48
|
+
## YYYY-MM-DD — Brief title describing the major change
|
|
49
|
+
|
|
50
|
+
One or two sentences summarising what fundamentally changed and why it matters to readers.
|
|
51
|
+
|
|
52
|
+
### Added
|
|
53
|
+
- …
|
|
54
|
+
|
|
55
|
+
### Changed
|
|
56
|
+
- …
|
|
57
|
+
|
|
58
|
+
### Removed
|
|
59
|
+
- …
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Rules for the entry:
|
|
63
|
+
- Date is today's date in `YYYY-MM-DD` format
|
|
64
|
+
- Sections (`Added`, `Changed`, `Removed`) are included only when non-empty
|
|
65
|
+
- No version numbers — dates only
|
|
66
|
+
- Title is a brief, reader-facing description (not a git commit message)
|
|
67
|
+
|
|
68
|
+
Prepend the entry above any existing entries in `CHANGELOG.md`. Do not commit — the user reviews, edits if needed, and commits manually.
|
|
69
|
+
|
|
70
|
+
## Pitfalls
|
|
71
|
+
|
|
72
|
+
- **Do not draft an entry for every change.** The changelog is for readers who want to know what fundamentally changed, not a git log. When in doubt, do not draft.
|
|
73
|
+
- **Do not commit.** Always leave the file for the user to review. The user runs `git add` and `git commit` themselves before publishing.
|
|
74
|
+
- **If CHANGELOG.md does not exist yet**, create it with just the new entry (no header needed).
|
|
75
|
+
|
|
76
|
+
## Verification
|
|
77
|
+
|
|
78
|
+
After drafting, show the user the proposed entry in the terminal and remind them to review `CHANGELOG.md` before committing and running `mk2conf publish`.
|