8000
Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

README.md

Spotless: Keep your code spotless with Maven

MavenCentral Changelog Javadoc

Spotless is a general-purpose formatting plugin used by 6,000 projects on GitHub (Jan 2023). 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:

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

Contributions are welcome, see the contributing guide for development info.

Quickstart

To use it in your pom, just add the Spotless plugin, and configure it like so:

<plugin>
  <groupId>com.diffplug.spotless</groupId>
  <artifactId>spotless-maven-plugin</artifactId>
  <version>${spotless.version}</version>
  <configuration>
    <!-- optional: limit format enforcement to just the files changed by this feature branch -->
    <ratchetFrom>origin/main</ratchetFrom>
    <formats>
      <!-- you can define as many formats as you want, each is independent -->
      <format>
        <!-- define the files to apply to -->
        <includes>
          <include>.gitattributes</include>
          <include>.gitignore</include>
        </includes>
        <!-- define the steps to apply to those files -->
        <trimTrailingWhitespace/>
        <endWithNewline/>
        <indent>
          <tabs>true</tabs>
          <spacesPerTab>4</spacesPerTab>
        </indent>
      </format>
    </formats>
    <!-- define a language-specific format -->
    <java>
      <!-- no need to specify files, inferred automatically, but you can if you want -->

      <!-- apply a specific flavor of google-java-format and reflow long strings -->
      <googleJavaFormat>
        <version>1.8</version>
        <style>AOSP</style>
        <reflowLongStrings>true</reflowLongStrings>
        <formatJavadoc>false</formatJavad
D480
oc>
      </googleJavaFormat>

      <!-- make sure every file has the following copyright header.
        optionally, Spotless can set copyright years by digging
        through git history (see "license" section below) -->
      <licenseHeader>
        <content>/* (C)$YEAR */</content>  <!-- or <file>${project.basedir}/license-header</file> -->
      </licenseHeader>
    </java>
  </configuration>
</plugin>

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
  • a list of FormatterStep, which are just String -> String functions, such as replace, replaceRegex, trimTrailingWhitespace, indent, prettier, eclipseWtp, and licenseHeader.
  • order matters, and this is good! (More info here and here)
    • For example, googleJavaFormat always indents with spaces, but some wish it had a tab mode
      • <googleJavaFormat/> // this works
        <indent><tabs>true</tabs><spacesPerTab>2</spacesPerTab></indent>
      • <indent><tabs>true</tabs><spacesPerTab>2</spacesPerTab></indent>
        <googleJavaFormat/> // the tab indentation gets overwritten

Requirements

Spotless requires Maven to be running on JRE 17+.

Git hook

If you want, you can run mvn spotless:install-git-pre-push-hook and it will install a hook such that

  1. When you push, it runs spotless:check
  2. If formatting issues are found:
    • It automatically runs spotless:apply to fix them
    • Aborts the push with a message
    • You can then commit the changes and push again

This ensures your code is always clean before it leaves your machine.

If you prefer instead to have a "pre-commit" hook so that every single commit is clean, see #623 for a workaround or to contribute a permanent fix.

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;

<executions>
  <execution>
    <goals>
      <goal>check</goal>
    </goals>
  </execution>
</executions>

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;

<executions>
  <execution>
    <goals>
      <goal>check</goal>
    </goals>
    <phase>compile</phase>
  </execution>
</executions>

Java

code. available steps.

<configuration>
  <java>
    <!-- These are the defaults, you can override if you want -->
    <includes>
      <include>src/main/java/**/*.java</include>
      <include>src/test/java/**/*.java</include>
    </includes>

    <!-- Cleanthat will refactor your code, but it may break your style: apply it before your formatter -->
    <cleanthat />        <!-- has its own section below -->

    <googleJavaFormat /> <!-- has its own section below -->
    <eclipse />          <!-- has its own section below -->
    <prettier />         <!-- has its own section below -->
    <idea />             <!-- has its own section below -->

    <tableTestFormatter /> <!-- has its own section below -->

    <importOrder /> <!-- standard import order -->
    <importOrder>  <!-- or a custom ordering -->
      <wildcardsLast>false</wildcardsLast> <!-- Optional, default false. Sort wildcard import after specific imports -->
      <order>java|javax,org,com,com.diffplug,,\#com.diffplug,\#</order>  <!-- or use <file>${project.basedir}/eclipse.importorder</file> -->
      <!-- you can use an empty string for all the imports you didn't specify explicitly, '|' to join group without blank line, and '\#` prefix for static imports. -->
      <semanticSort>false</semanticSort> <!-- Optional, default false. Sort by package, then class, then member (for static imports). Splitting is based on common conventions (packages are lower case, classes start with upper case). Use <treatAsPackage> and <treatAsClass> for exceptions. -->
      <treatAsPackage> <!-- Packages starting with upper case letters. -->
        <package>com.example.MyPackage</package>
      </treatAsPackage>
      <treatAsClass> <!-- Classes starting with lower case letters. -->
        <class>com.example.myClass</class>
      </treatAsClass>
    </importOrder>

    <removeUnusedImports /> <!-- self-explanatory -->
    <forbidWildcardImports /> <!-- yell if any import ends with '*' -->
    <forbidModuleImports /> <!-- yell if any module imports are found (Java 25+) -->

    <formatAnnotations />  <!-- fixes formatting of type annotations, see below -->

    <licenseHeader>
      <content>/* (C)$YEAR */</content>  <!-- or <file>${project.basedir}/license-header</file> -->
    </licenseHeader>
  </java>
