A Markdown toolbox — convert, template, and publish Markdown documents
Project description
marksmith
A Markdown toolbox — write docs in Markdown, ship them as polished DOCX or publish them to Confluence.
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
-
Create a
.docxtemplate in Word with Jinja2-style placeholders for metadata sourced from your Markdown front-matter:{{ title }} {{ version }} {{ author }} {{ date }} {{ classification }}
-
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 thepmodifier), not{{ ... }}. Thepmodifier inserts a paragraph-level sub-document rather than plain text, so all headings, lists, tables, and code blocks are preserved. -
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:
.envin the current working directory.envin your home directory (~/.envon Linux/macOS,%USERPROFILE%\.envon 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
- Bump
__version__inmarksmith/__init__.py. - Commit and push.
- Create a GitHub Release with a tag matching the version (e.g.
v0.2.0). - The publish workflow fires automatically and publishes to PyPI via OIDC Trusted Publisher — no API tokens needed.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file marksmith-0.4.0.tar.gz.
File metadata
- Download URL: marksmith-0.4.0.tar.gz
- Upload date:
- Size: 22.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a225f79dce9a17c6475e81ce7e5290e06f5af5d9f7c657c0587a9a258c0f455c
|
|
| MD5 |
eafc00bb38f232a1fa6cf989b0edcc83
|
|
| BLAKE2b-256 |
42ef2075f5e60bafe343f579b6e80e90672a21a094b74e22fbbdba1247547f3b
|
Provenance
The following attestation bundles were made for marksmith-0.4.0.tar.gz:
Publisher:
publish.yml on tkdpython/marksmith
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
marksmith-0.4.0.tar.gz -
Subject digest:
a225f79dce9a17c6475e81ce7e5290e06f5af5d9f7c657c0587a9a258c0f455c - Sigstore transparency entry: 1115699215
- Sigstore integration time:
-
Permalink:
tkdpython/marksmith@aebd1a9a381aa7d9c835bf88acfb7f2567355e9d -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/tkdpython
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@aebd1a9a381aa7d9c835bf88acfb7f2567355e9d -
Trigger Event:
release
-
Statement type:
File details
Details for the file marksmith-0.4.0-py3-none-any.whl.
File metadata
- Download URL: marksmith-0.4.0-py3-none-any.whl
- Upload date:
- Size: 21.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2caf5f336f4bb92c07046174aa564f1195dd9f825585e0d2dc985c8598082441
|
|
| MD5 |
6119403085d69b9434da8be0a10b8f2f
|
|
| BLAKE2b-256 |
5b227fc5dab8c103acd975ed011f60ee56c0e3c004e2630a6207c4dc565095b7
|
Provenance
The following attestation bundles were made for marksmith-0.4.0-py3-none-any.whl:
Publisher:
publish.yml on tkdpython/marksmith
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
marksmith-0.4.0-py3-none-any.whl -
Subject digest:
2caf5f336f4bb92c07046174aa564f1195dd9f825585e0d2dc985c8598082441 - Sigstore transparency entry: 1115699263
- Sigstore integration time:
-
Permalink:
tkdpython/marksmith@aebd1a9a381aa7d9c835bf88acfb7f2567355e9d -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/tkdpython
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@aebd1a9a381aa7d9c835bf88acfb7f2567355e9d -
Trigger Event:
release
-
Statement type: