Metadata-Version: 2.4
Name: djangofmt
Version: 1.0.0
Classifier: Development Status :: 5 - Production/Stable
Classifier: Framework :: Django
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Rust
License-File: LICENSE
Summary: A fast, HTML aware, Django template formatter and linter, written in Rust.
Keywords: Django
Author-email: Thibaut Decombe <thibaut.decombe@gmail.com>
Requires-Python: >=3.8
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Changelog, https://unknownplatypus.github.io/djangofmt/docs/changelog/
Project-URL: Documentation, https://unknownplatypus.github.io/djangofmt/docs/
Project-URL: Issues, https://github.com/UnknownPlatypus/djangofmt/issues
Project-URL: Playground, https://unknownplatypus.github.io/djangofmt/
Project-URL: Repository, https://github.com/UnknownPlatypus/djangofmt

# Djangofmt

<!-- Begin section: Overview -->

[![Pypi Version](https://img.shields.io/pypi/v/djangofmt.svg)](https://pypi.python.org/djangofmt)
[![License](https://img.shields.io/pypi/l/djangofmt.svg)](https://github.com/UnknownPlatypus/djangofmt/blob/main/LICENSE)
[![Supported Python Versions](https://img.shields.io/pypi/pyversions/djangofmt.svg)](https://pypi.python.org/pypi/djangofmt)
[![Actions status](https://github.com/UnknownPlatypus/djangofmt/actions/workflows/ci.yml/badge.svg)](https://github.com/UnknownPlatypus/djangofmt/actions)
[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/UnknownPlatypus/djangofmt/main.svg)](https://results.pre-commit.ci/latest/github/UnknownPlatypus/djangofmt/main)
[![CodSpeed Badge](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/UnknownPlatypus/djangofmt?utm_source=badge)

[**Docs**](https://unknownplatypus.github.io/djangofmt/docs/) | [**Playground**](https://unknownplatypus.github.io/djangofmt/)

A fast, HTML aware, Django template formatter and linter, written in Rust.

<p align="center">
  <picture align="center">
    <source
      media="(prefers-color-scheme: dark)"
      srcset="https://github.com/user-attachments/assets/806ad1c2-a2c7-4177-9651-1857b43aff0d"
    >
    <source
      media="(prefers-color-scheme: light)"
      srcset="https://github.com/user-attachments/assets/7e132145-7738-4cd1-8cdc-dab6e87175b4"
    >
    <img
      alt="Shows a bar chart with benchmark results."
      src="https://github.com/user-attachments/assets/7e132145-7738-4cd1-8cdc-dab6e87175b4"
      style="max-width: 75%;"
    >
  </picture>
</p>

<p align="center">
  <i>Formatting 100k+ lines of HTML across 1.7k+ files from scratch.</i>
</p>

Heavily rely on the awesome [markup_fmt](https://github.com/g-plane/markup_fmt) with some additions to support Django fully.

- ⚡️ **70-120x faster** than existing Django template formatters
- 🐍 **Installable via `pip`, `uv` or `pipx`**
- 🛡️ **A strict HTML aware parser**: invalid HTML is reported as an error instead of being silently mangled
- 🎨 **Formats CSS** in `<style>` tags and `style` attributes, and JSON in `<script type="application/json">`
- 🔧 **[Lint rules](https://unknownplatypus.github.io/djangofmt/docs/rules/) with autofix**, for automatic error correction (e.g., automatically sort Tailwind classes)
- 🛠️ **`pyproject.toml` and `.editorconfig` support**
- ⌨️ **[Editor integrations](https://unknownplatypus.github.io/djangofmt/docs/editor-integration/)**, a **[pre-commit hook](#pre-commit-hook)** and a **[browser playground](https://unknownplatypus.github.io/djangofmt/)**

## Table of contents

- [Installation](#installation)
- [Usage](#usage)
- [Pre-commit hook](#pre-commit-hook)
- [Configuration](#configuration)
- [Editor integration](https://unknownplatypus.github.io/djangofmt/docs/editor-integration/)
- [Controlling the formatting](https://unknownplatypus.github.io/djangofmt/docs/formatting/)
- [Lint rules](https://unknownplatypus.github.io/djangofmt/docs/rules/)
- [Known limitations](https://unknownplatypus.github.io/djangofmt/docs/known-limitations/)
- [Benchmarks](https://unknownplatypus.github.io/djangofmt/docs/benchmarks/)
- [Shell completions](#shell-completions)
- [Contributing](#contributing)

## Installation

djangofmt is available on PyPI.

```shell
# With pip
pip install djangofmt

# With uv
uv tool install djangofmt@latest  # Install djangofmt globally.
uv add --dev djangofmt            # Or add djangofmt to your project.

# With pipx
pipx install djangofmt
```

## Usage

To run the formatter:

```shell
djangofmt .                    # Format all files in the current directory (and any subdirectories).
djangofmt src/templates        # Format all template files in `src/templates`
djangofmt templates/base.html  # Format individual files
```

When given a directory, djangofmt recurses into it and formats all `*.html`, `*.jinja`, `*.jinja2`, and `*.j2` files it finds (respecting `.gitignore` files).

To run the linter:

```shell
djangofmt check .                       # Report violations
djangofmt check --fix .                 # Apply safe fixes, then report what is left
djangofmt check --fix --unsafe-fixes .  # Apply all fixes, unsafe ones included
```

- See [Running the linter](https://unknownplatypus.github.io/djangofmt/docs/linter/) for rule selection, fixes and suppression comments, or `djangofmt check --help` for the full list of options.
- See [Lint rules](https://unknownplatypus.github.io/djangofmt/docs/rules/) for the full list of available rules and categories.

## Pre-commit hook

See [pre-commit](https://github.com/pre-commit/pre-commit) for instructions.

Sample `.pre-commit-config.yaml`:

```yaml
- repo: https://github.com/UnknownPlatypus/djangofmt-pre-commit
  # Djangofmt version.
  rev: v1.0.0
  hooks:
    # Run the linter.
    - id: djangofmt-check
      args: [--fix]
    # Run the formatter.
    - id: djangofmt
```

The [separate repository](https://github.com/UnknownPlatypus/djangofmt-pre-commit) enables installation without compiling the Rust code.

By default, the configuration uses pre-commit's [`files` option](https://pre-commit.com/#creating-new-hooks) to detect
all text files in directories named `templates`. If your templates are stored elsewhere, you can override this behavior
by specifying the desired files in the hook configuration within your `.pre-commit-config.yaml` file.

### `.svg` files support

djangofmt can format svg files too.
There is a dedicated pre-commit hook for these:

```yaml
- repo: https://github.com/UnknownPlatypus/djangofmt-pre-commit
  rev: v1.0.0
  hooks:
    - id: djangofmt-svg
```

### Check mode

`--check` reports the files that would be reformatted without writing anything, exiting with `1` if any would change:

```shell
djangofmt --check .
```

CI is usually too late for a code formatter though: prefer the pre-commit hook above or an IDE "format on save" integration.

## Configuration

Djangofmt can also be configured via a `[tool.djangofmt]` section in your `pyproject.toml`:

```toml
[tool.djangofmt]
line-length = 120
indent-width = 4
profile = "django"
custom-blocks = ["stage", "flatblock"]
html-void-self-closing = "never"
preserve-unquoted-attrs = false
```

Lint rules, used by the `djangofmt check` command, are configured in the nested `[tool.djangofmt.lint]` section:

```toml
[tool.djangofmt.lint]
select = ["category:all"]
ignore = ["category:style"]
preview = true
target-version = "5.2"
fix = true

[tool.djangofmt.lint.per-file-ignores]
"templates/admin/*.html" = ["missing-img-alt"]
```

`target-version` is the Django version your templates target. When unset, it comes from the minimum supported Django version in `[project] dependencies`.
Rules that depend on it stay disabled until it is known.

Every option is documented in the [settings reference](https://unknownplatypus.github.io/djangofmt/docs/settings/).

Djangofmt looks for a `pyproject.toml` file by traversing directories upward from the current working directory.
The first `pyproject.toml` found is used. If no file is found or the file doesn't contain a `[tool.djangofmt]` section, defaults are used.

Djangofmt also reads [EditorConfig](https://editorconfig.org/) settings from the nearest `.editorconfig` file:

```ini
root = true

[*]
indent_size = 4
max_line_length = 120
```

Command-line arguments always take precedence over `pyproject.toml` settings, which take precedence over `.editorconfig` settings.

See [Controlling the formatting](https://unknownplatypus.github.io/djangofmt/docs/formatting/) for the behaviour of each option and how to opt into per-node overrides.

## Editor integration

See the [editor integration guide](https://unknownplatypus.github.io/djangofmt/docs/editor-integration/).

## Shell completions

You can generate shell completions for your preferred
shell using the `djangofmt completions` command.

```shell
Usage: djangofmt completions <SHELL>

Arguments:
  <SHELL>
      The shell to generate the completions for
      [possible values: bash, elvish, fish, nushell, powershell, zsh]
```

## Contributing

Contributions are welcome! Please see [`CONTRIBUTING.md`](CONTRIBUTING.md) for details on how to get started.

<!-- End section: Overview -->

