Skip to main content

Convert Markdown to Atlassian Document Format (ADF) and upload to Confluence

Project description

md-to-adf

Convert Markdown to Atlassian Document Format (ADF) and publish to Confluence Cloud.

Tests PyPI License: MIT

What it does

md-to-adf takes a Markdown file and converts it to the JSON-based Atlassian Document Format (ADF) that Confluence Cloud requires for its REST API. It handles headings, paragraphs, bold/italic/code inline formatting, fenced code blocks, bullet and ordered lists, blockquotes, horizontal rules, tables, and Mermaid diagrams. Once converted, the built-in upload command creates or updates a Confluence page in a single step, so you can keep documentation in version control and push it to Confluence with one command.

Install

pip

pip install md-to-adf

npm (installs the Python package via pip automatically)

npm install -g md2adf

Homebrew

brew tap imzak31/md-to-adf
brew install md-to-adf

Quick start

Convert a Markdown file to ADF JSON:

md-to-adf convert docs/my-page.md

Convert and write to a file:

md-to-adf convert docs/my-page.md --output my-page.adf.json

Convert and validate the output:

md-to-adf convert docs/my-page.md --validate

Upload to Confluence:

md-to-adf upload docs/my-page.md \
  --title "My Page" \
  --space ENG \
  --parent 12345

Upload using environment variables (no flags needed after setup):

export MD_TO_ADF_DOMAIN=myorg.atlassian.net
export MD_TO_ADF_EMAIL=me@example.com
export MD_TO_ADF_TOKEN=my-api-token
export MD_TO_ADF_SPACE=ENG

md-to-adf upload docs/my-page.md --title "My Page"

Setup

Run the interactive wizard to store your Confluence credentials once:

md-to-adf init

The wizard prompts for your Confluence domain, email address, and API token, then writes them to ~/.md-to-adf/config.toml. After running init, the upload command works without any flags.

To generate a Confluence API token, visit: https://id.atlassian.com/manage-profile/security/api-tokens

Configuration

Config file location: ~/.md-to-adf/config.toml

Example config file:

[confluence]
domain = "myorg.atlassian.net"
email = "me@example.com"
token = "my-api-token"
space_key = "ENG"

[mermaid]
strategy = "auto"

Settings reference

Setting Config key Env var CLI flag
Domain confluence.domain MD_TO_ADF_DOMAIN --domain
Email confluence.email MD_TO_ADF_EMAIL --email
Token confluence.token MD_TO_ADF_TOKEN --token
Space confluence.space_key MD_TO_ADF_SPACE --space
Mermaid mermaid.strategy MD_TO_ADF_MERMAID --mermaid

Priority: CLI flags > env vars > config file > defaults

CLI Commands

init — Interactive setup wizard

md-to-adf init

Prompts for Confluence credentials and writes ~/.md-to-adf/config.toml.


convert — Convert Markdown to ADF

md-to-adf convert <file> [options]
Option Description
--output FILE Write ADF JSON to FILE instead of stdout
--validate Validate the ADF output after conversion
--mermaid STRATEGY Mermaid handling: auto, macro, image, code

Examples:

# Print ADF JSON to stdout
md-to-adf convert README.md

# Save to file and validate
md-to-adf convert docs/guide.md --output guide.adf.json --validate

upload — Upload to Confluence

md-to-adf upload <file> [options]
Option Description
--title TEXT Page title (default: filename stem)
--space KEY Confluence space key
--parent ID Parent page ID
--domain HOST Confluence domain
--email EMAIL Atlassian account email
--token TOKEN Atlassian API token
--mermaid STRATEGY Mermaid handling strategy

Examples:

# Upload using config file credentials
md-to-adf upload docs/architecture.md --title "Architecture Overview"

# Upload to a specific space with a parent page
md-to-adf upload docs/guide.md \
  --title "User Guide" \
  --space ENG \
  --parent 98765

validate — Validate ADF JSON

md-to-adf validate <file>

Validates a Markdown file (by converting first) or a raw ADF JSON file against the ADF schema.

