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.1

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.1
File Size Uploaded
lupaxa_markdown_converter-0.1.1.tar.gz 15.4 kB Details

Built distribution (wheel)

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

Total release size: 34.7 kB

Release files / lupaxa_markdown_converter-0.1.1.tar.gz

Download URL lupaxa_markdown_converter-0.1.1.tar.gz
Size 15.4 kB
Tags Source
SHA-256 checksum
How to use checksums
68263886fb968e616fb2b14f82e7f17f5bfd6d80af9c0a3413d259ddac951948
BLAKE2b-256 checksum
How to use checksums
5a89108f3235d9f7e325c6243bf5351bdebc9c6d9a61cbd18e04b1ceb81689e8
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 7, 2026.

Transparency log

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

Download URL lupaxa_markdown_converter-0.1.1-py3-none-any.whl
Size 19.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
effa1b04ec5800bc116640e379d490293c748e028c2b23f20a0d57021f65867d
BLAKE2b-256 checksum
How to use checksums
84243477ebb16ca7d2eea3371039cde05a21c506f314377dd1e35a1819068f0f
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 7, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

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