HTML template formatter and linter for Django, Jinja, Twig, Nunjucks, Handlebars, Mustache, Liquid, Go templates, Angular, Tera, Askama and Mako. Formats markup and template syntax together, and lints
翻译准备中
开发工具Python · HTMLGitHub @djlint自行安装运营者未确认
试用过了吗? 点一下就好,无需登录。
HTML template formatter and linter for Django, Jinja, Twig, Nunjucks, Handlebars, Mustache, Liquid, Go templates, Angular, Tera, Askama and Mako. Formats markup and template syntax together, and lints for accessibility, correctness and style. CLI, pre-commit hook and VS Code extension.
翻译准备中
正在加载完整 README。
查看完整 README ↗Every language in your stack has a formatter and a linter, except HTML templates. Generic HTML tools can't parse {% %} and {{ }}, and template engines don't care what the markup around them looks like. So indentation drifts, tags go unclosed and spacing goes wherever, and none of it gets caught in review.
djLint reads HTML and the template syntax inside it, with profiles for Django, Jinja, Twig, Nunjucks, Handlebars, Liquid, Go templates and more.
Take a template only its author could love:
{% block content %}
<SECTION class="posts">
<h2>Latest posts</h2>
{%if posts%}
<ul>
{% for post in posts %}
<li>
<a href="{% url 'post' post.slug %}" class="post-link {%if post.featured%}is-featured{%endif%}" data-analytics-id="post-{{post.id}}" aria-label="Read {{post.title}}">{{post.title|title}}</a>
</li>
{% endfor %}
</ul>
{%else%}
<p>No posts yet.</p>
{%endif%}
</SECTION>
{% endblock %}
One djlint --reformat --single-attribute-per-line later:
{% block content %}
<section class="posts">
<h2>Latest posts</h2>
{% if posts %}
<ul>
{% for post in posts %}
<li>
<a
href="{% url 'post' post.slug %}"
class="post-link {% if post.featured %}is-featured{% endif %}"
data-analytics-id="post-{{ post.id }}"
aria-label="Read {{ post.title }}"
>{{ post.title|title }}</a>
</li>
{% endfor %}
</ul>
{% else %}
<p>No posts yet.</p>
{% endif %}
</section>
{% endblock %}
One command rebuilt the indentation, fixed the tag case, split the long tag into one attribute per line, normalized the template tags and collapsed stray blank lines.
The linter catches what formatting can't fix: orphan tags, missing alt attributes, hard-coded URLs and dozens of other checks.
You can try it on your own templates in the online playground.
Add it to your project as a development dependency with uv
uv add --dev djlint
Or install it as a standalone tool
uv tool install djlint
Or with pip
pip install djlint
Or with pipx
pipx install djlint
Or with the community-maintained Homebrew formula on macOS or Linux
brew install djlint
Or with npm. Warning: the npm package is only a wrapper. Its install script runs pip on whatever python3 is on your system path and installs the djLint version of that npm release, which can replace a newer djLint with an older one. npm will not manage or uninstall the actual package, so prefer pip when you can.
npm i djlint
To run djLint on every commit, see pre-commit.
Lint your project
djlint . --lint
Check your format
djlint . --check --single-attribute-per-line
Fix my format!
djlint . --reformat --single-attribute-per-line
Set a --profile to enable the rules and formatting of your template engine
djlint . --reformat --single-attribute-per-line --profile=django
Or use pre-commit to reformat, then lint!
repos:
- repo: https://github.com/djlint/djLint
rev: v1.50.0 # use the latest version instead
hooks:
- id: djlint-reformat
- id: djlint
djlint --lsp. See the setup for each.Add a badge to your projects readme.md:
[](https://djlint.com)
Add a badge to your readme.rst:
.. image:: https://img.shields.io/badge/html%20style-djlint-blue.svg
:target: https://djlint.com
Looks like this:
Yes!
Would you like to add a rule to the linter? Take a look at the linter docs and the rule definitions.
Local setup takes two commands:
# install uv first: https://docs.astral.sh/uv/getting-started/installation/
uv sync
# run the test suite
uv run pytest