</configuration>

removeUnusedImports

<removeUnusedImports>
  <engine>google-java-format</engine>    <!-- optional. Defaults to `google-java-format`. Can be switched to `cleanthat-javaparser-unnecessaryimport` (e.g. to process JDK17 source files with a JDK8+ Runtime) -->
</removeUnusedImports>

forbidWildcardImports

<forbidWildcardImports/>

forbidModuleImports

<forbidModuleImports/>

google-java-format

homepage. changelog. code.

<googleJavaFormat>
  <version>1.8</version>                      <!-- optional, 1.8 is the minimum supported version for Java 11 -->
  <style>GOOGLE</style>                       <!-- or AOSP (optional) -->
  <reflowLongStrings>true</reflowLongStrings> <!-- optional -->
  <formatJavadoc>false</formatJavadoc>        <!-- optional -->
  <!-- optional: custom group artifact (you probably don't need this) -->
  <groupArtifact>com.google.googlejavaformat:google-java-format</groupArtifact>
</googleJavaFormat>

palantir-java-format

homepage. changelog. code.

<palantirJavaFormat>
  <version>2.39.0</version>                     <!-- optional -->
  <style>PALANTIR</style>                       <!-- or AOSP/GOOGLE (optional) -->
  <formatJavadoc>false</formatJavadoc>          <!-- defaults to false (optional, requires at least Palantir 2.39.0) -->
</palantirJavaFormat>

eclipse jdt

homepage. code. See here for screenshots that demonstrate how to get and install the config file mentioned below.

<eclipse>
  <!-- Optional: Specify the Eclipse JDT version to use. -->
  <version>4.26</version>
  <!-- Optional: Specify a file which contains all formatting options. -->
  <file>${project.basedir}/eclipse-formatter.xml</file>
  <!-- If the access to the p2 repositories is restricted, mirrors can be pecified using a URI prefix map as follows:-->
  <p2Mirrors>
    <p2Mirror>
      <prefix>https://download.eclipse.org/eclipse/updates/4.26/</prefix>
      <url>https://some.internal.mirror/4-26-updates-p2/</url>
    </p2Mirror>
  </p2Mirrors>
</eclipse>

Sort Members

Not only can you format your code with Eclipse JDT, but you can also sort the members as you know it from Eclipse IDE. This ensures that the methods are always in sorted order (and thus reduces the likelihood of collisions in a version control system). It is turned off by default, but you might want to consider enabling it when setting coding standards for a project.

The format to specify the sort order follows the outlinesortoption and org.eclipse.jdt.ui.visibility.order properties that can be found in the workspace folder of your Eclipse IDE. You can look at the file .plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs in your workspace directory.

<eclipse>
  <!-- Optional: Enable the Sort Members feature globally. (default: false) -->
  <sortMembersEnabled>true</sortMembersEnabled>
  <!-- Optional: Specify the sort order of the member categories. (default: T,SF,SI,SM,F,I,C,M)
       SF,SI,SM,F,I,C,M,T = Static Fields, Static Initializers, Static Methods, Fields, Initializers, Constructors, Methods, (Nested) Types -->
  <sortMembersOrder>SF,SI,SM,F,I,C,M,T</sortMembersOrder>
  <!-- Optional: Enable the reordering of fields, enum constants, and initializers. (default: true) -->
  <sortMembersDoNotSortFields>false</sortMembersDoNotSortFields>
  <!-- Optional: Enable reordering of members of the same category by the visibility within the category. (default: false) -->
  <sortMembersVisibilityOrderEnabled>true</sortMembersVisibilityOrderEnabled>
  <!-- Optional: Specify the ordering of members of the same category by the visibility within the category. (default: B,V,R,D)
       B,R,D,V = Public, Protected, Package, Private -->
  <sortMembersVisibilityOrder>B,R,D,V</sortMembersVisibilityOrder>
</eclipse>

You can enable/disable the globally defined sort properties on file level by adding the following comments:

  • // @SortMembers:enabled=false - disable the Sort Members feature for this file
  • // @SortMembers:doNotSortFields=true - disable the sorting of static and instance fields
  • // @SortMembers:sortByVisibility=false - don't sort members by its visibility modifier

formatAnnotations

Type annotations should be on the same line as the type that they qualify.

  @Override
  @Deprecated
  @Nullable @Interned String s;

However, some tools format them incorrectly, like this:

  @Override
  @Deprecated
  @Nullable
  @Interned
  String s;

To fix the incorrect formatting, add the formatAnnotations rule after a Java formatter. For example:

<googleJavaFormat />
<formatAnnotations />

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. CleanThat enables automatic refactoring of Java code. ChangeLog

<cleanthat>
  <version>2.8</version>                          <!-- optional version of Cleanthat -->
  <sourceJdk>${maven.compiler.source}</sourceJdk> <!-- optional. Default to ${maven.compiler.source} else '1.7' -->
  <mutators>
    <mutator>SafeAndConsensual</mutator>          <!-- optional. Default to 'SafeAndConsensual' to include all mutators -->
  </mutators>
  <mutators>            <!-- List of mutators: https://github.com/solven-eu/cleanthat/blob/master/MUTATORS.generated.MD -->
    <mutator>LiteralsFirstInComparisons</mutator> <!-- You may alternatively list the requested mutators -->
  </mutators>
  <excludedMutators>
    <excludedMutator>OptionalNotEmpty</excludedMutator> <!-- You can discard specific rules -->
  </excludedMutators>
  <includeDraft>false</includeDraft>              <!-- optional. Default to false, not to include draft mutators from Composite mutators -->
</cleanthat>

tabletest-formatter

homepage. changelog. code. Formats @TableTest tables in Java source files. All configuration is read from .editorconfig files.

<tableTestFormatter>
  <version>1.1.1</version> <!-- optional -->
</tableTestFormatter>

Groovy

code. available steps.

<configuration>
  <groovy>
    <!-- These are the defaults, you can override if you want -->
    <includes>
      <include>src/main/groovy/**/*.groovy</include>
      <include>src/test/groovy/**/*.groovy</include>
    </includes>

    <importOrder/> <!-- standard import order -->
    <importOrder>  <!-- or a custom ordering -->
      <order>java|javax,org,com,com.diffplug,,\#com.diffplug,\#</order>  <!-- or use <file>${project.basedir}/eclipse.importorder</file> -->
      <!-- you can use an empty string for all the imports you didn't specify explicitly, '|' to join group without blank line, and '\#` prefix for static imports. -->
    </importOrder>
    
    <removeSemicolons/> <!-- removes semicolons at the end of lines -->
    <greclipse/>          <!-- has its own section below -->

    <excludeJava/>
    <licenseHeader>
      <content>/* (C)$YEAR */</content>  <!-- or <file>${project.basedir}/license-header</file> -->
    </licenseHeader>
  </groovy>
</configuration>

eclipse groovy

homepage. changelog. compatible versions. The Groovy formatter uses some of the 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 in the previous example. The formatter step can also load the exported Eclipse properties 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.

<greclipse>
  <version>4.26</version>  <!-- optional version of Eclipse Formatter -->
  <file>${project.basedir}/greclipse.properties</file> <!-- optional -->
</greclipse>

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. available steps.

<configuration>
  <kotlin>
    <!-- These are the defaults, you can override if you want -->
    <includes>
      <include>src/main/kotlin/**/*.kt</include>
      <include>src/test/kotlin/**/*.kt</include>
    </includes>

    <ktfmt />    <!-- has its own section below -->
    <ktlint />   <!-- has its own section below -->
    <diktat />   <!-- has its own section below -->
    <prettier /> <!-- has its own section below -->

    <tableTestFormatter /> <!-- has its own section below -->

    <licenseHeader>
      <content>/* (C)$YEAR */</content>  <!-- or <file>${project.basedir}/license-header</file> -->
    </licenseHeader>
  </kotlin>
</configuration>

ktfmt

homepage. changelog. code.

<ktfmt>
  <version>0.51</version> <!-- optional -->
  <style>KOTLINLANG</style> <!-- optional, options are META (default), GOOGLE and KOTLINLANG -->
  <maxWidth>120</maxWidth> <!-- optional -->
  <blockIndent>4</blockIndent> <!-- optional -->
  <continuationIndent>8</continuationIndent> <!-- optional -->
  <removeUnusedImports>false</removeUnusedImports> <!-- optional -->
  <trailingCommaManagementStrategy>COMPLETE</trailingCommaManagementStrategy> <!-- optional -->
</ktfmt>

ktlint

homepage. changelog. code.

Spotless respects the .editorconfig settings by providing editorConfigPath option. (ktlint docs).

Additionally, editorConfigOverride options will override what's supplied in .editorconfig file.

<ktlint>
  <version>1.0.0</version> <!-- optional -->
  <editorConfigOverride> <!-- optional -->
    <ij_kotlin_allow_trailing_comma>true</ij_kotlin_allow_trailing_comma>
    <ij_kotlin_allow_trailing_comma_on_call_site>true</ij_kotlin_allow_trailing_comma_on_call_site>
    <!-- intellij_idea is the default style we preset in Spotless, you can override it referring to https://pinterest.github.io/ktlint/latest/rules/code-styles. -->
    <ktlint_code_style>intellij_idea</ktlint_code_style>
  </editorConfigOverride>
  <customRuleSets> <!-- optional -->
    <value>io.nlopez.compose.rules:ktlint:0.4.25</value>
  </customRuleSets>
</ktlint>

diktat

homepage. changelog. code. You can provide configuration path manually as configFile.

<diktat>
  <version>1.0.1</version> <!-- optional -->
  <configFile>full/path/to/diktat-analysis.yml</configFile> <!-- optional, configuration file path -->
</diktat>

tabletest-formatter

homepage. changelog. code. Formats @TableTest tables in Kotlin source files. All configuration is read from .editorconfig files.

<tableTestFormatter>
  <version>1.1.1</version> <!-- optional -->
</tableTestFormatter>

Scala

code. available steps.

<configuration>
  <scala>
    <!-- These are the defaults, you can override if you want -->
    <includes>
      <include>src/main/scala/**/*.scala</include>
      <include>src/test/scala/**/*.scala</include>
      <include>src/main/scala/**/*.sc</include>
      <include>src/test/scala/**/*.sc</include>
    </includes>

    <scalafmt /> <!-- has its own section below -->

    <licenseHeader>
      <content>/* (C)$YEAR */</content>  <!-- or <file>${project.basedir}/license-header</file> -->
      <delimiter>package </delimiter> <!--
        note the 'package ' argument - this is a regex which identifies the top
        of the file, be careful that all of your sources have a package declaration,
        or pick a regex which works better for your code -->
    </licenseHeader>
  </scala>
</configuration>

scalafmt

homepage. changelog. config docs. code.

<scalafmt>
  <version>3.5.9</version>              <!-- optional -->
  <file>${project.basedir}/scalafmt.conf</file> <!-- optional -->
  <scalaMajorVersion>2.13</scalaMajorVersion> <!-- optional -->
</scalafmt>

C/C++

code. available steps.

<configuration>
  <cpp>
    <includes> <!-- You have to set the target manually -->
      <include>src/native/**</include>
    </includes>

    <eclipseCdt /> <!-- has its own section below -->

    <licenseHeader>
      <content>/* (C)$YEAR */</content>  <!-- or <file>${project.basedir}/license-header</file> -->
    </licenseHeader>
  </cpp>
</configuration>

eclipse cdt

homepage. compatible versions. code.

<eclipseCdt>
  <version>11.0</version> <!-- optional version of Eclipse Formatter, others at https://download.eclipse.org/tools/cdt/releases/ -->
  <file>${project.basedir}/eclipse-cdt.xml</file> <!-- optional -->
</eclipseCdt>

clang-format

homepage. changelog. clang-format is a formatter for c, c++, c#, objective-c, protobuf, javascript, and java. You can use clang-format in any language-specific format, but usually you will be creating a generic format.

<clangFormat>
  <version>14.0.0-1ubuntu1.1</version> <!-- optional version of clang-format. Explicitly allow "any found version" with '*'. -->
  <pathToExe>/path/to/buf</pathToExe>  <!-- optional: if clang-format isn't in your path -->
  <style>LLVM</style>  <!-- optional: can be LLVM, Google, Chromium, Mozilla, WebKit -->
</clangFormat>

Python

code. available steps.

<configuration>
  <python>
    <!-- You have to set the target manually -->
    <includes>
      <include>src/main/**/*.py</include>
    </includes>

    <black />  <!-- has its own section below -->
  </python>
</configuration>

black

homepage. changelog.

<black>
  <version>19.10b0</version> <!-- optional. Explicitly allow "any found version" with '*'. -->
  <!-- if black is not on your path, you must specify its location manually -->
  <pathToExe>C:/myuser/.pyenv/versions/3.8.0/scripts/black.exe</pathToExe>
  <!--
    Spotless always checks the version of the black it is using
    and will fail with an error if it does not match the expected version
    (whether manually specified or default). If there is a problem, Spotless
    will suggest commands to help install the correct version.
    TODO: handle installation & packaging automatically - https://github.com/diffplug/spotless/issues/674
  -->
</black>

Antlr4

code. available steps.

<configuration>
  <antlr4>
    <!-- These are the defaults, you can override if you want -->
    <includes>
      <include>src/*/antlr4/**/*.g4</include>
    </includes>

    <antlr4Formatter /> <!-- has its own section below -->

    <licenseHeader>
      <content>/* (C)$YEAR */</content>  <!-- or <file>${project.basedir}/license-header</file> -->
    </licenseHeader>
  </antlr4>
</configuration>

antlr4Formatter

homepage. available versions. code.

<antlr4Formatter>
  <version>1.2.1</version> <!-- optional -->
</antlr4Formatter>

SQL

code. available steps.

<configuration>
  <sql>
    <!-- You have to set the target manually -->
    <includes>
      <include>src/main/resources/**/*.sql</include>
    </includes>

    <dbeaver />  <!-- has its own section below -->
    <prettier /> <!-- has its own section below -->
    <idea />     <!-- has its own section below -->
  </sql>
</configuration>

dbeaver

homepage. 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.

<dbeaver>
    <configFile>dbeaver.properties</configFile> <!-- configFile is optional -->
</dbeaver>

Default configuration file, other options available here.

# 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. available steps.

<configuration>
  <pom>
    <!-- These are the defaults, you can override if you want -->
    <includes>
      <include>pom.xml</include>
    </includes>

    <sortPom /> <!-- has its own section below -->

  </pom>
</configuration>

sortPom

homepage. code.

All configuration settings are optional, they are described in detail here.

<sortPom>

  <encoding>UTF-8</encoding> <!-- The encoding of the pom files -->

  <lineSeparator>${line.separator}</lineSeparator> <!-- line separator to use -->

  <expandEmptyElements>true</expandEmptyElements> <!-- Should empty elements be expanded -->

  <spaceBeforeCloseEmptyElement>false</spaceBeforeCloseEmptyElement> <!-- Should a space be added inside self-closing elements -->

  <keepBlankLines>true</keepBlankLines> <!-- Keep empty lines -->

  <endWithNewline>true</endWithNewline> <!-- Whether sorted pom ends with a newline -->

  <nrOfIndentSpace>2</nrOfIndentSpace> <!-- Indentation -->

  <indentBlankLines>false</indentBlankLines> <!-- Should empty lines be indented -->

  <indentSchemaLocation>false</indentSchemaLocation> <!-- Should schema locations be indented -->

  <indentAttribute></indentAttribute> <!-- Should the xml attributes be indented -->

  <predefinedSortOrder>recommended_2008_06</predefinedSortOrder> <!-- Sort order of elements: https://github.com/Ekryd/sortpom/wiki/PredefinedSortOrderProfiles -->

  <sortOrderFile></sortOrderFile> <!-- Custom sort order of elements: https://raw.githubusercontent.com/Ekryd/sortpom/master/sorter/src/main/resources/custom_1.xml -->

  <sortDependencies></sortDependencies> <!-- Sort dependencies: https://github.com/Ekryd/sortpom/wiki/SortDependencies -->

  <sortDependencyManagement></sortDependencyManagement> <!-- Sort dependency management: https://github.com/Ekryd/sortpom/wiki/SortDependencies -->

  <sortDependencyExclusions></sortDependencyExclusions> <!-- Sort dependency exclusions: https://github.com/Ekryd/sortpom/wiki/SortDependencies -->

  <sortPlugins></sortPlugins> <!-- Sort plugins: https://github.com/Ekryd/sortpom/wiki/SortPlugins -->

  <sortProperties>false</sortProperties> <!-- Sort properties -->

  <sortModules>false</sortModules> <!-- Sort modules -->

  <sortExecutions>false</sortExecutions> <!-- Sort plugin executions -->
</sortPom>

Markdown

code. available steps.

<configuration>
  <markdown>
    <includes> <!-- You have to set the target manually -->
      <include>**/*.md</include>
    </includes>

    <flexmark/> <!-- has its own section below -->
  </markdown>
</configuration>

Flexmark

homepage. code. Flexmark is a flexible Commonmark/Markdown parser that can be used to format Markdown files. It supports different flavors of Markdown and many formatting options.

The default configuration uses a pegdown compatible parser with COMMONMARK as FORMATTER_EMULATION_PROFILE. You can change the emulationProfile to one of the other supported profiles. The pegdownExtensions can be configured as a comma-seperated list of constants or as a custom bitset as an integer. Any other extension can be configured using either the simple name as shown in the example or using a full-qualified class name.

<flexmark>
  <emulationProfile>COMMONMARK</emulationProfile>
  <pegdownExtensions>ALL,TOC</pegdownExtensions>
  <extensions>YamlFrontMatter,Emoji</extensions>
</flexmark>

Typescript

code. available steps.

<configuration>
  <typescript>
    <includes> <!-- You have to set the target manually -->
      <include>src/**/*.ts</include>
    </includes>

    <tsfmt/>    <!-- has its own section below -->
    <prettier/> <!-- has its own section below -->
    <eslint/>   <!-- has its own section below -->
    <biome/>    <!-- has its own section below -->

    <licenseHeader>
      <content>/* (C)$YEAR */</content>  <!-- or <file>${project.basedir}/license-header</file> -->
      <delimiter>(import|const|declare|export|var) </delimiter> <!--
        note the '(import|const|...' argument - this is a regex which identifies the top
        of the file, be careful that all of your sources have a suitable top-level declaration,
        or pick a regex which works better for your code -->
    </licenseHeader>
  </typescript>
</configuration>

tsfmt

npm. changelog. code. 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 for what is available.

<tsfmt>
  <typescriptFormatterVersion>7.2.2</typescriptFormatterVersion> <!-- optional https://www.npmjs.com/package/typescript-formatter -->
  <typescriptVersion>3.9.5</typescriptVersion> <!-- optional https://www.npmjs.com/package/typescript -->
  <tslintVersion>6.1.2</tslintVersion> <!-- optional https://www.npmjs.com/package/tslint -->

  <config> <!-- https://github.com/vvakame/typescript-formatter/blob/7764258ad42ac65071399840d1b8701868510ca7/lib/utils.ts#L11L32 -->
    <indentSize>1</indentSize>
    <convertTabsToSpaces>true</convertTabsToSpaces>
  </config>
  <!-- // or according to tsfmt-parameters: https://github.com/vvakame/typescript-formatter/blob/7764258ad42ac65071399840d1b8701868510ca7/lib/index.ts#L27L34 -->
  <tsconfigFile>${project.basedir}/tsconfig.json</tsconfigFile>
  <tslintFile>${project.basedir}/tslint.json</tslintFile>
  <vscodeFile>${project.basedir}/vscode.json</vscodeFile>
  <tsfmtFile>${project.basedir}/tsfmt.json</tsfmtFile>
</tsfmt>

Prerequisite: tsfmt requires a working NodeJS version

For details, see the npm detection, .npmrc detection and caching results of npm install sections of prettier, which apply also to tsfmt.

ESLint (typescript)

npm. changelog. 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) configuration. In typescript, a reference to a tsconfig.json is required.

