Skip to main content

marksmith

A Markdown toolbox — write docs in Markdown, ship them as polished DOCX or publish them to Confluence.

PyPI Python CI License: MIT

Installation

pip install marksmith

Optional extras for template support:

pip install marksmith[template]

Optional extras for Confluence publishing:

pip install marksmith[confluence]

Quick start

# Explicit output path
marksmith to-docx my-doc.md output.docx

# Output path taken from docx-path in the file's front-matter
marksmith to-docx my-doc.md

# Recursively convert all .md files in a directory tree that have docx-path set
marksmith to-docx --directory docs/

# Or via python -m
python -m marksmith to-docx my-doc.md output.docx

Markdown front-matter

You can add a YAML front-matter block at the top of your Markdown file. The metadata is written to the DOCX core properties (title, author, etc.) and is also available as Jinja2 template variables when using --template.

---
title:          My Document
version:        1.0
author:         Fred Bloggs
date:           2026-03-16
classification: Internal
docx-path:      '%MY_DOCS%\Reports\My Document.docx'
---

# My Document

Content goes here...

docx-path

The optional docx-path key sets the default output path for marksmith to-docx. If you omit the output argument on the command line, the path from front-matter is used. Environment variables are expanded automatically (%VAR% on Windows, $VAR on Linux/macOS).

Windows paths: Always use single quotes around the value in YAML. In double-quoted YAML strings, backslashes are escape characters and will corrupt the path.

# ✅ Correct
docx-path: '%MY_DOCS%\Reports\myfile.docx'

# ❌ Wrong — \R and \m etc. are YAML escape sequences
docx-path: "%MY_DOCS%\Reports\myfile.docx"

Supported Markdown elements

Element Status
Headings H1 – H6 ✅
Bold / italic / inline code ✅
Fenced and indented code blocks ✅
Unordered lists (nested) ✅
Ordered lists (nested) ✅
Block-quotes ✅
Tables ✅
Thematic breaks (horizontal rules) ✅
Strikethrough ✅
Links (text rendered, no hyperlink) ⚠️
Images ⚠️ placeholder text only
Inline HTML ➖ ignored

Template support

Keep your content in plain Markdown while producing brand-consistent DOCX output from a corporate template.

pip install marksmith[template]
marksmith to-docx my-doc.md output.docx --template company-template.docx

MARKSMITH_TEMPLATE environment variable

If you always use the same template, set MARKSMITH_TEMPLATE once in your environment and marksmith will use it automatically — no --template argument needed. An explicit --template argument always takes priority.

# Windows (set permanently via System Properties → Environment Variables)
$env:MARKSMITH_TEMPLATE = "C:\Users\You\Templates\company-template.docx"

# Then just run — template is applied automatically
marksmith to-docx my-doc.md

How it works

  1. Create a .docx template in Word with Jinja2-style placeholders for metadata sourced from your Markdown front-matter:

    {{ title }}        {{ version }}      {{ author }}
    {{ date }}         {{ classification }}
    
  2. Add a {{p marksmith_content }} paragraph alone on its own line at the exact point where the Markdown body should be inserted:

    {{p marksmith_content }}
    

    Important: Use {{p ... }} (with the p modifier), not {{ ... }}. The p modifier inserts a paragraph-level sub-document rather than plain text, so all headings, lists, tables, and code blocks are preserved.

  3. Run the conversion — marksmith will:

    • Render all front-matter metadata into the Jinja2 placeholders.
    • Convert the Markdown body to native DOCX content.
    • Insert the body at {{p marksmith_content }}.
    • Save the merged document.

Style inheritance

Content is inserted as a sub-document, so heading and paragraph styles are matched by name against those in your template. If your template defines Heading 1 with a custom font and colour, the converted content will pick it up automatically.


Publishing to Confluence

Publish Markdown files directly to a Confluence space.

pip install marksmith[confluence]

Credentials

Create a .env file with your Confluence URL and a Personal Access Token. marksmith checks the following locations in order:

  1. .env in the current working directory
  2. .env in your home directory (~/.env on Linux/macOS, %USERPROFILE%\.env on Windows)
