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.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 djot-fmt 0.2.0
File Size Uploaded
djot_fmt-0.2.0.tar.gz 31.1 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for djot-fmt 0.2.0
File
djot_fmt-0.2.0-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details
djot_fmt-0.2.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
djot_fmt-0.2.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl Python 3 none Linux glibc 2.28+ ARM64, Linux glibc 2.17+ ARM64 Details
djot_fmt-0.2.0-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl Python 3 none Linux glibc 2.5+ x86-64, Linux glibc 2.28+ x86-64 Details
djot_fmt-0.2.0-py3-none-macosx_15_0_x86_64.whl Python 3 none macOS 15.0+ x86-64 Details
djot_fmt-0.2.0-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.0.tar.gz

Download URL djot_fmt-0.2.0.tar.gz
Size 31.1 kB
Tags Source
SHA-256 checksum
How to use checksums
bfdbeb430233ff3737853fca6038f8bbac7a80c7b81b9c8ef362418a8e5e93a0
BLAKE2b-256 checksum
How to use checksums
f0fdd3e01c00625a310cf1f27205b25000b357f46e9949e2a19655865c0ffcd7
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 27, 2026.

Transparency log

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

Download URL djot_fmt-0.2.0-py3-none-win_arm64.whl
Size 873.8 kB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
a254071baae80fdb89a41ec005ea9e3bf3c30f8cbfe012badf0da464f6c8ed50
BLAKE2b-256 checksum
How to use checksums
7221d646b25e990ed180f2b85be86588520d66123665de115c61f1a4b930b03a
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 27, 2026.

Transparency log

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

Download URL djot_fmt-0.2.0-py3-none-win_amd64.whl
Size 961.3 kB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
be0596507169c5fbb808cfd34c54ad24af1124d260b81927457d764ae874e279
BLAKE2b-256 checksum
How to use checksums
e2e7c2276c0f8aaf821e817c73c5cb29836c1d547680870903783a984a9b0be1
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 27, 2026.

Transparency log

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

Download URL djot_fmt-0.2.0-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
1562aaa09144b202482a6589e16e85f3d3ae335823c5447de61c9718b5186c1c
BLAKE2b-256 checksum
How to use checksums
323c42f9a3086bd34c9bdc9b8d8202dac1caa30f56500fd33d7c95fe6e9266a2
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 27, 2026.

Transparency log

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

Download URL djot_fmt-0.2.0-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
b21ceb6dbee86e8f2b3ae2a16f2ea01fdddc9185d7ce58997b3da4022fb2f74a
BLAKE2b-256 checksum
How to use checksums
f849eabedd8df82608976893d292247c6edf6a9f1bb2b1a1b1b4a9ba817fc346
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 27, 2026.

Transparency log

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

Download URL djot_fmt-0.2.0-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
94d4e8d5d7f3ce6351bf3d7bb416b7b3d1f3f24771185195b0fb859f5ca5080d
BLAKE2b-256 checksum
How to use checksums
5a0c4e073ac09d99613c0dc63f2fd0ab5ac526d987bfae5cae16af1e1f746022
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 27, 2026.

Transparency log

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

Download URL djot_fmt-0.2.0-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
1121557b5d699299e87a277f53d0b45bf660d86bb3016ceaa373e4ad2f7fb052
BLAKE2b-256 checksum
How to use checksums
e118059afd535c86a6ea0244c91df35c611ac434b1b91610529bd4f210333fb4
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 27, 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

0.2.1

7 release files

This release

0.2.0 This release

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