<eslint>
  <!-- Specify at most one of the following 3 configs: either 'eslintVersion', 'devDependencies' or 'devDependencyProperties'  -->
  <eslintVersion>8.30.0</eslintVersion>
  <devDependencies>
    <myEslintFork>8.30.0</myEslintFork>
    <myEslintPlugin>1.2.1</myEslintPlugin>
  </devDependencies>
  <devDependencyProperties>
    <property>
      <name>eslint</name>
      <value>8.30.0</value>
    </property>
    <property>
      <name>@eslint/my-plugin-typescript</name> <!-- this could not be written in the simpler to write 'devDependencies' element. -->
      <value>0.14.2</value>
    </property>
  </devDependencyProperties>
  <!-- mandatory: provide either a configFile or a configJs object -->
  <configFile>${project.basedir}/.eslintrc.js</configFile>
  <configJs>
    {
      env: {
        browser: true,
        es2021: true
      },
      extends: 'standard-with-typescript',
      overrides: [
      ],
      parserOptions: {
        ecmaVersion: 'latest',
        sourceType: 'module',
        project: './tsconfig.json',
      },
      rules: {
      }
    }
  </configJs>
  <!-- recommended: provide a tsconfigFile - especially when using the styleguides -->
  <tsconfigFile>${project.basedir}/tsconfig.json</tsconfigFile>