md-to-adf validate docs/my-page.md
md-to-adf validate output.adf.json

spaces — List Confluence spaces

md-to-adf spaces

Lists all spaces accessible with your configured credentials. Useful for finding space keys.

Mermaid Support

Mermaid diagrams in fenced code blocks (```mermaid) are handled according to the selected strategy:

Strategy Description
auto Use macro if the Mermaid for Confluence app is installed, otherwise fall back to code
macro Render as a Confluence Mermaid macro (requires the Mermaid app)
image Render the diagram to a PNG and attach it to the page
code Preserve the diagram source as a code block

Set the strategy in config, env var, or per-command:

md-to-adf upload diagram.md --mermaid image

Claude Code Skill

md-to-adf ships a Claude Code skill that lets you upload the current file to Confluence from inside your editor with a single slash command.

Install the skill:

# Copy the skill to your Claude Code skills directory
cp -r /path/to/md-to-adf/skill ~/.claude/skills/md-to-confluence

Or install via the package (after pip install md-to-adf):

md-to-adf-install-skill

Use the skill inside Claude Code:

/md-to-confluence

The skill reads the current file, calls md-to-adf upload, and reports the resulting Confluence URL.

Python Library API

You can use md-to-adf as a library in your own Python projects:

from md_to_adf import convert, validate

# Convert Markdown string to ADF dict
markdown = "# Hello\n\nThis is **bold** text."
adf = convert(markdown)
print(adf)  # {"version": 1, "type": "doc", "content": [...]}

# Validate an ADF dict
errors = validate(adf)
if errors:
    print("Validation errors:", errors)
else:
    print("Valid ADF document")

Upload programmatically:

from md_to_adf import convert
from md_to_adf.confluence.auth import build_token_auth_header
from md_to_adf.confluence.client import ConfluenceClient

adf = convert(open("docs/page.md").read())

auth = build_token_auth_header("me@example.com", "my-api-token")
client = ConfluenceClient("myorg.atlassian.net", auth)

result = client.create_page(adf, space_key="ENG", title="My Page")
print(f"Published: https://myorg.atlassian.net/wiki{result['_links']['webui']}")

Contributing

  1. Fork the repository and create a feature branch.
  2. Install development dependencies: pip install -e ".[dev]"
  3. Run the test suite: pytest tests/ -v
  4. Ensure all tests pass and add tests for new functionality.
  5. Open a pull request with a clear description of the change.

The test suite covers the converter, validator, CLI, and Confluence client (with mocked HTTP). New features should include unit tests.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

md_to_adf-1.0.0.tar.gz (33.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

md_to_adf-1.0.0-py3-none-any.whl (25.0 kB view details)

Uploaded Python 3

File details

Details for the file md_to_adf-1.0.0.tar.gz.

File metadata

  • Download URL: md_to_adf-1.0.0.tar.gz
  • Upload date:
  • Size: 33.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for md_to_adf-1.0.0.tar.gz
Algorithm Hash digest
SHA256 e4385c8735179ee12846fd4108c578d7fef7a306546c96151aafd3412f1660fb
MD5 327c00786e6877ccbcbf25d8047622d4
BLAKE2b-256 68f54c154cf95d42dad3f136191d2a242b2a80c096a9a79540dc2530afb3ecdf

See more details on using hashes here.

Provenance

The following attestation bundles were made for md_to_adf-1.0.0.tar.gz:

Publisher: release.yml on imzak31/md_to_adf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file md_to_adf-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: md_to_adf-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 25.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for md_to_adf-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9e2473ce00e8270d791e7a50a42c8eae1ad64496da7ade656fd4e96e0819bd4f
MD5 3594aa2dc4862dbf115a643edfe9e5a9
BLAKE2b-256 70a9c11fb35494c9ff473d591c7c2b391fe9eba6ddc9e7856ba05c735884c944

See more details on using hashes here.

Provenance

The following attestation bundles were made for md_to_adf-1.0.0-py3-none-any.whl:

Publisher: release.yml on imzak31/md_to_adf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page