Convert Obsidian-flavored Markdown to PDF and DOCX via a 5-stage pipeline
Project description
obsidian-export
Convert Obsidian-flavored Markdown to PDF and DOCX. Handles wikilinks, embeds, callouts, Mermaid diagrams, and frontmatter — producing clean, professional documents via a 5-stage pipeline (vault ops → preprocess → mermaid → SVG → pandoc).
Install
pip install obsidian-export
System Dependencies
| Dependency | Required | Purpose |
|---|---|---|
| pandoc >= 3.5 | Yes | Markdown to PDF/DOCX conversion |
| tectonic >= 0.15 | Yes (PDF) | XeLaTeX PDF engine |
| Node.js >= 20 | Optional | Runtime for Mermaid CLI |
| librsvg | Optional | SVG to PDF conversion |
Check your setup:
obsidian-export doctor
Quick Start
# Convert with default settings
obsidian-export convert --input my_note.md --format pdf --output my_note.pdf
# Convert to DOCX
obsidian-export convert --input my_note.md --format docx --output my_note.docx
# Use a custom profile
obsidian-export convert --input my_note.md --format pdf --output my_note.pdf --profile my_brand
Profile Management
Profiles are YAML config files stored in ~/.obsidian-export/profiles/.
# Initialize directory structure and default profile
obsidian-export init
# Create a new profile (starts from defaults)
obsidian-export profile create my_brand
# Create from existing YAML
obsidian-export profile create my_brand --from existing_config.yaml
# List profiles
obsidian-export profile list
# Show profile contents
obsidian-export profile show my_brand
# Delete a profile
obsidian-export profile delete my_brand --yes
Custom Styles
Styles are LaTeX header templates. Place custom styles in ~/.obsidian-export/styles/<name>/header.tex.
Style resolution order:
style_dirfield in config (explicit path)- Built-in styles (
default) - User styles in
~/.obsidian-export/styles/<name>/ - Treat style name as a filesystem path
Configuration
A config YAML can override any subset of defaults. Only include fields you want to change:
# Minimal override — everything else uses defaults
style:
fontsize: "12pt"
mainfont: "Georgia"
line_spacing: 1.5
Full Config Reference
mermaid:
mmdc_bin: "mmdc" # Path to Mermaid CLI binary
scale: 3 # PNG render scale
obsidian:
wikilink_strategy: "text" # How to handle [[wikilinks]]
url_strategy: "footnote_long" # bare URL handling: keep|footnote_long|footnote_all|strip
url_length_threshold: 60 # URL length for footnote_long strategy
pandoc:
from_format: "gfm-tex_math_dollars" # Pandoc input format
style:
name: "default" # Style name (resolves to header.tex template)
geometry: "a4paper,margin=25mm" # Page geometry
fontsize: "10pt" # Base font size
mainfont: "" # Main font (XeLaTeX)
sansfont: "" # Sans font
monofont: "" # Mono font
linkcolor: "NavyBlue" # Internal link color
urlcolor: "NavyBlue" # URL color
line_spacing: 1.0 # Line spacing multiplier
table_fontsize: "small" # Font size in tables
image_max_height_ratio: 0.40 # Max image height as fraction of page
url_footnote_threshold: 60 # URL length threshold for footnoting
header_left: "" # Left header (supports {doc_title}, {logo_path})
header_right: "" # Right header
footer_left: "" # Left footer
footer_center: "\\thepage" # Center footer
footer_right: "" # Right footer
logo: "" # Logo filename (relative to style dir)
style_dir: "" # Explicit style directory path
callout_colors:
note: [219, 234, 254]
tip: [220, 252, 231]
warning: [254, 243, 199]
danger: [254, 226, 226]
Python API
from pathlib import Path
from obsidian_export import run
from obsidian_export.config import default_config, load_config
# Using defaults
config = default_config()
run(Path("my_note.md"), Path("output.pdf"), "pdf", config)
# Using a config file
config = load_config(Path("my_config.yaml"))
run(Path("my_note.md"), Path("output.pdf"), "pdf", config)
What It Does
| Obsidian Syntax | Result |
|---|---|
![[embed]] |
Resolved inline (content inlined) |
[[Entity|Display]] |
Replaced with Display |
[[Entity]] |
Replaced with Entity |
> [!note] callouts |
Colored boxes (PDF) or blockquotes (DOCX) |
```mermaid |
Rendered to PNG |
## Relations section |
Removed |
| YAML frontmatter | Title extracted, tags → keywords, rest removed |
$25/user |
Safe literal dollar sign |
License
MIT
Project details
Release history Release notifications | RSS feed
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 obsidian_export-0.1.0.tar.gz.
File metadata
- Download URL: obsidian_export-0.1.0.tar.gz
- Upload date:
- Size: 18.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c6bb241f3c6b7105ad5d8d7a994c1badcddd850bee2d2ce949a67762588d8569
|
|
| MD5 |
3a3c8d621250dc25f00ef7237f90bd3c
|
|
| BLAKE2b-256 |
20dd336f6884ad9201d1afce1dfb3364f81607200f749f86580ac00620a41801
|
Provenance
The following attestation bundles were made for obsidian_export-0.1.0.tar.gz:
Publisher:
publish.yml on neuralsignal/obsidian-export
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
obsidian_export-0.1.0.tar.gz -
Subject digest:
c6bb241f3c6b7105ad5d8d7a994c1badcddd850bee2d2ce949a67762588d8569 - Sigstore transparency entry: 1061082628
- Sigstore integration time:
-
Permalink:
neuralsignal/obsidian-export@19398f63b17e45c9c515f17798372fe5abb2f52e -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/neuralsignal
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@19398f63b17e45c9c515f17798372fe5abb2f52e -
Trigger Event:
push
-
Statement type:
File details
Details for the file obsidian_export-0.1.0-py3-none-any.whl.
File metadata
- Download URL: obsidian_export-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.8 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 |
789f9d32c158a82ff757f7bf017a8a9dffdec1397de1a04060aeb2dec8342f6a
|
|
| MD5 |
81e2a0130d0eb89b46fc592464d8c350
|
|
| BLAKE2b-256 |
ead67a43570da208df56e3d730416a56d4fc8a81f8e22118844740209b1f569d
|
Provenance
The following attestation bundles were made for obsidian_export-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on neuralsignal/obsidian-export
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
obsidian_export-0.1.0-py3-none-any.whl -
Subject digest:
789f9d32c158a82ff757f7bf017a8a9dffdec1397de1a04060aeb2dec8342f6a - Sigstore transparency entry: 1061082657
- Sigstore integration time:
-
Permalink:
neuralsignal/obsidian-export@19398f63b17e45c9c515f17798372fe5abb2f52e -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/neuralsignal
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@19398f63b17e45c9c515f17798372fe5abb2f52e -
Trigger Event:
push
-
Statement type: