Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ Two-way Markdown ↔ Confluence sync from the command line, written in Python.

Confluence MD allows you to create, edit and download Confluence Cloud
pages as local Markdown files — all through the REST API, with a
single-file script and no server-side install.
single-file script and no server-side install. It works page by page or
on whole page trees, mirroring them to local folders and back.

Round-tripping is the point: every supported element converts in both
directions, so a page can be downloaded, edited locally in your editor,
and pushed back without losing structure.
and pushed back without losing structure. A version marker in each
downloaded file ensures nobody's concurrent edits are overwritten along
the way.

---

Expand Down
9 changes: 7 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Architecture

How the single module is organised and why the non-obvious parts — placeholder
substitution, version markers, tree state — work the way they do.
substitution, version markers, tree state — work the way they do. Read this
before changing either conversion pipeline, so the invariants the round-trip
tests rely on stay intact.

- [Module layout](#module-layout)
- [The two conversion pipelines](#the-two-conversion-pipelines)
Expand Down Expand Up @@ -34,6 +36,8 @@ read top to bottom:

Both pipelines are pure functions from string to string (plus optional
collectors), which is what makes them unit-testable without any network.
Every API call stays in the CLI layer, which passes strings in and writes
the results out.

**Upload** (`md_to_confluence_storage`): pre-process strikethrough (skipping
code spans and fences), let python-markdown produce HTML, then walk the
Expand Down Expand Up @@ -105,7 +109,8 @@ content.

Both directions mirror the same layout: `<name>.md` is a page, a sibling
`<name>/` folder holds its children, `<name>_attachments/` holds its image
attachments.
attachments. Because the layouts match, whatever one direction writes, the
other can consume unchanged.

**Download** (`download_page`): recursion threads a `_tree` dict through the
calls, recording `title → written path` for every page. Page links are
Expand Down
13 changes: 9 additions & 4 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Configuration

Everything needed to get from a fresh clone to a working setup: install the
dependencies, generate an API token, and store the credentials in a `.env` file.
dependencies, generate an API token, and store the credentials in a `.env`
file. Each step takes a minute or two and only needs doing once per machine.

- [Prerequisites](#prerequisites)
- [Installation](#installation)
Expand Down Expand Up @@ -33,7 +34,8 @@ This installs the four dependencies: `atlassian-python-api`, `python-dotenv`,
`markdown` and `beautifulsoup4`.

Alternatively, install the project as a package to get a `confluence-md`
command on your PATH (usable anywhere instead of `python src/confluence_md.py`):
command on your PATH, which lets you run the tool from any directory instead
of invoking `python src/confluence_md.py` from a repository checkout:

```bash
pip install .
Expand All @@ -46,6 +48,8 @@ confluence-md --version

The script authenticates with an API token rather than your password.
Atlassian Cloud does **not** allow authentication with your regular password.
Tokens can be revoked individually at any time, so create one dedicated to
this tool.

1. Go to [https://id.atlassian.com/manage-profile/security/api-tokens](https://id.atlassian.com/manage-profile/security/api-tokens)
2. Log in with your Atlassian account
Expand All @@ -70,8 +74,9 @@ You can find it in your browser address bar when you open Confluence.

## 3. Set up the `.env` file

The three credentials live in a `.env` file that the script loads at startup.
Copy the template from the project root and fill in your values:
The three credentials live in a `.env` file that the script loads at startup
from the directory it runs in. Copy the template from the project root and
fill in the three values collected in the previous steps:

```bash
cp .env.example .env
Expand Down
14 changes: 9 additions & 5 deletions docs/conversion.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ break the Markdown table structure.
## Table of Contents — `[TOC]`

**Upload:** A standalone `[TOC]` line in your Markdown becomes the Confluence
**Table of Contents macro**, which auto-generates a clickable TOC on the page.
**Table of Contents macro**, which auto-generates a clickable TOC on the page
and keeps itself up to date whenever the page's headings change.

**Download:** The TOC macro becomes a list of anchor links to the page headings:

Expand All @@ -100,7 +101,8 @@ Each link points to the corresponding `#heading-slug` within the Markdown file.
## Child Pages — `[CHILD_PAGES]`

**Upload:** A standalone `[CHILD_PAGES]` line in your Markdown becomes the
Confluence **Children Display macro**, which auto-lists all child pages.
Confluence **Children Display macro**, which auto-lists all child pages of
the page and updates dynamically as children are added or removed.

**Download:** The Children Display macro becomes a list of links to the child
pages:
Expand All @@ -127,7 +129,7 @@ by URL without uploading anything.

**Download:** images backed by page attachments are saved into a
`<name>_attachments/` folder next to the output file, and the Markdown links
point there:
point there, so the images render correctly in any local Markdown preview:

```markdown
![diagram](My_Page_attachments/diagram.png)
Expand All @@ -141,15 +143,17 @@ the same files.
## Task lists

Markdown checkbox lists map to Confluence action-item task lists and back,
including the checked state and inline formatting in the item text:
including the checked state and inline formatting in the item text, so a
to-do list can be ticked off on either side and synced across:

```markdown
- [ ] open task
- [x] completed task
```

A list converts as a task list only when **every** item starts with a
checkbox; lists mixing checkbox and plain items stay regular bullet lists.
checkbox; lists mixing checkbox and plain items stay regular bullet lists,
so no list is ever converted half-way into a mix of tasks and text.

---

Expand Down
5 changes: 4 additions & 1 deletion docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ Symptom first: find the error message the script printed, then apply the fix.
## Configuration and authentication

Errors in this group appear before any page content is transferred — the
script either refuses to start or Confluence refuses the credentials.
script either refuses to start or Confluence refuses the credentials. Fixing
them is always a matter of configuration, never of page content.

| Error | Cause | Fix |
|---|---|---|
Expand All @@ -25,6 +26,8 @@ script either refuses to start or Confluence refuses the credentials.

Errors in this group mean the page you pointed at could not be resolved —
either the URL was not understood or the page is not visible to your account.
Check the URL in a browser first: if it does not open there, the tool cannot
reach it either.

| Error | Cause | Fix |
|---|---|---|
Expand Down
9 changes: 6 additions & 3 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ python src/confluence_md.py download <page_url> [output.md] [--recur

## `upload` — create a new child page

Creates a new page as a child of the given parent. Aborts with an error if a
page with the same title already exists in the space — use `edit` in that case.
Creates a new page as a child of the given parent. Confluence requires titles
to be unique within a space, so the command aborts with an error if a page
with the same title already exists — use `edit` in that case.

```bash
python src/confluence_md.py upload <file.md> <parent_url> <title>
Expand Down Expand Up @@ -51,7 +52,8 @@ python src/confluence_md.py upload release_notes.md \
```

The parent URL is the page in Confluence under which the new page will appear.
Open that page in your browser and copy the address bar URL.
Open that page in your browser and copy the address bar URL — both the pretty
`/spaces/.../pages/...` form and the `?pageId=...` form are accepted.

---

Expand Down Expand Up @@ -120,6 +122,7 @@ python src/confluence_md.py download <page_url> [output.md] [--recursive]

Images embedded from page attachments are saved into a `<name>_attachments/`
folder next to the output file (created only when the page has such images).
External images referenced by URL are left as-is and never downloaded.

The first line of the output file is a version marker comment
(`<!-- confluence-md page_id=... version=... -->`). Leave it in place: `edit`
Expand Down