</eslint>

Prerequisite: ESLint requires a working NodeJS version

For details, see the npm detection, .npmrc detection and caching results of npm install sections of prettier, which apply also to ESLint.

Javascript

code. available steps.

<configuration>
  <typescript>
    <includes> <!-- You have to set the target manually -->
      <include>src/**/*.js</include>
    </includes>

    <prettier/> <!-- has its own section below -->
    <eslint/>   <!-- has its own section below -->
    <biome/>    <!-- has its own section below -->

    <licenseHeader>
      <content>/* (C)$YEAR */</content>  <!-- or <file>${project.basedir}/license-header</file> -->
      <delimiter>REGEX_TO_DEFINE_TOP_OF_FILE</delimiter> <!-- set a regex to define the top of the file -->
    </licenseHeader>
  </typescript>
</configuration>

ESLint (Javascript)

npm. changelog. 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) configuration. In javascript, no tsconfig.json is supported.

<eslint>
  <!-- Specify at most one of the following 3 configs: either 'eslintVersion', 'devDependencies' or 'devDependencyProperties'  -->
  <eslintVersion>8.30.0</eslintVersion>
  <devDependencies>
    <myEslintFork>8.30.0</myEslintFork>
    <myEslintPlugin>1.2.1</myEslintPlugin>
  </devDependencies>
  <devDependencyProperties>
    <property>
      <name>eslint</name>
      <value>8.30.0</value>
    </property>
    <property>
      <name>@eslint/my-plugin-javascript</name> <!-- this could not be written in the simpler to write 'devDependencies' element. -->
      <value>0.14.2</value>
    </property>
  </devDependencyProperties>
  <!-- mandatory: provide either a configFile or a configJs object -->
  <configFile>${project.basedir}/.eslintrc.js</configFile>
  <configJs>
    {
      env: {
        browser: true,
        es2021: true
      },
      extends: 'standard',
      overrides: [
      ],
      parserOptions: {
        ecmaVersion: 'latest',
        sourceType: 'module'
      },
      rules: {
      }
    }
  </configJs>