CONFLUENCE_URL=https://your-confluence.example.com
CONFLUENCE_TOKEN=your-personal-access-token

Front-matter fields

Each file must include a YAML front-matter block that tells marksmith where to publish the page:

---
title: My Page Title
space: MYSPACE
parent_title: My Parent Page   # resolved by title; or use parent_id: 12345
labels:
  - my-label
page-properties:
  description: A short description of this page
  created_by: Fred Bloggs
  version: "1.0"
  document_status: DRAFT       # DRAFT (yellow) | PUBLISHED (green) | other (red)
---

# My Page Title

Content goes here...
Field Required Description
title Yes Confluence page title
space Yes Confluence space key
parent_title One of Title of the parent page (resolved at publish time)
parent_id One of Numeric Confluence page ID of the parent
labels No List of labels to apply
page-properties No Renders a Page Properties macro at the top of the page

If the page already exists it is updated; otherwise it is created.

Commands

# Publish a single file
marksmith to-confluence --upload-file path/to/my-doc.md

# Publish all .md files in a directory
marksmith to-confluence --upload-directory path/to/docs/

# Publish a tree of repositories (each must have a confluence.yml at its root)
marksmith to-confluence --process-repo-tree path/to/repos/

Repository tree mode — confluence.yml

When using --process-repo-tree, each subdirectory that contains a confluence.yml is processed. The file defines the target space, parent page, and index page title for that repository:

repo-docs-path: docs/               # relative path to the docs directory
conflu-directory-title: My Service  # title of the index page created in Confluence
conflu-parent-id: "12345"           # Confluence page ID to create the index under
conflu-space-id: MYSPACE            # Confluence space key

All four fields are mandatory.

Additional features

Image attachments — local images referenced in Markdown are automatically uploaded as attachments to the published page.

Confluence link replacements — annotate a Markdown link with a <!-- replace_link(<page_id>) --> comment to rewrite it as a Confluence internal link at publish time:

[See related page](./other.md) <!-- replace_link(98765) -->

Roadmap

Action Description
to-docx Markdown → DOCX ✔️
to-docx --template Merge into branded DOCX template ✔️
to-docx (docx-path) Output path from front-matter docx-path key ✔️
to-docx --directory Recursively convert all files with docx-path set ✔️
to-confluence Publish Markdown to Confluence ✔️
lint Validate Markdown style and structure
toc Generate / update table of contents
diff Show structural diff between two Markdown files
Images Embed local images via run.add_picture()
Hyperlinks Full OOXML hyperlink support

Development

git clone https://github.com/tkdpython/marksmith
cd marksmith
pip install -e .[dev,template]

# Run tests
pytest

# Lint
ruff check .

Releasing

  1. Bump __version__ in marksmith/__init__.py.
  2. Commit and push.
  3. Create a GitHub Release with a tag matching the version (e.g. v0.2.0).
  4. The publish workflow fires automatically and publishes to PyPI via OIDC Trusted Publisher — no API tokens needed.

License

MIT — see LICENSE.

Metadata

Release files for marksmith 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for marksmith 0.5.0
File Size Uploaded
marksmith-0.5.0.tar.gz 22.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for marksmith 0.5.0
File Interpreter ABI Platform
marksmith-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 44.1 kB

Release files / marksmith-0.5.0.tar.gz

Download URL marksmith-0.5.0.tar.gz
Size 22.3 kB
Tags Source
SHA-256 checksum
How to use checksums
5b2836fd73f72b60460612dd7064f1a782682463f76622103ad65b0b1a2009c9
BLAKE2b-256 checksum
How to use checksums
4b579197116ae57a095ae8e40313f436be120db0773f41b8ce3e36c1a70b725d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 17, 2026.

Transparency log

Release files / marksmith-0.5.0-py3-none-any.whl

Download URL marksmith-0.5.0-py3-none-any.whl
Size 21.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
08fb7c0ee6fb44f3a1a15f77451da7bfdc48fe67f2348c6e83c94853771b41b0
BLAKE2b-256 checksum
How to use checksums
6f3834786dd9b5d3f3e61e276677fbc3c99c989c5f42ce040e805de857b5a7d7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 17, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page