prettier-plugin-nunjucks
v0.1.4
Published
Prettier plugin for Nunjucks templates (.njk, .nunjucks, .nunj)
Downloads
236
Maintainers
Readme
prettier-plugin-nunjucks
Prettier plugin for HTML-heavy Nunjucks templates.
It formats .njk / .nunjucks / .nunj files with stable, idempotent output and keeps Nunjucks statement tags, variables, comments, whitespace-control markers, and raw/verbatim blocks in the Nunjucks syntax instead of treating them as Handlebars or generic HTML.
Install
npm install --save-dev prettier prettier-plugin-nunjucksQuick Start
Recommended config:
/** @type {import("prettier").Config} */
module.exports = {
plugins: ["prettier-plugin-nunjucks"],
overrides: [
{
files: ["*.njk", "*.nunjucks", "*.nunj"],
options: {
parser: "nunjucks",
},
},
],
};The explicit override makes editor format-on-save deterministic, especially in projects that mix HTML, Nunjucks, Jinja-like templates, and other Prettier plugins.
Configuration Patterns
1. Minimal plugin setup
Use this only after verifying your Prettier/editor resolves .njk files to this plugin.
/** @type {import("prettier").Config} */
module.exports = {
plugins: ["prettier-plugin-nunjucks"],
};2. Explicit Nunjucks override
Use this for shared projects and CI.
/** @type {import("prettier").Config} */
module.exports = {
plugins: ["prettier-plugin-nunjucks"],
overrides: [
{
files: ["src/**/*.{njk,nunjucks,nunj}"],
options: {
parser: "nunjucks",
},
},
],
};3. Projects with Nunjucks in HTML files
If your project stores Nunjucks templates as .html, force the parser for those paths.
{
"plugins": ["prettier-plugin-nunjucks"],
"overrides": [
{
"files": ["views/**/*.html", "templates/**/*.html"],
"options": { "parser": "nunjucks" }
}
]
}4. Project style options
Normal Prettier options still apply.
/** @type {import("prettier").Config} */
module.exports = {
plugins: ["prettier-plugin-nunjucks"],
overrides: [
{
files: ["**/*.{njk,nunjucks,nunj}"],
options: {
parser: "nunjucks",
printWidth: 100,
tabWidth: 2,
singleQuote: true,
htmlWhitespaceSensitivity: "ignore",
},
},
],
};5. Local plugin path during dogfooding
Useful before publishing a new npm version.
/** @type {import("prettier").Config} */
module.exports = {
plugins: ["../prettier-plugin-nunjucks/dist/plugin.js"],
overrides: [
{
files: ["**/*.{njk,nunjucks,nunj}"],
options: {
parser: "nunjucks",
},
},
],
};Custom extension tags
Nunjucks extensions can define project-specific tags. Unknown single statement tags are preserved by default; tags that behave like blocks or branches can be configured explicitly.
/** @type {import("prettier").Config} */
module.exports = {
plugins: ["prettier-plugin-nunjucks"],
overrides: [
{
files: ["**/*.{njk,nunjucks,nunj}"],
options: {
parser: "nunjucks",
blockTags: ["remote"],
forkTags: ["error"],
},
},
],
};Input:
{% remote "/stuff" %}
This content will be replaced with the content from /stuff
{% error %}
There was an error fetching /stuff
{% endremote %}Output:
{% remote "/stuff" %}
This content will be replaced with the content from /stuff
{% error %}
There was an error fetching /stuff
{% endremote %}CLI
Published package:
npx prettier --write "src/**/*.{njk,nunjucks,nunj}" --plugin prettier-plugin-nunjucks --parser nunjucksLocal plugin build:
npx prettier --write "src/**/*.{njk,nunjucks,nunj}" --plugin ../prettier-plugin-nunjucks/dist/plugin.js --parser nunjucksAPI
const prettier = require("prettier");
const plugin = require("prettier-plugin-nunjucks");
async function run(source) {
return prettier.format(source, {
filepath: "template.njk",
parser: "nunjucks",
plugins: [plugin],
});
}What The Plugin Handles Today
- HTML elements, void elements, comments, and custom elements
- Nunjucks variables:
{{ value }}, including whitespace control{{- value -}} - Nunjucks comments:
{# comment #} - statement tags such as
extends,include,import,from, and custom extension tags if/elif/elseif/else/endiffor/else/endforasyncEach/endeachandasyncAll/endallblock/endblockmacro/endmacro- single-statement
setand blockset/endset filter/endfiltercall/endcallraw/endrawandverbatim/endverbatimpreserved verbatim- Nunjucks inside attribute values
- Nunjucks blocks that emit attributes
- multiline class formatting with conditional modifiers and whitespace-control blocks
- embedded JavaScript / CSS formatting for plain
script/styletags when the content is safe to parse - raw
script/stylepreservation when content contains Nunjucks or non-JS/CSS types - custom extension block/fork tags via
blockTags,inlineTags, andforkTags - incomplete/unmatched template structures preserved as raw nodes instead of crashing
Real-World Examples
Branch chains
{% if primary %}
Primary
{% elif secondary %}
Secondary
{% else %}
Fallback
{% endif %}Conditional class values
Input:
<fieldset class="govuk-fieldset {%- if params.classes %} {{ params.classes }}{% endif %}">
{{ caller() }}
</fieldset>Output:
<fieldset
class="
govuk-fieldset
{%- if params.classes %}
{{ params.classes }}
{% endif %}
"
>
{{ caller() }}
</fieldset>Blocks that emit attributes
<button
{% if disabled %}
disabled
{% elif primary %}
class="primary"
{% else %}
data-empty="1"
{% endif %}
>
Save
</button>Raw/verbatim content
{% raw %}<div>{{ untouched }}</div>{% endraw %}
{% verbatim %}{{ also_untouched }}{% endverbatim %}Quality Gates
Core check before release:
npm run checkPackage/install checks:
npm run pack:check
npm run smoke:install
npm auditReal-world corpus check:
npm run build
npm run corpus:ossThe OSS corpus currently covers 1,125 real-world Nunjucks templates across 13 public projects, including web.dev, 11ty, Jamstack, A11Y Project, Mozilla Nunjucks, GOV.UK Frontend, and GOV.UK Design System. The check formats each file twice and fails on crashes or non-idempotent output.
Maintainer Release
Run the checks above, then publish from this repository root:
npm publish --access public