</eslint>

Prerequisite: ESLint requires a working NodeJS version

For details, see the npm detection, .npmrc detection and caching results of npm install sections of prettier, which apply also to ESLint.

JSON

  • com.diffplug.spotless.maven.json.Json code
<configuration>
  <json>
    <includes>    <!-- You have to set the target manually -->
      <include>src/**/*.json</include>
    </includes>

    <simple />         <!-- has its own section below -->
    <gson />           <!-- has its own section below -->
    <jackson />        <!-- has its own section below -->
    <biome />          <!-- has its own section below -->
    <jsonPatch />      <!-- has its own section below -->
  </json>
</configuration>

simple

Uses a JSON pretty-printer that optionally allows configuring the number of spaces that are used to pretty print objects:

<simple>
  <indentSpaces>4</indentSpaces>    <!-- optional: specify the number of spaces to use -->
</simple>

Gson

Uses Google Gson to also allow sorting by keys besides custom indentation - useful for i18n files.

<gson>
  <indentSpaces>4</indentSpaces>        <!-- optional: specify the number of spaces to use -->
  <sortByKeys>false</sortByKeys>        <!-- optional: sort JSON by its keys -->
  <escapeHtml>false</escapeHtml>      <!-- optional: escape HTML in values -->
  <version>2.8.1</version>              <!-- optional: specify version -->
