Skip to main content

Developers Toolbox

Markdown Converter

Python library that loads CommonMark, GitHub Flavored Markdown, or Obsidian Markdown into one document tree, then writes any of those flavours. Conversion is two-pass through that tree — there are no pairwise converters.

The PyPI name is lupaxa-markdown-converter. The import path is lupaxa.markdown_converter. lupaxa is a namespace package. The console script is markdown-converter.

Install

pip install lupaxa-markdown-converter

Requires Python 3.10+. The package pulls in markdown-it-py.

You can also run python -m lupaxa.markdown_converter.

Usage

from lupaxa.markdown_converter import MarkdownConverter

source = "[[folder/My Page#Hello World]]\n"
converter = MarkdownConverter(source, flavour="obsidian")

print(converter.to_commonmark())
print(converter.to_github())
print(converter.to_obsidian())

MarkdownConverter accepts a document string. Set flavour to the flavour of that string (case-insensitive). The value is stored lower-case on converter.flavour, then any to_* method can write it out. Same-flavour conversion is supported.

flavour Input
commonmark CommonMark (default)
github GitHub Flavored Markdown: tables, tasks, strikethrough, and autolinks
obsidian Those GitHub extras, plus wikilinks, embeds, highlights, and callouts
from_commonmark = MarkdownConverter("# Title\n", flavour="commonmark")
from_github = MarkdownConverter("- [x] done\n", flavour="github")
from_obsidian = MarkdownConverter("==hi==\n", flavour="OBSIDIAN")

Note: Output is canonical. A same-flavour conversion can still change the source. A setext heading becomes an ATX heading, and a reference link is written inline.

MarkdownConverter("Title\n=====\n", flavour="commonmark").to_commonmark()
# '# Title\n'

An Obsidian wikilink becomes a Markdown link on the way to GitHub or CommonMark. Each path segment is percent-encoded, .md is added when the target does not already end in .md, and a heading becomes a fragment. An image embed becomes an image. A numeric label is a resize hint and is dropped. Obsidian keeps both forms.

converter = MarkdownConverter("[[folder/My Page#Hello World]]\n", flavour="obsidian")
converter.to_github()
# '[My Page](folder/My%20Page.md#hello-world)\n'

embed = MarkdownConverter("![[shot.png|100]]\n", flavour="obsidian")
embed.to_github()
# '![shot](shot.png)\n'
embed.to_obsidian()
# '![[shot.png|100]]\n'

GitHub and Obsidian keep pipe tables, task lists, strikethrough, and bare autolinks. CommonMark receives the nearest CommonMark form: an HTML table, escaped checkbox text, <del>, and an angle autolink. Plain CommonMark is left as plain CommonMark. A checkbox written as ordinary text is escaped, and an HTML table stays HTML.

table = "| A | B |\n| --- | ---: |\n| 1 | 2 |\n"
MarkdownConverter(table, flavour="github").to_obsidian()
# '| A | B |\n| --- | ---: |\n| 1 | 2 |\n'

MarkdownConverter("- [x] done\n", flavour="github").to_github()
# '- [x] done\n'
MarkdownConverter("- [ ] todo\n", flavour="commonmark").to_github()
# '- \\[ \\] todo\n'

MarkdownConverter("~~old~~ and https://example.com\n", flavour="github").to_commonmark()
# '<del>old</del> and <https://example.com>\n'

Highlights and Callouts

Obsidian keeps ==highlights== and [!type] callouts. GitHub and CommonMark receive <mark> and a blockquote whose first line is the type and title.

note = MarkdownConverter("==hi==\n", flavour="obsidian")
note.to_obsidian()
# '==hi==\n'
note.to_github()
# '<mark>hi</mark>\n'

callout = MarkdownConverter("> [!tip] Look\n", flavour="obsidian")
callout.to_github()
# '> **Tip:** Look\n'
callout.to_obsidian()
# '> [!tip] Look\n'

Frontmatter

A leading YAML fence is copied through unchanged, including its line endings. The body is converted. The fence is not parsed as Markdown.

source = "---\ntitle: Note\n---\n\n# Title\n"
MarkdownConverter(source, flavour="obsidian").to_commonmark()
# '---\ntitle: Note\n---\n\n# Title\n'

Command Line

--from and --to are required. They take commonmark, github, or obsidian. Pass a file, or - to read stdin. Omit -o to write stdout.

markdown-converter --from obsidian --to github note.md -o note.github.md
markdown-converter --from github --to commonmark - < note.md

A missing file, a directory, text that is not UTF-8, or a conversion error prints one Error: line on stderr and exits 2.

Errors

An unknown flavour, a document that is not a string, and a body that cannot be parsed raise MarkdownConverterError. The parse failure is attached as __cause__.

from lupaxa.markdown_converter import MarkdownConverter, MarkdownConverterError

try:
    MarkdownConverter("hi\n", flavour="rst")
except MarkdownConverterError as exc:
    print(exc)
The Lupaxa Project Footer

Metadata

Release files for lupaxa-markdown-converter 0.1.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 lupaxa-markdown-converter 0.1.0
File Size Uploaded
lupaxa_markdown_converter-0.1.0.tar.gz 15.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for lupaxa-markdown-converter 0.1.0
File Interpreter ABI Platform
lupaxa_markdown_converter-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 34.7 kB

Release files / lupaxa_markdown_converter-0.1.0.tar.gz

Download URL lupaxa_markdown_converter-0.1.0.tar.gz
Size 15.4 kB
Tags Source
SHA-256 checksum
How to use checksums
5554e3bd61584f41a8fdd7dfd9de6a78cd9d717837efe3d0f8fcfd0738696f56
BLAKE2b-256 checksum
How to use checksums
66ab2ca7ea8f2406fa1bb4955cdb1e8debf90c6704a0e992fc2e2d8a8eecb98a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 4, 2026.

Transparency log

Release files / lupaxa_markdown_converter-0.1.0-py3-none-any.whl

Download URL lupaxa_markdown_converter-0.1.0-py3-none-any.whl
Size 19.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
30634f6db7ca0598c5e437944f468e0dafe8b96f87cff5610d1a06d224500b3b
BLAKE2b-256 checksum
How to use checksums
5c598a93c72cd27adc18fd82ae0c5a54df73721a10de43f795523f9eb7545e4d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 4, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.1

2 release files

This release

0.1.0 This release

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