Skip to content

Changelog

1.0.0 - 2026-09-20

Docs | Playground

๐ŸŽ‰ djangofmt 1.0 is here! The formatter is now stable, hardened by extensive fuzzing, ecosystem check and bug fixing. The new check command also gained automatic Tailwind CSS class sorting, powered by rustywind.

โ›ฐ๏ธ Features

  • (check) Add --output-format concise - (4fe930f)
  • (cli) Add --target-version option (#492) - (eb317d3)
  • (cli) Add {# djangofmt: file-ignore[...] #} file-level opt-outs (#440) - (a24f7be)
  • (cli) Hint at the conditional open/close tag limitation on parse errors (#426) - (7c6c67b)
  • (dev) Add cargo-fuzz idempotency fuzzing for the formatter (#435) - (2e0e66e)
  • (ecosystem) Report exclusions that are no longer needed (#401) - (0fda5d6)
  • (ecosystem) Add EvaP, djangoproject.com, healthchecks, babybuddy, InvenTree and netbox targets (#400) - (969a64c)
  • (ecosystem-check) Add 12 Django projects to the corpus (#463) - (788afe8)
  • (format) Support --check option for checking formatting without making changes (#496) - (4d92de4)
  • (format) Accept whitespace around : in the ignore directive (#449) - (4f149a2)
  • (lint) Stabilize the linter for 1.0 (#517) - (49e56ed)
  • (lint) Add a pedantic category and leave it out of the default rule set (#508) - (6a7ead9)
  • (lint) Add unused-ignore-code lint rule (#487) - (486e2d6)
  • (lint) Add deprecated-ignore lint rule (#443) - (59b2d58)
  • (lint) Infer target-version from the django requirement (#495) - (95b98e6)
  • (lint) Add invalid-ignore-comment and invalid-ignore-code lint rules (#442) - (6e8f422)
  • (lint) Suppress diagnostics with {# djangofmt: ignore[rule] #} comments (#441) - (ef3335f)
  • (lint) Honor rule codes in {# djangofmt: file-ignore[...] #} (#470) - (a4aea6d)
  • (lint) Add unsorted-tailwind-classes lint rule (#332) - (da2a7aa)
  • (lint) Add same-file-partial-include lint rule (#344) - (a103419)
  • (lint) Add per-file-ignores configuration (#411) - (fefdd9b)

๐Ÿ› Bug Fixes

  • (check) Render parse errors concisely with --output-format concise (#394) - (b821e10)
  • (ci) Actually truncate the ecosystem comment body - (58bbd22)
  • (cli) Stop breaking help URLs across lines (#458) - (63af806)
  • (cli) Honor a leading djangofmt:ignore on unparsable files in check (#439) - (8974a3b)
  • (cli) Anchor include and exclude patterns at the project root (#433) - (2e98311)
  • (cli) Report accurate parse error locations (#430) - (de1ddde)
  • (cli) Exit 2 on I/O and parse errors in file mode (#429) - (34f5745)
  • (format) Reject self-closing non-void HTML elements as a parse error (#516) - (2e90033)
  • (format) Keep a comment-only CSS block instead of emptying it (#499) - (f39c760)
  • (format) Keep /*!, /*# and /** CSS comment markers intact (#498) - (25c46f7)
  • (format) Leave JSON with raw control characters in strings unformatted (#485) - (69edc82)
  • (format) Stop reordering CSS shorthands past the longhands they override (#483) - (c77d667)
  • (format) Respect internal attr loop separator (#480) - (11aee2f)
  • (format) Honor {# djangofmt: ignore[format] #} on the next node (#473) - (e4ea817)
  • (format) Reject malformed template syntax instead of silently corrupting it (#457) - (04e8d72)
  • (format) Recover from panics instead of crashing the whole run (#459) - (5c3837b)
  • (format) Keep the opening tag of an ignored nested block tag (#434) - (4a56d53)
  • (format) Resolve stdin profile with the same precedence as files (#413) - (78bed0d)
  • (format) Don't treat --- as front matter outside the top of the file (#407) - (d41752d)
  • (format) Only treat Django's built-in tags as block tags (#402) - (275acaa)
  • (format) Re-indent {% endcomment %} with its block (#395) - (6612b1b)
  • (format) Don't panic on {% comment %} among tag attributes (#393) - (9522c6e)
  • (lint) More small linter fixes and perf improvements (#521) - (efd6d4d)
  • (lint) Minor lint rule fixes (#520) - (fc3eec9)
  • (lint) Detect whitespace-padded URLs in django-static-url and django-url-pattern (#431) - (7de1dd7)
  • (lint) Don't disable missing-doctype on root-level Jinja blocks (#427) - (b74d4d4)
  • (lint) Restore build for form-action-whitespace fix content (#399) - (1ec0946)
  • (playground) Fix border of plus/minus inputs (#382) - (c026381)
  • (release) Opt the binary back into dist after publish = false (#509) - (2735037)

๐Ÿšœ Refactor

  • (cli) Count check results in a single pass (#468) - (06e3aa5)
  • (cli) Unify parsing into a lint_source and parse_source interface (#404) - (017e23e)
  • (dev) Move generated-page prose out of Rust into Markdown files (#437) - (1781144)
  • (ecosystem) Document ecosystem exclusion reasons (#410) - (96f070c)
  • (format) Delete dead display only fix api (#414) - (2e5b7d2)
  • (lint) Pass checker as the first argument to rule check functions (#505) - (5678cbb)
  • (lint) Route check, --fix and the playground through one lint_text api (#490) - (6c8d3e9)
  • (lint) Add source_span/source_end helpers and derive spans from slices (#484) - (35653ce)
  • (lint) Tighten diagnostic messages and help text (#481) - (253e26f)
  • (lint) Parse suppression directives with one shared grammar (#472) - (e8a5667)

๐Ÿ“š Documentation

  • (agents) Sync the add-lint-rule skill and AGENTS.md with the current code - (0226c88)
  • (benchmark) Update benchmark numbers (#454) - (c725574)
  • (format) Document the omitted end tag limitation and link the hint to it (#515) - (7d00e1a)
  • (skill) Insist rule doc comments say what, never how (#424) - (2b6a243)
  • Document LF-only output as a known limitation (#461) - (de59f2b)

โšก Performance

  • (bench) Add a reporter benchmark covering diagnostic rendering (#390) - (70c2820)
  • (format) Use oxc-miette for ~5x faster diagnostic rendering (#392) - (822a21f)
  • (lint) Avoid allocating for static violation messages, help and fix titles (#397) - (e67ab92)
  • (lint) Avoid allocating for static fix content (#398) - (72551cc)
  • (lint) Use &'static str for diagnostic rule codes (#396) - (be7ed4f)

๐Ÿงช Testing

  • (bench) Benchmark the default rule selection, not just none and all (#412) - (b9e9591)
  • (benchmark) Benchmark templates carrying a djangofmt: directive (#469) - (00c4553)
  • (ecosystem) Drop the stale bookwyrm manual-merge.html exclusion (#497) - (9be0f74)
  • (ecosystem) Exclude django-unfold avatar.html (dynamic tag name) (#455) - (30ba2c8)
  • (ecosystem) Update ecosystem exclusion list and also check stability false positives (#403) - (671704f)
  • (ecosystem-check) Report fixable lint changes as a source diff - (cfa4d66)
  • (format) Pin lowercased CSS property names as intended (#486) - (60d599d)
  • (fuzz) Skip control-character inputs in the idempotency target (#504) - (1f0b3df)
  • (refactor) Drop tests already covered elsewhere (#438) - (e5b827f)
  • (refactor) Each rule test fixture now only enable the rule (#406) - (d0921df)

โš™๏ธ Miscellaneous Tasks

  • (benchmark) Fix codspeed flakiness after v5 (#448) - (2dfa651)
  • (changelog) Add a one-off 1.0 banner to the generated changelog (#464) - (d4994ef)
  • (ecosystem) Add a parse check that fails when formatting breaks templates (#494) - (43a6507)
  • (ecosystem) Stop rebuilding djangofmt a third time in the ecosystem check (#456) - (43fd237)
  • (release) Fix s390x cross build of psm assembly (#453) - (0d8e8de)
  • (security) Reject a tampered pr-number artifact before it reaches GITHUB_OUTPUT (#514) - (21a11e0)
  • (security) Harden release workflow permissions, inputs, and caching (#422) - (4df167d)
  • (stability) Reduce codspeed variance (#465) - (657918f)
  • (tests) Regenerate snapshots in insta's current format (#475) - (23cca63)
  • Pin cargo dev tools through uv.lock (#477) - (f92f89c)
  • Drop the cargo-bloat workflow for a just recipe (#479) - (110c8a2)
  • Build and test with --locked (#476) - (7a87cea)
  • Set UV_LOCKED in workflows that resolve dependencies (#478) - (81e72fd)

New Contributors โค๏ธ

0.2.12 - 2026-07-15

Docs | Playground

โ›ฐ๏ธ Features

  • (lint) Add table-header-missing-scope lint rule (#345) - (4d9f72c)

๐Ÿ› Bug Fixes

  • (format) Skip formatting Django verbatim blocks (#370) - (caf2fe4)

0.2.11 - 2026-06-26

Docs | Playground

โ›ฐ๏ธ Features

  • (format) Preserve single-line Django blocks inside attribute lists (#360) - (ca3d825)
  • (format) Support .editorconfig configuration files (#349) - (0df2c71)
  • (lint) Add duplicate-block-name lint rule - (4fe9aef)
  • (lint) Add rule selection (select/ignore + preview) (#350) - (7d0eb76)
  • (playground) Add documentation link to navbar (#351) - (0923257)

๐Ÿ› Bug Fixes

  • (format) Fix formatting of multiline django template tags (#359) - (2908461)
  • (lint) Restore correct ANSI display in error messages (#346) - (d4c21ba)

๐Ÿšœ Refactor

  • (lint) Avoid double parse when fixing (#362) - (621980e)
  • (lint) Drop redundant help on empty-attr-value rule (#357) - (e10ed1e)
  • (lint) Cleanup RuleSet implementation and simplify (#336) - (17c0668)
  • (misc) Minor cleanup (#356) - (2b1346b)
  • (tests) Misc test simplification (#348) - (cdda76a)

๐Ÿงช Testing

  • (bench) Isolate check_ast cost from parsing (#364) - (8251c11)
  • (clippy) Enable more clippy restriction rules (#363) - (539450c)
  • (ecosystem-check) Select all rules + preview in check ecosystem run (#352) - (17110ef)

โš™๏ธ Miscellaneous Tasks

  • (codspeed) Pin glibc CPU-feature dispatch to reduce benchmark variance (#366) - (5175539)

0.2.10 - 2026-06-03

Docs | Playground

โ›ฐ๏ธ Features

  • (format) Allow {# djangofmt:ignore #} to disable formatting (#333) - (8de13fc)
  • (lint) Add django-url-pattern lint rule (#314) - (9cfc71c)
  • (lint) Add empty-tag-pair lint rule (#313) - (5ac93df)
  • (lint) Add missing-img-alt lint rule (#312) - (d7e3d38)
  • (lint) Add django-static-url lint rule (#311) - (27836b6)
  • (lint) Add use-https lint rule (#308) - (3503bc7)
  • (playground) Add ast + Doc IR representation in playground (#331) - (c9489bb)

๐Ÿ› Bug Fixes

  • (format) Stabilize indentation of <script> tag content (#335) - (8c98e1e)

๐Ÿšœ Refactor

  • (lint) Dispatch per-attribute rules from a single attribute visitor (#330) - (d02925c)
  • (lint) Dispatch tag-scoped rules by tag (#326) - (4c1a059)
  • (lint) Check img height and width attributes in a single pass (#322) - (5164cea)
  • (lint) Reuse fs::get_cwd and drop build_walk_filters wrapper (#320) - (9aab7b7)
  • (lint) Add fix::edits module with delete_attr_fix helper (#319) - (d7cc9ad)
  • (lint) Extract jinja-aware attr-presence helper (#318) - (6910bd9)
  • (lint) Fold attribute value match into NativeAttribute pattern (#317) - (67f5802)
  • (playground) Switch to deno (#316) - (2abd19d)
  • (test) Share benchmark template list via ALL_TEMPLATES const (#321) - (2eab77b)

โšก Performance

  • (format) Update markup_fmt leading to average perf improvement of 2x (#329) - (d0329ca)
  • (lint) Use a BitSet to store enabled rules (#325) - (347d0b9)

0.2.9 - 2026-05-29

Docs | Playground

โ›ฐ๏ธ Features

  • (check) Expose --fix, --unsafe-fixes, --show-fixes in pyproject config (#290) - (448f487)
  • (docs) Publish Zensical-based documentation site (#300) - (5f29df3)
  • (lint) Add missing-doctype lint rule (#310) - (e372374)
  • (lint) Add missing-title lint rule (#309) - (b243792)
  • (lint) Add duplicate-attr lint rule (#304) - (ef732af)
  • (lint) Add form-action-whitespace lint rule (#303) - (c2b3d53)
  • (lint) Add empty-attr-value lint rule (#298) - (559313c)
  • (lint) Add uppercase-form-method lint rule (#294) - (4d37afe)
  • (lint) Add javascript-url lint rule (#293) - (791e928)
  • (lint) Add redundant-type-attr rule (#260) - (3d65c26)

๐Ÿšœ Refactor

  • (lint) Align violation structs with owned-data convention (#296) - (1f0e05f)

๐Ÿ“š Documentation

  • (lint) Auto-generate lint rule docs from violation struct doc comments (#297) - (3670b71)
  • (pycharm) Pycharm editor integration (#301) - (bbf6823)
  • (readme) Extract some part of the README to dedicated doc page (#291) - (1ea7bae)

โš™๏ธ Miscellaneous Tasks

  • (pre-commit) Chore/pre commit autoupdate and zizmor (#299) - (2dd2c0e)
  • Scope pages concurrency per PR (#315) - (57ae947)

0.2.8 - 2026-05-18

Docs | Playground

โ›ฐ๏ธ Features

  • (check) Add autofix framework to the djangofmt check command and the blocktranslate-no-trimmed rule (#276) - (0b04439)
  • (cli) Format from stdin via - or --stdin-filename (#284) - (a876757)
  • (format) Add --preserve-unquoted-attrs option (#271) - (081ab4a)
  • (format) Add support for Django template partials (#275) - (a13115e)

๐Ÿ› Bug Fixes

  • (docs) Remove smart quotes from example code (#267) - (adc40d6)

โš™๏ธ Miscellaneous Tasks

  • (msrv) Track MSRV and rust-toolchain version with renovate (#281) - (690170f)
  • (perf) Include all rust-related files in changed_files detection (#280) - (f182cfa)
  • (renovate) Add 7-day cooldown to mitigate supply chain attacks (#266) - (ce3759f)
  • Set CARGO_PROFILE_DEV_DEBUG=line-tables-only for faster builds (#270) - (06486be)

Build

  • (playground) Migrate from npm to bun, gate dep release age (#279) - (b4915de)

New Contributors โค๏ธ

0.2.7 - 2026-04-16

Docs | Playground

โ›ฐ๏ธ Features

  • (ci) Build pipeline improvements (#225) - (3e3b009)
  • (config) Use kebab-case for pyproject.toml settings (#227) - (f26e834)
  • (format) Add recursive file discovery -- enable djangofmt . to format the current folder (#229) - (385f60a)
  • (format) Add flag to allow self closing void elements (#219) - (d0d85b0)
  • (format) Improve error message for cut off html (#207) - (decbaec)
  • (format) Add JSON external formatter (#188) - (07e770b)

๐Ÿ› Bug Fixes

  • (format) Fixes extra indent for {% plural %} inside blocktranslate (#208) - (c7de06d)
  • (format) Fix formatting issues for nested template blocks in html opening tag (#205) - (378bc36)

๐Ÿšœ Refactor

  • (format) Reuse LineLength and PrintWidth newtypes to remove hardcoded default values (#189) - (13e89b5)
  • (misc) Avoid clone on check error path, add force_exclude tests (#239) - (abc267d)
  • (misc) Hoist Settings::default(), remove dead Hash derive, avoid clone on error path (#237) - (2923267)
  • (misc) Minor code quality improvement and simplifications (#235) - (1c1c856)
  • (rules) Declare lint rule category on the Violation (#230) - (6dd81ab)

๐Ÿ“š Documentation

  • (ai) Add AI policy to CONTRIBUTING.md (#228) - (479c575)
  • (check) Document check mode workaround (#200) - (8be5ca6)

โšก Performance

  • (bench) Bench linter and parser (#232) - (d1644eb)
  • (summary) Add micro bench build summary (#236) - (6ba6a80)

๐Ÿงช Testing

  • (ci) Add djangofmt check to ecosystem check (#253) - (e9ac547)
  • (ci) Add code coverage with cargo-llvm-cov and 85% CI threshold (#240) - (78a97a6)
  • (ci) Re-enable djade ecosystem check (+ tidy up justfile) (#206) - (461db3b)
  • (ci) Remove docker-run-action (#195) - (c1c080b)
  • (ecosystem-check) Allows pr comment on forks (#196) - (54b204d)
  • (lint) Cleanup lint test structure (#254) - (5bf935e)

โš™๏ธ Miscellaneous Tasks

  • (playground) Upgrade all node dependencies to latest (#252) - (da82da2)

New Contributors โค๏ธ

0.2.6 - 2026-02-10

Docs | Playground

โ›ฐ๏ธ Features

  • (config) Implement loading options from a pyproject.toml file (#186) - (5df4a98)

๐Ÿ› Bug Fixes

  • (format) Always swap wrapping quotes if attribute contains one (#180) - (0fd9ed3)
  • (format) Fix formatting of {% for %}/{% empty %} blocks (#178) - (98f8ef7)

๐Ÿ“š Documentation

  • (format) Documents workarounds for unsupported formatting (#174) - (15b1f32)
  • (github) Add Github issue template (#173) - (5821c07)
  • (ignore) Document ignore comment (#172) - (50a2fdd)

๐Ÿงช Testing

  • (ci) Only build djangofmt in ci, not other workspace crates (#170) - (7bbbfc8)

0.2.5 - 2026-01-12

Docs | Playground

โ›ฐ๏ธ Features

  • (debug) Add debug logs on external formatter failures (#143) - (a5dda3b)
  • (format) Don't format django multiline comment tags ({% comment %}...{% endcomment %}) (#162) - (6a6ca10)
  • (format) Auto-sort css statements using smacss ordering and enforce % in keyframes (#114) - (1dd641f)
  • (format) Auto-indent <script> tag content (#115) - (d959cf0)
  • (format) Keep style attribute value on a single line (#113) - (7c2f33c)
  • (format) Skip file parsing if there is a top-level <!-- djangofmt:ignore --> (#112) - (fcbab9b)
  • (format) Improve formatting of style tags and attributes (#111) - (24920db)
  • (lint) Show source file name in lint diagnostics (#159) - (6ee8c96)
  • (lint) Add building blocks for linting (#144) - (08a12a0)
  • (playground) Add a "Open issue on Github" button in the playground (#163) - (ae247b3)
  • (playground) Add a new collapsible panel to display linting errors (#148) - (067e4a0)
  • (playground) Add playground deploy to release workflow (#124) - (124b149)
  • (playground) Add an online playground (#118) - (a655190)
  • (playground) Expose a wasm format command (#122) - (847d3d8)

๐Ÿ› Bug Fixes

  • (format) Fixes handling of deprecated django {% trans %} tag (#154) - (8a7a64f)

๐Ÿšœ Refactor

  • (cargo) Switch to workspace setup (#121) - (ad75960)
  • (format) Remove line_col_to_offset and use miette SourceOffset::from_location for error reporting (#145) - (f8acc95)

โšก Performance

  • (allocator) Use jemalloc on linux (#128) - (4e92927)
  • (codspeed) Setup Codspeed CI benchmarks (#125) - (0ea2b39)
  • (perf) Update the lto and codegen-units benchmark script (#126) - (ccd7ede)

๐Ÿงช Testing

  • (binary-size) Add cargo-bloat (#136) - (2855cb2)
  • (ci) Skip codspeed in CI if no rust code changes (#158) - (8bf4432)
  • (ci) Cancel outdated ci jobs - (18595c3)
  • (clippy) Improve clippy configuration (#156) - (2de17b3)
  • (pre-commit) Switch to a managed dprint pre-commit integration (#138) - (1ccfba0)
  • (pre-commit) Simplify dprint discovery in pre-commit (#137) - (f4eb28c)
  • (review) Add coderrabit (#141) - (bac6128)

โš™๏ธ Miscellaneous Tasks

New Contributors โค๏ธ

0.2.3 - 2025-11-30

Docs | Playground

โ›ฐ๏ธ Features

  • (format) Add pretty-printing of parse errors (#104) - (fee4ee3)
  • (format) Add custom <!-- djangofmt:ignore --> directive (#102) - (c9b20bb)
  • (format) Improvements on inline node formatting (#75) - (58a4f8f)

๐Ÿšœ Refactor

  • (error) Remove anyhow and use custom error enum (#100) - (e39f71a)

๐Ÿงช Testing

  • (clippy) Enable strict clippy rules (#97) - (cd7d6ea)
  • (ecosystem-check) Fix ecosystem check comment urls and support codeberg.com (#101) - (337592c)
  • (ecosystem-check) Fix ecosystem-check and support other providers than github (#99) - (13e8bb2)

0.2.2 - 2025-06-12

Docs | Playground

โ›ฐ๏ธ Features

  • (format) Document svg files support (#74) - (60ba20f)
  • (format) Support unquoted attr value recovery for jinja tags & blocks (#73) - (ca7efc6)

0.2.1 - 2025-06-07

Docs | Playground

โ›ฐ๏ธ Features

  • (format) Improve whitespace-sensitive node formatting (#70) - (cfaa21e)

0.2.0 - 2025-05-23

Docs | Playground

โ›ฐ๏ธ Features

  • (cli) Add indent_width cli parameter (#48) - (b0d0219)
  • (fmt) Never wrap opening tag with no attrs (#20) - (8fb993a)
  • (format) Converge in one pass formatting style attr (#50) - (fadce6b)

๐Ÿ› Bug Fixes

  • (cli) Exit 1 on handled formatting failure - (b7ebb78)

๐Ÿงช Testing

  • (ecosystem-check) Stability test + Integration test with djade (#51) - (449456e)
  • (pre-commit.ci) Enable pre-commit.ci (#15) - (5ce836f)

โš™๏ธ Miscellaneous Tasks

  • (markup_fmt) Bump markup_fmt to v0.20.0 (#65) - (070e2af)
  • (rust) Rust 1.87 edition 2024 (#55) - (9aeb174)

New Contributors โค๏ธ

0.1.0 - 2025-03-16

Docs | Playground

New Contributors โค๏ธ