</gson>

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 for details.

Jackson

Uses Jackson for formatting.

<jackson>
  <version>2.14.1</version>    <!-- optional: The version of 'com.fasterxml.jackson.core:jackson-databind' to be used -->
  <features>                   <!-- optional: Customize the set of features (based on com.fasterxml.jackson.databind.SerializationFeature) -->
    <INDENT_OUTPUT>true</INDENT_OUTPUT>                            <!-- optional: true by default -->
    <ORDER_MAP_ENTRIES_BY_KEYS>false</ORDER_MAP_ENTRIES_BY_KEYS>   <!-- optional: false by default -->
    <ANY_OTHER_FEATURE>true|false</ANY_OTHER_FEATURE>              <!-- any SerializationFeature can be toggled on or off -->
  </features>
  <jsonFeatures>
    <QUOTE_FIELD_NAMES>false</QUOTE_FIELD_NAMES>                   <!-- false by default -->
    <ANY_OTHER_FEATURE>true|false</ANY_OTHER_FEATURE>              <!-- any JsonGenerator.Feature can be toggled on or off -->
  </jsonFeatures>
  <spaceBeforeSeparator>false</spaceBeforeSeparator>               <!-- optional: false by default -->
</jackson>

jsonPatch

Uses zjsonpatch to apply JSON Patches as per RFC 6902 to JSON documents.

