Skip to main content

djot-fmt

Automatic formatter for djot markup files.

Overview

djot-fmt is a command-line tool that automatically formats djot files, focusing primarily on fixing common list formatting issues:

  • Missing newlines between list items
  • Incorrect indentation for nested lists
  • Blank line spacing before nested content

Installation

go install github.com/KyleKing/djot-fmt@latest

Or from PyPI, which ships the same formatter as a shared library bound with ctypes:

uv tool install djot-fmt   # or: pipx install djot-fmt
uvx djot-fmt file.dj       # run without installing

The Python wheels carry a compiled library rather than a reimplementation, so output is byte-identical to the Go binary. Formatting runs in-process, which costs about 9 microseconds for a small document against roughly 3 milliseconds to spawn the CLI.

Python API

import djot_fmt

djot_fmt.format('-  a\n-  b\n')  # '- a\n- b\n'
djot_fmt.format(source, wrap_sentences=False)

format raises djot_fmt.DjotFormatError on input the formatter rejects. Calls are serialized internally because the underlying djot parser is not goroutine-safe.

The shared library is opened on the first call rather than at import, so a process that imports djot_fmt and then forks stays safe. Calling into it before forking does not, because the Go runtime does not survive fork() without exec(). Use the spawn or forkserver start method with multiprocessing.

Usage

Basic Usage

# Format stdin to stdout
cat file.dj | djot-fmt

# Format file and write back
djot-fmt -w file.dj

# Format multiple files and write back
djot-fmt -w file1.dj file2.dj file3.dj

# Check if file is formatted (exit 1 if not)
djot-fmt -c file.dj

# Check multiple files
djot-fmt -c file1.dj file2.dj file3.dj

# Format to different file
djot-fmt -o output.dj input.dj

Batch Processing

# Format all .dj files in current directory
fd -e dj -x djot-fmt -w

# Format all .dj files in specific directory
fd -e dj . content/ -x djot-fmt -w

# Check formatting for all .dj files
fd -e dj -x djot-fmt -c

# Using find (alternative to fd)
find . -name "*.dj" -exec djot-fmt -w {} \;

Options

  • -w, --write - Write result to source file(s) instead of stdout
  • -c, --check - Check if file(s) are formatted (exit 1 if not)
  • -o, --output FILE - Write output to FILE instead of stdout (single input file only)
  • -h, --help - Show help message
  • -v, --version - Show version information

Validation Options

After formatting, djot-fmt renders both the input and the output to HTML and compares them. A difference means formatting changed what the document says, which is a bug in djot-fmt, so the run fails rather than writing the file.

  • --no-validate - Skip the check
  • --from-md - Allow the list changes that formatting markdown as djot causes, and report each one that was waived. djot requires a blank line before a nested list where markdown does not, so inserting that line legitimately changes the parse. Nothing else is waived: losing a word, a block kind, or an <ol> start number still fails

SLW (Semantic Line Wrap) Options

  • --no-wrap-sentences - Disable semantic line wrapping
  • --slw-markers TEXT - Characters that mark sentence endings (default: ".!?")
  • --slw-wrap INTEGER - Maximum line width for wrapping (default: 88, set to 0 to disable)
  • --slw-min-line INTEGER - Minimum line length before wrapping (default: 40, set to 0 for aggressive mode)

Development

This project uses mise for tool management and hk for git hooks.

Setup

# Install mise (if not already installed)
# See: https://mise.jdx.dev/getting-started.html

# Install project tools
mise install

# Install git hooks
hk install --mise

Common Commands

# Run all checks (linting, tests)
mise run ci

# Format code
mise run fmt

# Run tests
mise run test

# Build binary
mise run build

# Install locally
mise run install

Python bindings

# Build the wheel (compiles bindings/cshared with -buildmode=c-shared)
uv build --wheel

