# Spotless: Keep your code spotless with Maven [![MavenCentral](https://img.shields.io/badge/mavencentral-com.diffplug.spotless%3Aspotless--maven--plugin-blue.svg)](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.diffplug.spotless%22%20AND%20a%3A%22spotless-maven-plugin%22) [![Changelog](https://img.shields.io/badge/changelog-2.43.0-blue.svg)](CHANGES.md) [![Javadoc](https://img.shields.io/badge/javadoc-here-blue.svg)](https://javadoc.io/doc/com.diffplug.spotless/spotless-maven-plugin/2.43.0/index.html) Spotless is a general-purpose formatting plugin used by [6,000 projects on GitHub (Jan 2023)](https://github.com/search?l=Maven+POM&q=spotless&type=Code). It is completely à la carte, but also includes powerful "batteries-included" if you opt-in. Plugin requires a version of Maven higher or equal to 3.1.0. To people who use your build, it looks like this: ```console user@machine repo % mvn spotless:check [ERROR] > The following files had format violations: [ERROR] src\main\java\com\diffplug\gradle\spotless\FormatExtension.java [ERROR] -\t\t····if·(targets.length·==·0)·{ [ERROR] +\t\tif·(targets.length·==·0)·{ [ERROR] Run 'mvn spotless:apply' to fix these violations. user@machine repo % mvn spotless:apply [INFO] BUILD SUCCESS user@machine repo % mvn spotless:check [INFO] BUILD SUCCESS ``` ### Table of Contents - [**Quickstart**](#quickstart) - [Requirements](#requirements) - [Binding to maven phase](#binding-to-maven-phase) - **Languages** - [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat)) - [Groovy](#groovy) ([eclipse groovy](#eclipse-groovy)) - [Kotlin](#kotlin) ([ktfmt](#ktfmt), [ktlint](#ktlint), [diktat](#diktat), [prettier](#prettier)) - [Scala](#scala) ([scalafmt](#scalafmt)) - [C/C++](#cc) ([eclipse cdt](#eclipse-cdt)) - [Python](#python) ([black](#black)) - [Antlr4](#antlr4) ([antlr4formatter](#antlr4formatter)) - [Sql](#sql) ([dbeaver](#dbeaver)) - [Maven Pom](#maven-pom) ([sortPom](#sortpom)) - [Markdown](#markdown) ([flexmark](#flexmark)) - [Typescript](#typescript) ([tsfmt](#tsfmt), [prettier](#prettier), [ESLint](#eslint-typescript), [Biome](#biome)) - [Javascript](#javascript) ([prettier](#prettier), [ESLint](#eslint-javascript), [Biome](#biome)) - [JSON](#json) ([simple](#simple), [gson](#gson), [jackson](#jackson), [Biome](#biome), [jsonPatch](#jsonPatch)) - [YAML](#yaml) - [Gherkin](#gherkin) - [Go](#go) - Multiple languages - [Prettier](#prettier) ([plugins](#prettier-plugins), [npm detection](#npm-detection), [`.npmrc` detection](#npmrc-detection), [caching `npm install` results](#caching-results-of-npm-install)) - [eclipse web tools platform](#eclipse-web-tools-platform) - [Biome](#biome) ([binary detection](#biome-binary), [config file](#biome-configuration-file), [input language](#biome-input-language)) - **Language independent** - [Generic steps](#generic-steps) - [License header](#license-header) ([slurp year from git](#retroactively-slurp-years-from-git-history)) - [How can I enforce formatting gradually? (aka "ratchet")](#ratchet) - [`spotless:off` and `spotless:on`](#spotlessoff-and-spotlesson) - [Line endings and encodings (invisible stuff)](#line-endings-and-encodings-invisible-stuff) - [Disabling warnings and error messages](#disabling-warnings-and-error-messages) - [How do I preview what `mvn spotless:apply` will do?](#how-do-i-preview-what-mvn-spotlessapply-will-do) - [Can I apply Spotless to specific files?](#can-i-apply-spotless-to-specific-files) - [Example configurations (from real-world projects)](#examples) ***Contributions are welcome, see [the contributing guide](../CONTRIBUTING.md) for development info.*** ## Quickstart To use it in your pom, just [add the Spotless plugin](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.diffplug.spotless%22%20AND%20a%3A%22spotless-maven-plugin%22), and configure it like so: ```xml com.diffplug.spotless spotless-maven-plugin ${spotless.version} origin/main .gitattributes .gitignore true 4 1.8 true false /* (C)$YEAR */ ``` Spotless consists of a list of formats (in the example above, `misc` and `java`), and each format has: - a `target` (the files to format), which you set with [`includes` and `excludes`](https://github.com/diffplug/spotless/blob/989abbecff4d8373c6111c1a98f359eadc532429/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java#L51-L55) - a list of `FormatterStep`, which are just `String -> String` functions, such as [`replace`](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Replace.java), [`replaceRegex`](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/ReplaceRegex.java), [`trimTrailingWhitespace`](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/TrimTrailingWhitespace.java), [`indent`](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Indent.java), [`prettier`](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Prettier.java), [`eclipseWtp`](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/EclipseWtp.java), and [`licenseHeader`](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/LicenseHeader.java). - **order matters**, and this is good! (More info [here](https://github.com/diffplug/spotless/blob/main/PADDEDCELL.md) and [here](https://github.com/diffplug/spotless/blob/main/CONTRIBUTING.md#how-spotless-works)) - For example, `googleJavaFormat` always indents with spaces, but some wish it had a tab mode - ```xml // this works true2 ``` - ```xml true2 // the tab indentation gets overwritten ``` ### Requirements Spotless requires Maven to be running on JRE 11+. To use JRE 8, go back to [`2.30.0` or older](https://github.com/diffplug/spotless/blob/main/plugin-maven/CHANGES.md#2300---2023-01-13). ### Binding to maven phase By default, spotless:check is bound to verify maven phase. This means it is not required to explicitly bind the plugin execution, and the following will suffice; ```xml check ``` with this `mvn verify` will run `spotless:check`. If you require the check goal to be run with any other maven phase (i.e. compile) then it can be configured as below; ```xml check compile ``` ## Java [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/java). ```xml src/main/java/**/*.java src/test/java/**/*.java false java|javax,org,com,com.diffplug,,\#com.diffplug,\# false com.example.MyPackage com.example.myClass /* (C)$YEAR */ ``` ### removeUnusedImports ```xml google-java-format ``` ### google-java-format [homepage](https://github.com/google/google-java-format). [changelog](https://github.com/google/google-java-format/releases). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/GoogleJavaFormat.java). ```xml 1.8 true false com.google.googlejavaformat:google-java-format ``` ### palantir-java-format [homepage](https://github.com/palantir/palantir-java-format). [changelog](https://github.com/palantir/palantir-java-format/releases). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/PalantirJavaFormat.java). ```xml 2.39.0 false ``` ### eclipse jdt [homepage](https://www.eclipse.org/downloads/packages/). [compatible versions](https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/eclipse_jdt_formatter). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Eclipse.java). See [here](../ECLIPSE_SCREENSHOTS.md) for screenshots that demonstrate how to get and install the config file mentioned below. ```xml 4.26 ${project.basedir}/eclipse-formatter.xml ``` ### formatAnnotations Type annotations should be on the same line as the type that they qualify. ```java @Override @Deprecated @Nullable @Interned String s; ``` However, some tools format them incorrectly, like this: ```java @Override @Deprecated @Nullable @Interned String s; ``` To fix the incorrect formatting, add the `formatAnnotations` rule after a Java formatter. For example: ```XML ``` This does not re-order annotations, it just removes incorrect newlines. A type annotation is an annotation that is meta-annotated with `@Target({ElementType.TYPE_USE})`. Because Spotless cannot necessarily examine the annotation definition, it uses a hard-coded list of well-known type annotations. You can make a pull request to add new ones. In the future there will be mechanisms to add/remove annotations from the list. These mechanisms already exist for the Gradle plugin. ### Cleanthat [homepage](https://github.com/solven-eu/cleanthat). CleanThat enables automatic refactoring of Java code. [ChangeLog](https://github.com/solven-eu/cleanthat/blob/master/CHANGES.MD) ```xml 2.8 ${maven.compiler.source} SafeAndConsensual LiteralsFirstInComparisons OptionalNotEmpty false ``` ## Groovy [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/groovy/Groovy.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/groovy). ```xml src/main/groovy/**/*.groovy src/test/groovy/**/*.groovy java|javax,org,com,com.diffplug,,\#com.diffplug,\# /* (C)$YEAR */ ``` ### eclipse groovy [homepage](https://github.com/groovy/groovy-eclipse/wiki). [changelog](https://github.com/groovy/groovy-eclipse/releases). [compatible versions](https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/groovy_eclipse_formatter). The Groovy formatter uses some of the [eclipse jdt](#eclipse-jdt) configuration parameters in addition to groovy-specific ones. All parameters can be configured within a single file, like the Java properties file [greclipse.properties](../testlib/src/main/resources/groovy/greclipse/format/greclipse.properties) in the previous example. The formatter step can also load the [exported Eclipse properties](../ECLIPSE_SCREENSHOTS.md) and augment it with the `.metadata/.plugins/org.eclipse.core.runtime/.settings/org.codehaus.groovy.eclipse.ui.prefs` from your Eclipse workspace as shown below. ```xml 4.26 ${project.basedir}/greclipse.properties ``` Groovy-Eclipse formatting errors/warnings lead per default to a build failure. This behavior can be changed by adding the property/key value `ignoreFormatterProblems=true` to a configuration file. In this scenario, files causing problems, will not be modified by this formatter step. ## Kotlin [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Kotlin.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin). ```xml src/main/kotlin/**/*.kt src/test/kotlin/**/*.kt /* (C)$YEAR */ ``` ### ktfmt [homepage](https://github.com/facebookincubator/ktfmt). [changelog](https://github.com/facebookincubator/ktfmt/releases). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktfmt.java). ```xml 0.39 ``` ### ktlint [homepage](https://github.com/pinterest/ktlint). [changelog](https://github.com/pinterest/ktlint/releases). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Ktlint.java). Spotless respects the `.editorconfig` settings by providing `editorConfigPath` option. ([ktlint docs](https://github.com/pinterest/ktlint#editorconfig)). Additionally, `editorConfigOverride` options will override what's supplied in `.editorconfig` file. ```xml 1.0.0 true true io.nlopez.compose.rules:ktlint:0.3.3 ``` ### diktat [homepage](https://github.com/cqfn/diKTat). [changelog](https://github.com/cqfn/diKTat/releases). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/kotlin/Diktat.java). You can provide configuration path manually as `configFile`. ```xml 1.0.1 full/path/to/diktat-analysis.yml ``` ## Scala [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/scala/Scala.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/scala). ```xml src/main/scala/**/*.scala src/test/scala/**/*.scala src/main/scala/**/*.sc src/test/scala/**/*.sc /* (C)$YEAR */ package ``` ### scalafmt [homepage](https://scalameta.org/scalafmt/). [changelog](https://github.com/scalameta/scalafmt/releases). [config docs](https://scalameta.org/scalafmt/docs/configuration.html). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/scala/Scalafmt.java). ```xml 3.5.9 ${project.basedir}/scalafmt.conf 2.13 ``` ## C/C++ [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/cpp/Cpp.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/cpp). ```xml src/native/** /* (C)$YEAR */ ``` ### eclipse cdt [homepage](https://www.eclipse.org/cdt/). [compatible versions](https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/eclipse_cdt_formatter). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/cpp/EclipseCdt.java). ```xml 11.0 ${project.basedir}/eclipse-cdt.xml ``` ## Python [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/python/Python.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/python/Black.java). ```xml src/main/**/*.py ``` ### black [homepage](https://github.com/psf/black). [changelog](https://github.com/psf/black/blob/master/CHANGES.md). ```xml 19.10b0 C:/myuser/.pyenv/versions/3.8.0/scripts/black.exe ``` ## Antlr4 [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/antlr4/Antlr4.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/antlr4). ```xml src/*/antlr4/**/*.g4 /* (C)$YEAR */ ``` ### antlr4Formatter [homepage](https://github.com/antlr/Antlr4Formatter). [available versions](https://search.maven.org/artifact/com.khubla.antlr4formatter/antlr4-formatter). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/antlr4/Antlr4Formatter.java). ```xml 1.2.1 ``` ## SQL [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/sql/Sql.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/sql). ```xml src/main/resources/**/*.sql ``` ### dbeaver [homepage](https://dbeaver.io/). DBeaver is only distributed as a monolithic jar, so the formatter used here was copy-pasted into Spotless, and thus there is no version to change. ```xml dbeaver.properties ``` Default configuration file, other options [available here](https://github.com/diffplug/spotless/blob/main/lib/src/main/java/com/diffplug/spotless/sql/dbeaver/DBeaverSQLFormatterConfiguration.java). ```properties # case of the keywords (UPPER, LOWER or ORIGINAL) sql.formatter.keyword.case=UPPER # Statement delimiter sql.formatter.statement.delimiter=; # Indentation style (space or tab) sql.formatter.indent.type=space # Number of identation characters sql.formatter.indent.size=4 ``` ## Maven POM [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/Pom.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java). ```xml pom.xml ``` ### sortPom [homepage](https://github.com/Ekryd/sortpom). [code](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/pom/SortPom.java). All configuration settings are optional, they are described in detail [here](https://github.com/Ekryd/sortpom/wiki/Parameters). ```xml UTF-8 ${line.separator} true false true true 2 false false recommended_2008_06 false false false ``` ## Markdown [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/markdown/Markdown.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/markdown). ```xml **/*.md ``` ### Flexmark [homepage](https://github.com/vsch/flexmark-java). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/markdown/Flexmark.java). Flexmark is a flexible Commonmark/Markdown parser that can be used to format Markdown files. It supports different [flavors of Markdown](https://github.com/vsch/flexmark-java#markdown-processor-emulation) and [many formatting options](https://github.com/vsch/flexmark-java/wiki/Markdown-Formatter#options). Currently, none of the available options can be configured yet. It uses only the default options together with `COMMONMARK` as `FORMATTER_EMULATION_PROFILE`. ## Typescript [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/typescript/Typescript.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/typescript). ```xml src/**/*.ts /* (C)$YEAR */ (import|const|declare|export|var) ``` ### tsfmt [npm](https://www.npmjs.com/package/typescript-formatter). [changelog](https://github.com/vvakame/typescript-formatter/blob/master/CHANGELOG.md). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/typescript/Tsfmt.java). *Please note:* The auto-discovery of config files (up the file tree) will not work when using tsfmt within spotless, hence you are required to provide resolvable file paths for config files, or alternatively provide the configuration inline. See [tsfmt's default config settings](https://github.com/vvakame/typescript-formatter/blob/7764258ad42ac65071399840d1b8701868510ca7/lib/utils.ts#L11L32) for what is available. ```xml 7.2.2 3.9.5 6.1.2 1 true ${project.basedir}/tsconfig.json ${project.basedir}/tslint.json ${project.basedir}/vscode.json ${project.basedir}/tsfmt.json ``` **Prerequisite: tsfmt requires a working NodeJS version** For details, see the [npm detection](#npm-detection), [`.npmrc` detection](#npmrc-detection) and [caching results of `npm install`](#caching-results-of-npm-install) sections of prettier, which apply also to tsfmt. ### ESLint (typescript) [npm](https://www.npmjs.com/package/eslint). [changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md). *Please note:* The auto-discovery of config files (up the file tree) will not work when using ESLint within spotless, hence you are required to provide resolvable file paths for config files, or alternatively provide the configuration inline. The configuration is very similar to the [ESLint (Javascript)](#eslint-javascript) configuration. In typescript, a reference to a `tsconfig.json` is required. ```xml 8.30.0 8.30.0 1.2.1 eslint 8.30.0 @eslint/my-plugin-typescript 0.14.2 ${project.basedir}/.eslintrc.js { env: { browser: true, es2021: true }, extends: 'standard-with-typescript', overrides: [ ], parserOptions: { ecmaVersion: 'latest', sourceType: 'module', project: './tsconfig.json', }, rules: { } } ${project.basedir}/tsconfig.json ``` **Prerequisite: ESLint requires a working NodeJS version** For details, see the [npm detection](#npm-detection), [`.npmrc` detection](#npmrc-detection) and [caching results of `npm install`](#caching-results-of-npm-install) sections of prettier, which apply also to ESLint. ## Javascript [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/javascript/Javascript.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/javascript). ```xml src/**/*.js /* (C)$YEAR */ REGEX_TO_DEFINE_TOP_OF_FILE ``` ### ESLint (Javascript) [npm](https://www.npmjs.com/package/eslint). [changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md). *Please note:* The auto-discovery of config files (up the file tree) will not work when using ESLint within spotless, hence you are required to provide resolvable file paths for config files, or alternatively provide the configuration inline. The configuration is very similar to the [ESLint (Typescript)](#eslint-typescript) configuration. In javascript, *no* `tsconfig.json` is supported. ```xml 8.30.0 8.30.0 1.2.1 eslint 8.30.0 @eslint/my-plugin-javascript 0.14.2 ${project.basedir}/.eslintrc.js { env: { browser: true, es2021: true }, extends: 'standard', overrides: [ ], parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, rules: { } } ``` **Prerequisite: ESLint requires a working NodeJS version** For details, see the [npm detection](#npm-detection), [`.npmrc` detection](#npmrc-detection) and [caching results of `npm install`](#caching-results-of-npm-install) sections of prettier, which apply also to ESLint. ## JSON - `com.diffplug.spotless.maven.json.Json` [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/Json.java) ```xml src/**/*.json ``` ### simple Uses a JSON pretty-printer that optionally allows configuring the number of spaces that are used to pretty print objects: ```xml 4 ``` ### Gson Uses Google Gson to also allow sorting by keys besides custom indentation - useful for i18n files. ```xml 4 false false 2.8.1 ``` Notes: * There's no option in Gson to leave HTML as-is (i.e. escaped HTML would remain escaped, raw would remain raw). Either all HTML characters are written escaped or none. Set `escapeHtml` if you prefer the former. * `sortByKeys` will apply lexicographic order on the keys of the input JSON. See the [javadoc of String](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#compareTo(java.lang.String)) for details. ### Jackson Uses Jackson for formatting. ```xml 2.14.1 true false true|false false true|false false ``` ### jsonPatch Uses [zjsonpatch](https://github.com/flipkart-incubator/zjsonpatch) to apply [JSON Patches](https://jsonpatch.com/) as per [RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902/) to JSON documents. This enables you to add, replace or remove properties at locations in the JSON document that you specify using [JSON Pointers](https://datatracker.ietf.org/doc/html/rfc6901/). For example, to apply the patch from the [JSON Patch homepage](https://jsonpatch.com/#the-patch): ```xml [ { "op": "replace", "path": "/baz", "value": "boo" }, { "op": "add", "path": "/hello", "value": ["world"] }, { "op": "remove", "path": "/foo" } ] ``` ## YAML - `com.diffplug.spotless.maven.FormatterFactory.addStepFactory(FormatterStepFactory)` [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Yaml.java) ```xml src/**/*.yaml ``` ### jackson Uses Jackson and YAMLFactory to pretty print objects: ```xml 2.14.1 true false true|false true false true|false false ``` ## Shell - `com.diffplug.spotless.maven.FormatterFactory.addStepFactory(FormatterStepFactory)` [code](./src/main/java/com/diffplug/spotless/maven/shell/Shell.java) ```xml scripts/**/*.sh ``` ### shfmt [homepage](https://github.com/mvdan/sh). [changelog](https://github.com/mvdan/sh/blob/master/CHANGELOG.md). When formatting shell scripts via `shfmt`, configure `shfmt` settings via `.editorconfig`. ```xml 3.8.0 /opt/homebrew/bin/shfmt ``` ## Gherkin - `com.diffplug.spotless.maven.FormatterFactory.addStepFactory(FormatterStepFactory)` [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/gherkin/Gherkin.java) ```xml src/**/*.feature ``` ### gherkinUtils [homepage](https://github.com/cucumber/gherkin-utils). [changelog](https://github.com/cucumber/gherkin-utils/blob/main/CHANGELOG.md). Uses a Gherkin pretty-printer that optionally allows configuring the number of spaces that are used to pretty print objects: ```xml 8.0.2 ``` ## Go - `com.diffplug.spotless.maven.FormatterFactory.addStepFactory(FormatterStepFactory)` [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/go/Go.java) ```xml src/**/*.go ``` ### gofmt Standard Go formatter, part of Go distribution. ```xml go1.25.1 /opt/sdks/go1.25.1/bin/go ``` ## Prettier [homepage](https://prettier.io/). [changelog](https://github.com/prettier/prettier/blob/master/CHANGELOG.md). [official plugins](https://prettier.io/docs/en/plugins.html#official-plugins). [community plugins](https://prettier.io/docs/en/plugins.html#community-plugins). Prettier is a formatter that can format almost every anything - JavaScript, JSX, Angular, Vue, Flow, TypeScript, CSS, Less, SCSS, HTML, JSON, GraphQL, Markdown (including GFM and MDX), and YAML. It can format even more [using plugins](https://prettier.io/docs/en/plugins.html) (PHP, Ruby, Swift, XML, Apex, Elm, Java (!!), Kotlin, pgSQL, .properties, solidity, svelte, toml, shellscript, ...). You can use prettier in any language-specific format, but usually you will be creating a generic format. ```xml src/**/typescript/**/*.ts 1.19.0 1.19.0 prettier 2.8.8 @prettier/plugin-php 0.19.6 ${project.basedir}/path/to/configfile true @prettier/plugin-php ``` **Limitations:** - The auto-discovery of config files (up the file tree) will not work when using prettier within spotless. - Prettier's override syntax is not supported when using prettier within spotless. To apply prettier to more kinds of files, just add more formats ```xml src/**/*.ts src/**/*.css ``` ### prettier plugins Since spotless uses the actual npm prettier package behind the scenes, it is possible to use prettier with [plugins](https://prettier.io/docs/en/plugins.html#official-plugins) or [community-plugins](https://www.npmjs.com/search?q=prettier-plugin) in order to support even more file types. ```xml src/*/java/**/*.java 2.8.8 2.2.0 4 java prettier-plugin-java src/**/*.php prettier 2.8.8 @prettier/plugin-php 0.19.6 3 php @prettier/plugin-php ``` ### npm detection Prettier is based on NodeJS, so to use it, a working NodeJS installation (especially npm) is required on the host running spotless. Spotless will try to auto-discover an npm installation. If that is not working for you, it is possible to directly configure the npm and/or node binary to use. ```xml /usr/bin/npm /usr/bin/node ``` If you provide both `npmExecutable` and `nodeExecutable`, spotless will use these paths. If you specify only one of the two, spotless will assume the other one is in the same directory. ### `.npmrc` detection Spotless picks up npm configuration stored in a `.npmrc` file either in the project directory or in your user home. Alternatively you can supply spotless with a location of the `.npmrc` file to use. (This can be combined with `npmExecutable` and `nodeExecutable`, of course.) ```xml /usr/local/shared/.npmrc ``` ### Caching results of `npm install` Spotless uses `npm` behind the scenes to install `prettier`. This can be a slow process, especially if you are using a slow internet connection or if you need large plugins. You can instruct spotless to cache the results of the `npm install` calls, so that for the next installation, it will not need to download the packages again, but instead reuse the cached version. ```xml true /usr/local/shared/.spotless-npm-install-cache ``` Depending on your filesystem and the location of the cache directory, spotless will use hardlinks when caching the npm packages. If that is not possible, it will fall back to copying the files. ## Eclipse web tools platform [changelog](https://www.eclipse.org/webtools/). [compatible versions](https://github.com/diffplug/spotless/tree/main/lib-extra/src/main/resources/com/diffplug/spotless/extra/eclipse_wtp_formatter). ```xml src/**/resources/**/*.xml src/**/resources/**/*.xsd XML ${project.basedir}/xml.prefs ${project.basedir}/additional.properties 4.21.0 ``` The WTP formatter accept multiple configuration files. All Eclipse configuration file formats are accepted as well as simple Java property files. Omit the `` entirely to use the default Eclipse configuration. The following formatters and configurations are supported: | Type | Configuration | File location | ---- | ------------------- | ------------- | CSS | editor preferences | .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.css.core.prefs | | cleanup preferences | .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.css.core.prefs | HTML | editor preferences | .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.html.core.prefs | | cleanup preferences | .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.html.core.prefs | | embedded CSS | .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.css.core.prefs | | embedded JS | Use the export in the Eclipse editor configuration dialog | JS | editor preferences | Use the export in the Eclipse editor configuration dialog | JSON | editor preferences | .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.json.core.prefs | XML | editor preferences | .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.xml.core.prefs Note that `HTML` should be used for `X-HTML` sources instead of `XML`. The Eclipse XML catalog cannot be configured for the Spotless WTP formatter, instead a user defined catalog file can be specified using the property `userCatalog`. Catalog versions 1.0 and 1.1 are supported by Spotless. Unlike Eclipse, Spotless WTP ignores per default external URIs in schema location hints and external entities. To allow the access of external URIs, set the property `resolveExternalURI` to true. ## Biome [homepage](https://biomejs.dev/). [changelog](https://github.com/biomejs/biome/blob/main/CHANGELOG.md). Biome is a formatter that for the frontend written in Rust, which has a native binary, does not require Node.js and as such, is pretty fast. It can currently format JavaScript, TypeScript, JSX, and JSON, and may support [more frontend languages](https://biomejs.dev/internals/language-support/) such as CSS in the future. Note: Biome [was formerly called Rome](https://biomejs.dev/blog/annoucing-biome/). Configurations with the old `` tag and `rome(...)` function are still supported for the time being. This will be removed in a future version, you should migrate to the new `` tag or `biome(...)` function. The configuration remains the same, you only need to update the version. If you are using a custom `rome.json` configuration file, you need to rename it to `biome.json`. You can use Biome in any language-specific format for supported languages, but usually you will be creating a generic format. ```xml src/**/typescript/**/*.ts 1.2.0 ${project.basedir}/path/to/config/dir ts ``` To apply Biome to more kinds of files with a different configuration, just add more formats: ```xml src/**/*.ts src/**/*.js ``` **Limitations:** - The auto-discovery of config files (up the file tree) will not work when using Biome within spotless. - The `ignore` option of the `biome.json` configuration file will not be applied. Include and exclude patterns are configured in the spotless configuration in the Maven pom instead. Note: Due to a limitation of biome, if the name of a file matches a pattern in the `ignore` option of the specified `biome.json` configuration file, it will not be formatted, even if included in the biome configuration section of the Maven pom. You could specify a different `biome.json` configuration file without an `ignore` pattern to circumvent this. Note 2: Biome is hard-coded to ignore certain special files, such as `package.json` or `tsconfig.json`. These files will never be formatted. ### Biome binary To format with Biome, spotless needs to find the Biome binary. By default, spotless downloads the binary for the given version from the network. This should be fine in most cases, but may not work e.g. when there is not connection to the internet. To download the Biome binary from the network, just specify a version: ```xml 1.2.0 ``` Spotless uses a default version when you do not specify a version, but this may change at any time, so we recommend that you always set the Biome version you want to use. Optionally, you can also specify a directory for the downloaded Biome binaries (defaults to `~/.m2/repository/com/diffplug/spotless/spotless-data/biome`): ```xml 1.2.0 ${user.home}/biome ``` To use a fixed binary, omit the `version` and specify a `pathToExe`: ```xml ${project.basedir}/bin/biome ``` Absolute paths are used as-is. Relative paths are resolved against the project's base directory. To use a pre-installed Biome binary on the user's path, specify just a name without any slashes / backslashes: ```xml biome ``` ### Biome configuration file Biome is a biased formatter and linter without many options, but there are a few basic options. Biome uses a file named [biome.json](https://biomejs.dev/reference/configuration/) for its configuration. When none is specified, the default configuration from Biome is used. To use a custom configuration: ```xml ${project.basedir} ``` ### Biome input language By default, Biome detects the language / syntax of the files to format automatically from the file extension. This may fail if your source code files have unusual extensions for some reason. If you are using the generic format, you can force a certain language like this: ```xml src/**/typescript/**/*.mjson 1.2.0 json ``` The following languages are currently recognized: * `js` -- JavaScript * `jsx` -- JavaScript + JSX (React) * `js?` -- JavaScript, with or without JSX, depending on the file extension * `ts` -- TypeScript * `tsx` -- TypeScript + JSX (React) * `ts?` -- TypeScript, with or without JSX, depending on the file extension * `json` -- JSON ## Generic steps [Prettier](#prettier), [eclipse wtp](#eclipse-web-tools-platform), and [license header](#license-header) are available in every format, and they each have their own section. As mentioned in the [quickstart](#quickstart), there are a variety of simple generic steps which are also available in every format, here are examples of these: ```xml true 4 Greetings to Mars org.codehaus.groovy:groovy-jsr223:3.0.9 groovy Greetings to Mars from sed /usr/bin/sed s/World/Mars/g Say Hello to Mars World Mars Say Hello to Mars from Regex (Hello) W[a-z]{3}d $1 Mars ``` ## License header Spotless can inject a license header into your files, including populating an accurate copyright header from today's date or from git history. ```xml /* (C)$YEAR */ # ``` If the license header (specified with `content` or `file`) contains `$YEAR` or `$today.year`, then that token will be replaced with the current 4-digit year. For example, if Spotless is launched in 2020, then `/* Licensed under Apache-2.0 $YEAR. */` will produce `/* Licensed under Apache-2.0 2020. */` Once a file's license header has a valid year, whether it is a year (`2020`) or a year range (`2017-2020`), it will not be changed. If you want the date to be updated when it changes, enable the [`ratchetFrom` functionality](#ratchet), and the year will be automatically set to today's year according to the following table (assuming the current year is 2020): * No license header -> `2020` * `2017` -> `2017-2020` * `2017-2019` -> `2017-2020` ### Retroactively slurp years from git history If your project has not been rigorous with copyright headers, and you'd like to use git history to repair this retroactively, you can do so with `-DspotlessSetLicenseHeaderYearsFromGitHistory=true`. When run in this mode, Spotless will do an expensive search through git history for each file, and set the copyright header based on the oldest and youngest commits for that file. This is intended to be a one-off sort of thing. ### Files with fixed header lines Some files have fixed header lines (e.g. `^#!.+?$` to skip shebangs). ## Incremental up-to-date checking and formatting **This feature is enabled by default starting from version 2.35.0.** Execution of `spotless:check` and `spotless:apply` for large projects can take time. By default, Spotless Maven plugin needs to read and format each source file. Repeated executions of `spotless:check` or `spotless:apply` are completely independent. If your project has many source files managed by Spotless and formatting takes a long time, you can enable incremental up-to-date checking with the following configuration: ```xml true ${project.basedir}/custom-index-file ``` With up-to-date checking enabled, Spotless creates an index file in the `target` directory. The index file contains source file paths and corresponding last modified timestamps. It allows Spotless to skip already formatted files that have not changed. **Note:** the index file is located in the `target` directory. Executing `mvn clean` will delete the index file, and Spotless will need to check/format all the source files. You can override the default index file location with the `indexFile` configuration parameter. Spotless will remove the index file when up-to-date checking is explicitly turned off with the following configuration: ```xml false ${project.basedir}/custom-index-file ``` Consider using this configuration if you experience issues with up-to-date checking. ## How can I enforce formatting gradually? (aka "ratchet") If your project is not currently enforcing formatting, then it can be a noisy transition. Having a giant commit where every single file gets changed makes the history harder to read. To address this, you can use the `ratchet` feature: ```xml origin/main ``` In this mode, Spotless will apply only to files which have changed since `origin/main`. You can ratchet from [any point you want](https://javadoc.io/doc/org.eclipse.jgit/org.eclipse.jgit/5.6.1.202002131546-r/org/eclipse/jgit/lib/Repository.html#resolve-java.lang.String-), even `HEAD`. You can also set `ratchetFrom` per-format if you prefer (e.g. `...`). However, we strongly recommend that you use a non-local branch, such as a tag or `origin/main`. The problem with `HEAD` or any local branch is that as soon as you commit a file, that is now the canonical formatting, even if it was formatted incorrectly. By instead specifying `origin/main` or a tag, your CI server will fail unless every changed file is at least as good or better than it was before the change. This is especially helpful for injecting accurate copyright dates using the [license step](#license-header). You can explicitly disable ratchet functionality by providing the value 'NONE': ```xml NONE ``` This is useful for disabling the ratchet functionality in child projects where the parent defines a ratchetFrom value. ### Using `ratchetFrom` on CI systems Many popular CI systems (GitHub, GitLab, BitBucket, and Travis) use a "shallow clone". This means that `origin/main` will fail with `No such reference`. You can fix this by: - calling `git fetch origin main` before you call Spotless - disabling the shallow clone [like so](https://github.com/diffplug/spotless/issues/710) ## `spotless:off` and `spotless:on` Sometimes there is a chunk of code which you have carefully handcrafted, and you would like to exclude just this one little part from getting clobbered by the autoformat. Some formatters have a way to do this, many don't, but who cares. If you setup your spotless like this: ```xml ... ``` Then whenever Spotless encounters a pair of `spotless:off` / `spotless:on`, it will exclude that subsection of code from formatting. If you want, you can change the tags to be whatever you want, e.g. `fmt:offfmt:on')`. If you change the default, [read this](https://github.com/diffplug/spotless/pull/691) for some gotchas. ## Line endings and encodings (invisible stuff) Spotless uses UTF-8 by default, but you can use [any encoding which Java supports](https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html). You can set it globally, and you can also set it per-format. ```xml Cp1252 US-ASCII ``` Line endings can also be set globally or per-format using the `lineEndings` property. Spotless supports four line ending modes: `UNIX`, `WINDOWS`, `MAC_CLASSIC`, `PLATFORM_NATIVE`, `GIT_ATTRIBUTES`, and `GIT_ATTRIBUTES_FAST_ALLSAME`. The default value is `GIT_ATTRIBUTES_FAST_ALLSAME`, and *we highly recommend that you* ***do not change*** *this value*. Git has opinions about line endings, and if Spotless and git disagree, then you're going to have a bad time. `FAST_ALLSAME` just means that Spotless can assume that every file being formatted has the same line endings ([more info](https://github.com/diffplug/spotless/pull/1838)). You can easily set the line endings of different files using [a `.gitattributes` file](https://help.github.com/articles/dealing-with-line-endings/). Here's an example `.gitattributes` which sets all files to unix newlines: `* text eol=lf`. ## Disabling warnings and error messages By default, `spotless:check` is bound to the `verify` phase. You might want to disable this behavior. We [recommend against this](https://github.com/diffplug/spotless/issues/79#issuecomment-290844602), but it's easy to do if you'd like: - set `-Dspotless.check.skip=true` at the command line - set `spotless.check.skip` to `true` in the `` section of the `pom.xml` ## How do I preview what `mvn spotless:apply` will do? - Save your working tree with `git add -A`, then `git commit -m "Checkpoint before spotless."` - Run `mvn spotless:apply` - View the changes with `git diff` - If you don't like what spotless did, `git reset --hard` - If you'd like to remove the "checkpoint" commit, `git reset --soft head~1` will make the checkpoint commit "disappear" from history, but keeps the changes in your working directory. ## Can I apply Spotless to specific files? You can target specific files by setting the `spotlessFiles` project property to a comma-separated list of file patterns: ``` cmd> mvn spotless:apply -DspotlessFiles=my/file/pattern.java,more/generic/.*-pattern.java ``` The patterns are matched using `String#matches(String)` against the absolute file path. ## Does Spotless support incremental builds in Eclipse? Spotless comes with [m2e](https://eclipse.dev/m2e/) support. However, by default its execution is skipped in incremental builds as most developers want to fix all issues in one go via explicit `mvn spotless:apply` prior to raising a PR and don't want to be bothered with Spotless issues during working on the source code in the IDE. To enable it use the following parameter ``` true ``` In addition Eclipse problem markers are being emitted for goal `check`. By default they have the severity `WARNING`. You can adjust this with ``` ERROR ``` Note that for Incremental build support the goals have to be bound to a phase prior to `test`. ## Example configurations (from real-world projects) - [Apache Avro](https://github.com/apache/avro/blob/8026c8ffe4ef67ab419dba73910636bf2c1a691c/lang/java/pom.xml#L307-L334) - [JUNG: Java Universal Network/Graph Framework](https://github.com/jrtom/jung/blob/b3a2461b97bb3ab40acc631e21feef74976489e4/pom.xml#L187-L208)