This enables you to add, replace or remove properties at locations in the JSON document that you specify using JSON Pointers.

For example, to apply the patch from the JSON Patch homepage:

<jsonPatch>[
  { "op": "replace", "path": "/baz", "value": "boo" },
  { "op": "add", "path": "/hello", "value": ["world"] },
  { "op": "remove", "path": "/foo" }
]</jsonPatch>

YAML

  • com.diffplug.spotless.maven.FormatterFactory.addStepFactory(FormatterStepFactory) code
<configuration>
  <yaml>
    <includes>     <!-- You have to set the target manually -->
      <include>src/**/*.yaml</include>
    </includes>

    <jackson />    <!-- has its own section below -->
    <prettier />   <!-- has its own section below -->
  </yaml>
</configuration>

jackson

Uses Jackson and YAMLFactory to pretty print objects:

<jackson>
  <version>2.14.1</version>    <!-- optional: The version of 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml' to be used -->
  <features>                   <!-- optional: Customize the set of features (based on com.fasterxml.jackson.databind.SerializationFeature) -->
    <INDENT_OUTPUT>true</INDENT_OUTPUT>                            <!-- true by default -->
    <ORDER_MAP_ENTRIES_BY_KEYS>false</ORDER_MAP_ENTRIES_BY_KEYS>   <!-- false by default -->
    <ANY_OTHER_FEATURE>true|false</ANY_OTHER_FEATURE>              <!-- any SerializationFeature can be toggled on or off -->
  </features>
  <yamlFeatures>
    <WRITE_DOC_START_MARKER>true</WRITE_DOC_START_MARKER>          <!-- false by default -->
    <MINIMIZE_QUOTES>false</MINIMIZE_QUOTES>                       <!-- false by default -->
    <ANY_OTHER_FEATURE>true|false</ANY_OTHER_FEATURE>              <!-- any YAMLGenerator.Feature can be toggled on or off -->
  </yamlFeatures>
  <spaceBeforeSeparator>false</spaceBeforeSeparator>   <!-- optional: false by default -->