# Run the Python tests against the built wheel
uv run --isolated --with dist/*.whl --with pytest pytest bindings/python/tests

bindings/cshared/lib.go is the cgo boundary. Every exported function there recovers from panics, because a panic crossing into C terminates the host process, which for a Python caller means killing the interpreter. Strings allocated on the Go side are freed through DjotFree.

Roadmap

Future enhancements under consideration:

  • Support for all djot node types (ordered lists, tables, code blocks, etc.)
  • Configurable formatting options (indentation width, line wrapping)
  • Semantic line wrapping (similar to mdformat-slw)
  • Code block formatting integration

License

MIT

Credits

Built using godjot for djot parsing and AST manipulation.

Metadata

Release files for djot-fmt 0.2.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 djot-fmt 0.2.1
File Size Uploaded
djot_fmt-0.2.1.tar.gz 31.3 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for djot-fmt 0.2.1
File
djot_fmt-0.2.1-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details
djot_fmt-0.2.1-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
djot_fmt-0.2.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64, Linux glibc 2.28+ ARM64 Details
djot_fmt-0.2.1-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl Python 3 none Linux glibc 2.28+ x86-64, Linux glibc 2.5+ x86-64 Details
djot_fmt-0.2.1-py3-none-macosx_15_0_x86_64.whl Python 3 none macOS 15.0+ x86-64 Details
djot_fmt-0.2.1-py3-none-macosx_15_0_arm64.whl Python 3 none macOS 15.0+ ARM64 Details

Total release size: 5.6 MB

Release files / djot_fmt-0.2.1.tar.gz

Download URL djot_fmt-0.2.1.tar.gz
Size 31.3 kB
Tags Source
SHA-256 checksum
How to use checksums
38cae937c9295973dd7ec696a5f2a6a65831887638a35ed5a0f73712a55ac36b
BLAKE2b-256 checksum
How to use checksums
5d881ff4eeed69a5300717638a6f9095d4533cb3bb2030b1458cbf56fe7f3f2d
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 Aug 31, 2026.

Transparency log

Release files / djot_fmt-0.2.1-py3-none-win_arm64.whl

Download URL djot_fmt-0.2.1-py3-none-win_arm64.whl
Size 873.8 kB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
cb74fe5522e40b879215f7c8f25e1a5178f2cc86ad36d081e9b3b0f65b430e5b
BLAKE2b-256 checksum
How to use checksums
3de6ef9a8febeb9e9595f0c363f5d0897ccd400333beab75d2c37f0fd255110e
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 Aug 31, 2026.

Transparency log

Release files / djot_fmt-0.2.1-py3-none-win_amd64.whl

Download URL djot_fmt-0.2.1-py3-none-win_amd64.whl
Size 961.3 kB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
e127349f094a9a14a06e6b931493645279f354308dd9c2d620152be2abcda5b7
BLAKE2b-256 checksum
How to use checksums
720798d5d76a79fb171abd0d8474aea84090f08004a8119e0af19cca8295e482
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 Aug 31, 2026.

Transparency log

Release files / djot_fmt-0.2.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL djot_fmt-0.2.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 893.6 kB
Tags Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64 Python 3
SHA-256 checksum
How to use checksums
46cbc24b71ce32837832b6f20eb508b099626ad327b92bc88574eca9103e43b4
BLAKE2b-256 checksum
How to use checksums
61de4ba9931c1464830bfde3c6ad3a241e2f0832d95f6e4660c42f848b38858e
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 Aug 31, 2026.

Transparency log

Release files / djot_fmt-0.2.1-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl

Download URL djot_fmt-0.2.1-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Size 969.0 kB
Tags Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64 Python 3
SHA-256 checksum
How to use checksums
fe86a05039b09f1ee9317f5063dcd500cb600ad79ab119beee035e06ecd0131d
BLAKE2b-256 checksum
How to use checksums
14e51f78f4d19a885180691f865ec231edded880bdbff20352d878644d48c7b8
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 Aug 31, 2026.

Transparency log

Release files / djot_fmt-0.2.1-py3-none-macosx_15_0_x86_64.whl

Download URL djot_fmt-0.2.1-py3-none-macosx_15_0_x86_64.whl
Size 961.3 kB
Tags Python 3 macOS 15.0+ x86-64
SHA-256 checksum
How to use checksums
eb750c35aa066cf860a9411577a615e6eaa685a30641ac1345984598e3ffd89b
BLAKE2b-256 checksum
How to use checksums
a405e8f287c0c44cdd1168e9f0c8fd7d04a56f308dbb457d1cdd1662e1640f50
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 Aug 31, 2026.

Transparency log

Release files / djot_fmt-0.2.1-py3-none-macosx_15_0_arm64.whl

Download URL djot_fmt-0.2.1-py3-none-macosx_15_0_arm64.whl
Size 902.9 kB
Tags Python 3 macOS 15.0+ ARM64
SHA-256 checksum
How to use checksums
c7c390e6e9bd655e28b7a64c0cc10623ce74b8b16f15eada2a66cb95c22353cd
BLAKE2b-256 checksum
How to use checksums
3b47753407a4412a53a27ba726758e6a9a1df8af9575ce3a9ec510d4c7877161
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 Aug 31, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.4

7 release files

0.2.3

7 release files

0.2.2

7 release files

This release

0.2.1 This release

7 release files

0.2.0

7 release files

0.1.2

7 release files

0.1.1

7 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