</jackson>

Shell

  • com.diffplug.spotless.maven.FormatterFactory.addStepFactory(FormatterStepFactory) code
<configuration>
  <shell>
    <includes>     <!-- Not required. Defaults to **/*.sh -->
      <include>scripts/**/*.sh</include>
    </includes>
    
    <shfmt />    <!-- has its own section below -->
  </shell>
</configuration>

shfmt

homepage. changelog.

When formatting shell scripts via shfmt, configure shfmt settings via .editorconfig.

<shfmt>
  <version>3.8.0</version>                         <!-- optional: Custom version of 'mvdan/sh'. Explicitly allow "any found version" with '*'. -->
  <pathToExe>/opt/homebrew/bin/shfmt</pathToExe>   <!-- optional: if shfmt is not on your path, you must specify its location manually -->
</shfmt>

TableTest

code. available steps.

<configuration>
  <tableTest>
    <includes>
      <include>src/**/*.table</include>
    </includes>
    <tableTestFormatter>
      <version>1.1.1</version> <!-- optional -->
    </tableTestFormatter>
  </tableTest>
</configuration>

homepage. changelog. Formats standalone TableTest .table files.

Gherkin

  • com.diffplug.spotless.maven.FormatterFactory.addStepFactory(FormatterStepFactory) code
<configuration>
  <gherkin>
    <includes>     <!-- You have to set the target manually -->
      <include>src/**/*.feature</include>
    </includes>

    <gherkinUtils />    <!-- has its own section below -->
  </gherkin>
</configuration>

gherkinUtils

homepage. changelog.

Uses a Gherkin pretty-printer that optionally allows configuring the number of spaces that are used to pretty print objects:

<gherkinUtils>
  <version>9.0.0</version>                 <!-- optional: Custom version of 'io.cucumber:gherkin-utils' -->
</gherkinUtils>

Go

  • com.diffplug.spotless.maven.FormatterFactory.addStepFactory(FormatterStepFactory) code
<configuration>
  <go>
    <includes>     <!-- You have to set the target manually -->
      <include>src/**/*.go</include>
    </includes>

    <gofmt />    <!-- has its own section below -->
  </go>
</configuration>

gofmt

Standard Go formatter, part of Go distribution.

<gofmt>
  <version>go1.25.1</version>                 <!-- Explicitly allow "any found version" with '*'. -->
  <goExecutablePath>/opt/sdks/go1.25.1/bin/go</goExecutablePath>
</gofmt>

RDF

Generic Options

List of generic configuration parameters (type/default)

  • failOnWarning (boolean/true): The Jena parser produces three levels of problem reports: warning, error, and fatal. By default, the build fails for any of them. You can ignore warnings using this parameter. They will still be logged in the plugin's output.
  • verify (boolean/true): If true, the content before and after formatting is parsed to an RDF model and compared for isomorphicity.
  • turtleFormatterVersion (string|RdfFormatterStep.LATEST_TURTLE_FORMATTER_VERSION): the version of turtle-formatter to use (see below).

Supported RDF formats: only TTL (at the moment)

Formatting TTL is done using turtle-formatter, which is highly configurable (have a look at the Style Documentation) and will handle blank nodes the way you'd hope.

The style options can be configured via spotless. Wherever the style wants a URI (for example, for the predicateOrder, you can use the abbreviated form if it is a FormattingStyle.KnownPrefix (currently rdf, rdfs, xsd, owl, dcterms) Error messages will give you hints. To configure the TTL formatting style, pass the configuration parameters under <turtle>

Examples

Minimal:

<configuration>
  <rdf>
    <includes>
      <include>**/*.ttl</include>
    </includes>
    <format/>
  </rdf>
</configuration>

Configuring some generic and TTL options:

<configuration>
  <rdf>
    <includes>
      <include>**/*.ttl</include>
    </includes>
    <format>
      <failOnWarning>false</failOnWarning>
      <verify>false</verify>
      <turtleFormatterVersion>1.2.13</turtleFormatterVersion>
      <turtle>
        <alignPrefixes>RIGHT</alignPrefixes>
        <enableDoubleFormatting>true</enableDoubleFormatting>
      </turtle>
    </format>
  </rdf>
</configuration>

Libraries and versions

RDF parsing is done via Apache Jena in the version that turtle-formatter depends on (not necessarily the latest).

Protobuf