From a78844fdcdea3d98dff550b2cdde4c4c11cc3d6f Mon Sep 17 00:00:00 2001 From: Daniel Heid Date: Thu, 4 Jun 2026 20:24:37 +0200 Subject: [PATCH 1/4] Integrate adocfmt for AsciiDoc formatting --- CHANGES.md | 2 + .../spotless/asciidoc/AdocfmtConfig.java | 65 +++++ .../spotless/asciidoc/AdocfmtStep.java | 117 ++++++++ plugin-gradle/CHANGES.md | 2 + plugin-gradle/README.md | 35 +++ .../gradle/spotless/AsciidocExtension.java | 124 +++++++++ .../gradle/spotless/SpotlessExtension.java | 9 +- .../spotless/AsciidocExtensionTest.java | 54 ++++ plugin-maven/CHANGES.md | 3 + plugin-maven/README.md | 43 +++ .../spotless/maven/AbstractSpotlessMojo.java | 6 +- .../spotless/maven/asciidoc/Adocfmt.java | 91 ++++++ .../spotless/maven/asciidoc/Asciidoc.java | 38 +++ .../maven/MavenIntegrationHarness.java | 4 + .../maven/asciidoc/AdocfmtMavenTest.java | 47 ++++ .../asciidoc/adocfmt/clean_all_options.adoc | 255 +++++++++++++++++ .../asciidoc/adocfmt/clean_complex.adoc | 258 ++++++++++++++++++ .../asciidoc/adocfmt/clean_custom.adoc | 255 +++++++++++++++++ .../asciidoc/adocfmt/clean_minimal.adoc | 258 ++++++++++++++++++ .../resources/asciidoc/adocfmt/dirty.adoc | 256 +++++++++++++++++ .../spotless/asciidoc/AdocfmtStepTest.java | 82 ++++++ 21 files changed, 2002 insertions(+), 2 deletions(-) create mode 100644 lib/src/main/java/com/diffplug/spotless/asciidoc/AdocfmtConfig.java create mode 100644 lib/src/main/java/com/diffplug/spotless/asciidoc/AdocfmtStep.java create mode 100644 plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AsciidocExtension.java create mode 100644 plugin-gradle/src/test/java/com/diffplug/gradle/spotless/AsciidocExtensionTest.java create mode 100644 plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Adocfmt.java create mode 100644 plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Asciidoc.java create mode 100644 plugin-maven/src/test/java/com/diffplug/spotless/maven/asciidoc/AdocfmtMavenTest.java create mode 100644 testlib/src/main/resources/asciidoc/adocfmt/clean_all_options.adoc create mode 100644 testlib/src/main/resources/asciidoc/adocfmt/clean_complex.adoc create mode 100644 testlib/src/main/resources/asciidoc/adocfmt/clean_custom.adoc create mode 100644 testlib/src/main/resources/asciidoc/adocfmt/clean_minimal.adoc create mode 100644 testlib/src/main/resources/asciidoc/adocfmt/dirty.adoc create mode 100644 testlib/src/test/java/com/diffplug/spotless/asciidoc/AdocfmtStepTest.java diff --git a/CHANGES.md b/CHANGES.md index a686e880dc..8ebdac1e2b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,8 @@ This document is intended for Spotless developers. We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`). ## [Unreleased] +### Added +- Add support for AsciiDoc formatting via `adocfmt`. (#TODO-PR-LINK) ### Fixed - Support `ktfmt` 0.63 and use its new builder API for formatting options to better avoid future breaking changes. ### Changes diff --git a/lib/src/main/java/com/diffplug/spotless/asciidoc/AdocfmtConfig.java b/lib/src/main/java/com/diffplug/spotless/asciidoc/AdocfmtConfig.java new file mode 100644 index 0000000000..c5b1d2cb64 --- /dev/null +++ b/lib/src/main/java/com/diffplug/spotless/asciidoc/AdocfmtConfig.java @@ -0,0 +1,65 @@ +/* + * Copyright 2026 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.spotless.asciidoc; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Objects; + +public class AdocfmtConfig implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + + public boolean normalizeSetextHeadings = false; + public boolean collapseConsecutiveBlankLines = true; + public boolean oneSentencePerLine = false; + public boolean normalizeBlockDelimiters = true; + public boolean removeTrailingHeaderEqualsSign = true; + public boolean titleCase = false; + public boolean removeTrailingWhitespace = true; + public boolean normalizeListBullets = false; + public boolean normalizeOrderedListMarkers = false; + public boolean ensureHeadingBlankLines = true; + public boolean ensureSourceDelimiters = false; + + public AdocfmtConfig() {} + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof AdocfmtConfig other)) + return false; + return normalizeSetextHeadings == other.normalizeSetextHeadings + && collapseConsecutiveBlankLines == other.collapseConsecutiveBlankLines + && oneSentencePerLine == other.oneSentencePerLine + && normalizeBlockDelimiters == other.normalizeBlockDelimiters + && removeTrailingHeaderEqualsSign == other.removeTrailingHeaderEqualsSign + && titleCase == other.titleCase + && removeTrailingWhitespace == other.removeTrailingWhitespace + && normalizeListBullets == other.normalizeListBullets + && normalizeOrderedListMarkers == other.normalizeOrderedListMarkers + && ensureHeadingBlankLines == other.ensureHeadingBlankLines + && ensureSourceDelimiters == other.ensureSourceDelimiters; + } + + @Override + public int hashCode() { + return Objects.hash(normalizeSetextHeadings, collapseConsecutiveBlankLines, oneSentencePerLine, + normalizeBlockDelimiters, removeTrailingHeaderEqualsSign, titleCase, removeTrailingWhitespace, + normalizeListBullets, normalizeOrderedListMarkers, ensureHeadingBlankLines, ensureSourceDelimiters); + } +} diff --git a/lib/src/main/java/com/diffplug/spotless/asciidoc/AdocfmtStep.java b/lib/src/main/java/com/diffplug/spotless/asciidoc/AdocfmtStep.java new file mode 100644 index 0000000000..b2898c79d4 --- /dev/null +++ b/lib/src/main/java/com/diffplug/spotless/asciidoc/AdocfmtStep.java @@ -0,0 +1,117 @@ +/* + * Copyright 2026 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.spotless.asciidoc; + +import java.io.Serial; +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Objects; + +import com.diffplug.spotless.FormatterFunc; +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.JarState; +import com.diffplug.spotless.Provisioner; +import com.diffplug.spotless.ThrowingEx; + +public final class AdocfmtStep implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + private static final String DEFAULT_VERSION = "0.1.2"; + private static final String NAME = "adocfmt"; + private static final String MAVEN_COORDINATE = "org.drjekyll:adocfmt:"; + + private final String version; + private final AdocfmtConfig config; + private final JarState.Promised jarState; + + private AdocfmtStep(String version, AdocfmtConfig config, JarState.Promised jarState) { + this.version = version; + this.config = config; + this.jarState = jarState; + } + + public static FormatterStep create(Provisioner provisioner) { + return create(defaultVersion(), provisioner); + } + + public static FormatterStep create(String version, Provisioner provisioner) { + return create(version, provisioner, new AdocfmtConfig()); + } + + public static FormatterStep create(String version, Provisioner provisioner, AdocfmtConfig config) { + Objects.requireNonNull(version, "version"); + Objects.requireNonNull(provisioner, "provisioner"); + Objects.requireNonNull(config, "config"); + return FormatterStep.create(NAME, + new AdocfmtStep(version, config, JarState.promise(() -> JarState.from(MAVEN_COORDINATE + version, provisioner))), + AdocfmtStep::equalityState, + State::createFormat); + } + + public static String defaultVersion() { + return DEFAULT_VERSION; + } + + private State equalityState() { + return new State(version, config, jarState.get()); + } + + private static final class State implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + private final String version; + private final AdocfmtConfig config; + private final JarState jarState; + + State(String version, AdocfmtConfig config, JarState jarState) { + this.version = version; + this.config = config; + this.jarState = jarState; + } + + FormatterFunc createFormat() throws Exception { + final ClassLoader classLoader = jarState.getClassLoader(); + final Class formatterClass = classLoader.loadClass("org.drjekyll.adocfmt.AsciidocFormatter"); + final Class configClass = classLoader.loadClass("org.drjekyll.adocfmt.AsciidocFormatterConfig"); + final Method builderMethod = configClass.getMethod("builder"); + Object builder = builderMethod.invoke(null); + final Class builderClass = builder.getClass(); + builder = builderClass.getMethod("normalizeSetextHeadings", boolean.class).invoke(builder, config.normalizeSetextHeadings); + builder = builderClass.getMethod("collapseConsecutiveBlankLines", boolean.class).invoke(builder, config.collapseConsecutiveBlankLines); + builder = builderClass.getMethod("oneSentencePerLine", boolean.class).invoke(builder, config.oneSentencePerLine); + builder = builderClass.getMethod("normalizeBlockDelimiters", boolean.class).invoke(builder, config.normalizeBlockDelimiters); + builder = builderClass.getMethod("removeTrailingHeaderEqualsSign", boolean.class).invoke(builder, config.removeTrailingHeaderEqualsSign); + builder = builderClass.getMethod("titleCase", boolean.class).invoke(builder, config.titleCase); + builder = builderClass.getMethod("removeTrailingWhitespace", boolean.class).invoke(builder, config.removeTrailingWhitespace); + builder = builderClass.getMethod("normalizeListBullets", boolean.class).invoke(builder, config.normalizeListBullets); + builder = builderClass.getMethod("normalizeOrderedListMarkers", boolean.class).invoke(builder, config.normalizeOrderedListMarkers); + builder = builderClass.getMethod("ensureHeadingBlankLines", boolean.class).invoke(builder, config.ensureHeadingBlankLines); + builder = builderClass.getMethod("ensureSourceDelimiters", boolean.class).invoke(builder, config.ensureSourceDelimiters); + final Object adocfmtConfig = builderClass.getMethod("build").invoke(builder); + + final Object formatter = formatterClass.getConstructor(configClass).newInstance(adocfmtConfig); + final Method formatMethod = formatterClass.getMethod("format", String.class); + return input -> { + try { + return (String) formatMethod.invoke(formatter, input); + } catch (InvocationTargetException e) { + throw ThrowingEx.unwrapCause(e); + } + }; + } + } +} diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index 47ce008f79..a8db468ed7 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -4,6 +4,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] +### Added +- Add support for AsciiDoc formatting via `adocfmt`. (#TODO-PR-LINK) ### Fixed - Prevent build caches from interfering when executing under the `-PspotlessIdeHook` mode. ([#2365](https://github.com/diffplug/spotless/issues/2365)) ### Changes diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index 339c719668..a9f1140e51 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -60,6 +60,7 @@ Spotless supports all of Gradle's built-in performance features (incremental bui - [Groovy](#groovy) ([eclipse groovy](#eclipse-groovy)) - [Kotlin](#kotlin) ([ktfmt](#ktfmt), [ktlint](#ktlint), [diktat](#diktat), [tabletest-formatter](#tabletest-formatter-1), [prettier](#prettier)) - [Scala](#scala) ([scalafmt](#scalafmt)) + - [Asciidoc](#asciidoc) ([adocfmt](#adocfmt)) - [C/C++](#cc) ([clang-format](#clang-format), [eclipse cdt](#eclipse-cdt)) - [Protobuf](#protobuf) ([buf](#buf), [clang-format](#clang-format)) - [Python](#python) ([black](#black)) @@ -830,6 +831,40 @@ spotless { antlr4formatter('1.2.1') // version is optional ``` +## Asciidoc + +`com.diffplug.gradle.spotless.AsciidocExtension` [javadoc](https://javadoc.io/doc/com.diffplug.spotless/spotless-plugin-gradle/8.6.0/com/diffplug/gradle/spotless/AsciidocExtension.html), [code](https://github.com/diffplug/spotless/blob/main/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AsciidocExtension.java) + +```gradle +spotless { + asciidoc { + target '**/*.adoc', '**/*.asciidoc', '**/*.asc' // default value, you can change if you want + adocfmt() // has its own section below + } +} +``` + +### adocfmt + +[homepage](https://github.com/dheid/adocfmt). [available versions](https://search.maven.org/artifact/org.drjekyll/adocfmt). + +```gradle +adocfmt('0.1.2') // version is optional + .normalizeSetextHeadings(false) // convert === underlines to ATX == (default: false) + .collapseConsecutiveBlankLines(true) // max 1 blank line (default: true) + .oneSentencePerLine(false) // each sentence on its own line (default: false) + .normalizeBlockDelimiters(true) // exactly 4 characters (e.g. ----) (default: true) + .removeTrailingHeaderEqualsSign(true) // == Title == -> == Title (default: true) + .titleCase(false) // Title Case headings (default: false) + .removeTrailingWhitespace(true) // trim end of line (default: true) + .normalizeListBullets(false) // - -> * (default: false) + .normalizeOrderedListMarkers(false) // 1. -> . (default: false) + .ensureHeadingBlankLines(true) // blank line before/after headings (default: true) + .ensureSourceDelimiters(false) // wrap [source] in ---- (default: false) +``` + +Options default to `true` or `false` as shown above. This formatter is designed to help you maintain a clean, consistent AsciiDoc structure. Surface-altering options like `oneSentencePerLine` and `normalizeSetextHeadings` default to `false` so that zero-config formatting is conservative; opt in explicitly if you want those transforms. + diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AsciidocExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AsciidocExtension.java new file mode 100644 index 0000000000..d6783ac524 --- /dev/null +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AsciidocExtension.java @@ -0,0 +1,124 @@ +/* + * Copyright 2026 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.gradle.spotless; + +import java.util.List; + +import javax.inject.Inject; + +import com.diffplug.spotless.asciidoc.AdocfmtConfig; +import com.diffplug.spotless.asciidoc.AdocfmtStep; + +public class AsciidocExtension extends FormatExtension { + static final String NAME = "asciidoc"; + + @Inject + public AsciidocExtension(SpotlessExtension spotless) { + super(spotless); + } + + public AdocfmtFormatterConfig adocfmt() { + return adocfmt(AdocfmtStep.defaultVersion()); + } + + public AdocfmtFormatterConfig adocfmt(String version) { + return new AdocfmtFormatterConfig(version); + } + + public class AdocfmtFormatterConfig { + private final String version; + private final AdocfmtConfig config = new AdocfmtConfig(); + + AdocfmtFormatterConfig(String version) { + this.version = version; + addStep(AdocfmtStep.create(version, provisioner(), config)); + } + + public AdocfmtFormatterConfig normalizeSetextHeadings(boolean normalizeSetextHeadings) { + config.normalizeSetextHeadings = normalizeSetextHeadings; + replaceStep(AdocfmtStep.create(version, provisioner(), config)); + return this; + } + + public AdocfmtFormatterConfig collapseConsecutiveBlankLines(boolean collapseConsecutiveBlankLines) { + config.collapseConsecutiveBlankLines = collapseConsecutiveBlankLines; + replaceStep(AdocfmtStep.create(version, provisioner(), config)); + return this; + } + + public AdocfmtFormatterConfig oneSentencePerLine(boolean oneSentencePerLine) { + config.oneSentencePerLine = oneSentencePerLine; + replaceStep(AdocfmtStep.create(version, provisioner(), config)); + return this; + } + + public AdocfmtFormatterConfig normalizeBlockDelimiters(boolean normalizeBlockDelimiters) { + config.normalizeBlockDelimiters = normalizeBlockDelimiters; + replaceStep(AdocfmtStep.create(version, provisioner(), config)); + return this; + } + + public AdocfmtFormatterConfig removeTrailingHeaderEqualsSign(boolean removeTrailingHeaderEqualsSign) { + config.removeTrailingHeaderEqualsSign = removeTrailingHeaderEqualsSign; + replaceStep(AdocfmtStep.create(version, provisioner(), config)); + return this; + } + + public AdocfmtFormatterConfig titleCase(boolean titleCase) { + config.titleCase = titleCase; + replaceStep(AdocfmtStep.create(version, provisioner(), config)); + return this; + } + + public AdocfmtFormatterConfig removeTrailingWhitespace(boolean removeTrailingWhitespace) { + config.removeTrailingWhitespace = removeTrailingWhitespace; + replaceStep(AdocfmtStep.create(version, provisioner(), config)); + return this; + } + + public AdocfmtFormatterConfig normalizeListBullets(boolean normalizeListBullets) { + config.normalizeListBullets = normalizeListBullets; + replaceStep(AdocfmtStep.create(version, provisioner(), config)); + return this; + } + + public AdocfmtFormatterConfig normalizeOrderedListMarkers(boolean normalizeOrderedListMarkers) { + config.normalizeOrderedListMarkers = normalizeOrderedListMarkers; + replaceStep(AdocfmtStep.create(version, provisioner(), config)); + return this; + } + + public AdocfmtFormatterConfig ensureHeadingBlankLines(boolean ensureHeadingBlankLines) { + config.ensureHeadingBlankLines = ensureHeadingBlankLines; + replaceStep(AdocfmtStep.create(version, provisioner(), config)); + return this; + } + + public AdocfmtFormatterConfig ensureSourceDelimiters(boolean ensureSourceDelimiters) { + config.ensureSourceDelimiters = ensureSourceDelimiters; + replaceStep(AdocfmtStep.create(version, provisioner(), config)); + return this; + } + } + + @Override + protected void setupTask(SpotlessTask task) { + if (target == null) { + target = parseTarget(List.of("**/*.adoc", "**/*.asciidoc", "**/*.asc")); + } + super.setupTask(task); + } +} diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java index 0ab99f11ce..b1764933b4 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java @@ -228,13 +228,20 @@ public void yaml(Action closure) { format(YamlExtension.NAME, YamlExtension.class, closure); } - /** Configures the special Gherkin-specific extension. */ + /** Configures the special gherkin-specific extension. */ public void gherkin(Action closure) { requireNonNull(closure); format(GherkinExtension.NAME, GherkinExtension.class, closure); } + /** Configures the special asciidoc-specific extension. */ + public void asciidoc(Action closure) { + requireNonNull(closure); + format(AsciidocExtension.NAME, AsciidocExtension.class, closure); + } + public void toml(Action closure) { + requireNonNull(closure); format(TomlExtension.NAME, TomlExtension.class, closure); } diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/AsciidocExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/AsciidocExtensionTest.java new file mode 100644 index 0000000000..c312513d06 --- /dev/null +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/AsciidocExtensionTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2026 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.gradle.spotless; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +class AsciidocExtensionTest extends GradleIntegrationHarness { + @Test + void integration() throws IOException { + setFile("build.gradle") + .toContent( + """ + plugins { + id 'com.diffplug.spotless' + } + repositories { mavenCentral() } + spotless { + asciidoc { + target 'test.adoc' + adocfmt('0.1.2') + .normalizeSetextHeadings(true) + .collapseConsecutiveBlankLines(true) + .oneSentencePerLine(true) + .normalizeBlockDelimiters(true) + .removeTrailingHeaderEqualsSign(true) + .titleCase(true) + .removeTrailingWhitespace(true) + .normalizeListBullets(true) + .normalizeOrderedListMarkers(true) + .ensureHeadingBlankLines(true) + .ensureSourceDelimiters(true) + } + } + """); + setFile("test.adoc").toResource("asciidoc/adocfmt/dirty.adoc"); + gradleRunner().withArguments("spotlessApply").build(); + assertFile("test.adoc").sameAsResource("asciidoc/adocfmt/clean_all_options.adoc"); + } +} diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index e06df4137f..a54d68f5dd 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -4,6 +4,9 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] +### Added +- Add support for AsciiDoc formatting via `adocfmt`. (#TODO-PR-LINK) + ## [3.6.0] - 2026-05-27 ### Added - Add `` to ``, ``, and `` for the Equo/Solstice P2 cache. ([#2944](https://github.com/diffplug/spotless/pull/2944)) diff --git a/plugin-maven/README.md b/plugin-maven/README.md index 741f813441..950e2e624a 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -44,6 +44,7 @@ user@machine repo % mvn spotless:check - [Groovy](#groovy) ([eclipse groovy](#eclipse-groovy)) - [Kotlin](#kotlin) ([ktfmt](#ktfmt), [ktlint](#ktlint), [diktat](#diktat), [tabletest-formatter](#tabletest-formatter-1), [prettier](#prettier)) - [Scala](#scala) ([scalafmt](#scalafmt)) + - [Asciidoc](#asciidoc) ([adocfmt](#adocfmt)) - [C/C++](#cc) ([eclipse cdt](#eclipse-cdt), [clang-format](#clang-format)) - [Python](#python) ([black](#black)) - [Antlr4](#antlr4) ([antlr4formatter](#antlr4formatter)) @@ -704,6 +705,48 @@ Additionally, `editorConfigOverride` options will override what's supplied in `. ``` +## Asciidoc + +[code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Asciidoc.java). [available steps](https://github.com/diffplug/spotless/tree/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc). + +```xml + + + + + **/*.adoc + **/*.asciidoc + **/*.asc + + + + + +``` + +### adocfmt + +[homepage](https://github.com/dheid/adocfmt). [available versions](https://search.maven.org/artifact/org.drjekyll/adocfmt). [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Adocfmt.java). + +```xml + + 0.1.2 + true + true + true + true + true + false + true + false + false + true + false + +``` + +Options default to `true` or `false` as shown above. This formatter is opinionated and designed to help you maintain a clean, consistent AsciiDoc structure. For example, `` is a highly recommended practice in the AsciiDoc community for better version control diffs. + ## 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). diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java index 437a684061..520211334c 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java @@ -63,6 +63,7 @@ import com.diffplug.spotless.Provisioner; import com.diffplug.spotless.extra.P2Provisioner; import com.diffplug.spotless.maven.antlr4.Antlr4; +import com.diffplug.spotless.maven.asciidoc.Asciidoc; import com.diffplug.spotless.maven.cpp.Cpp; import com.diffplug.spotless.maven.css.Css; import com.diffplug.spotless.maven.generic.Format; @@ -182,6 +183,9 @@ public abstract class AbstractSpotlessMojo extends AbstractMojo { @Parameter private Antlr4 antlr4; + @Parameter + private Asciidoc asciidoc; + @Parameter private Pom pom; @@ -453,7 +457,7 @@ private FileLocator getFileLocator() { } private List getFormatterFactories() { - return Stream.concat(formats.stream(), Stream.of(groovy, java, scala, kotlin, cpp, css, typescript, javascript, antlr4, pom, sql, python, markdown, json, shell, yaml, gherkin, go, rdf, protobuf, tableTest, toml)) + return Stream.concat(formats.stream(), Stream.of(groovy, java, scala, kotlin, asciidoc, cpp, css, typescript, javascript, antlr4, pom, sql, python, markdown, json, shell, yaml, gherkin, go, rdf, protobuf, tableTest, toml)) .filter(Objects::nonNull) .map(factory -> factory.init(repositorySystemSession)) .collect(toList()); diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Adocfmt.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Adocfmt.java new file mode 100644 index 0000000000..51362d3162 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Adocfmt.java @@ -0,0 +1,91 @@ +/* + * Copyright 2026 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.spotless.maven.asciidoc; + +import org.apache.maven.plugins.annotations.Parameter; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.asciidoc.AdocfmtConfig; +import com.diffplug.spotless.asciidoc.AdocfmtStep; +import com.diffplug.spotless.maven.FormatterStepConfig; +import com.diffplug.spotless.maven.FormatterStepFactory; + +public class Adocfmt implements FormatterStepFactory { + @Parameter + private String version; + + @Parameter + private Boolean normalizeSetextHeadings; + + @Parameter + private Boolean collapseConsecutiveBlankLines; + + @Parameter + private Boolean oneSentencePerLine; + + @Parameter + private Boolean normalizeBlockDelimiters; + + @Parameter + private Boolean removeTrailingHeaderEqualsSign; + + @Parameter + private Boolean titleCase; + + @Parameter + private Boolean removeTrailingWhitespace; + + @Parameter + private Boolean normalizeListBullets; + + @Parameter + private Boolean normalizeOrderedListMarkers; + + @Parameter + private Boolean ensureHeadingBlankLines; + + @Parameter + private Boolean ensureSourceDelimiters; + + @Override + public FormatterStep newFormatterStep(FormatterStepConfig config) { + String version = this.version != null ? this.version : AdocfmtStep.defaultVersion(); + AdocfmtConfig adocfmtConfig = new AdocfmtConfig(); + if (normalizeSetextHeadings != null) + adocfmtConfig.normalizeSetextHeadings = normalizeSetextHeadings; + if (collapseConsecutiveBlankLines != null) + adocfmtConfig.collapseConsecutiveBlankLines = collapseConsecutiveBlankLines; + if (oneSentencePerLine != null) + adocfmtConfig.oneSentencePerLine = oneSentencePerLine; + if (normalizeBlockDelimiters != null) + adocfmtConfig.normalizeBlockDelimiters = normalizeBlockDelimiters; + if (removeTrailingHeaderEqualsSign != null) + adocfmtConfig.removeTrailingHeaderEqualsSign = removeTrailingHeaderEqualsSign; + if (titleCase != null) + adocfmtConfig.titleCase = titleCase; + if (removeTrailingWhitespace != null) + adocfmtConfig.removeTrailingWhitespace = removeTrailingWhitespace; + if (normalizeListBullets != null) + adocfmtConfig.normalizeListBullets = normalizeListBullets; + if (normalizeOrderedListMarkers != null) + adocfmtConfig.normalizeOrderedListMarkers = normalizeOrderedListMarkers; + if (ensureHeadingBlankLines != null) + adocfmtConfig.ensureHeadingBlankLines = ensureHeadingBlankLines; + if (ensureSourceDelimiters != null) + adocfmtConfig.ensureSourceDelimiters = ensureSourceDelimiters; + return AdocfmtStep.create(version, config.getProvisioner(), adocfmtConfig); + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Asciidoc.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Asciidoc.java new file mode 100644 index 0000000000..c4734f2ecb --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Asciidoc.java @@ -0,0 +1,38 @@ +/* + * Copyright 2026 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.spotless.maven.asciidoc; + +import java.util.Set; + +import org.apache.maven.project.MavenProject; + +import com.diffplug.spotless.maven.FormatterFactory; + +public class Asciidoc extends FormatterFactory { + @Override + public Set defaultIncludes(MavenProject project) { + return Set.of("**/*.adoc", "**/*.asciidoc", "**/*.asc"); + } + + @Override + public String licenseHeaderDelimiter() { + return null; + } + + public void addAdocfmt(Adocfmt adocfmt) { + addStepFactory(adocfmt); + } +} diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java index fd6c4b2047..bcc5791a5b 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java @@ -125,6 +125,10 @@ protected void writePomWithAntlr4Steps(String... steps) throws IOException { writePom(groupWithSteps("antlr4", steps)); } + protected void writePomWithAsciidocSteps(String... steps) throws IOException { + writePom(groupWithSteps("asciidoc", including("**/*.adoc"), steps)); + } + protected void writePomWithGroovySteps(String... steps) throws IOException { writePom(groupWithSteps("groovy", steps)); } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/asciidoc/AdocfmtMavenTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/asciidoc/AdocfmtMavenTest.java new file mode 100644 index 0000000000..f39c3dac7b --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/asciidoc/AdocfmtMavenTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2026 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.spotless.maven.asciidoc; + +import org.junit.jupiter.api.Test; + +import com.diffplug.spotless.maven.MavenIntegrationHarness; + +public class AdocfmtMavenTest extends MavenIntegrationHarness { + @Test + public void testAdocfmt() throws Exception { + writePomWithAsciidocSteps( + """ + + 0.1.2 + true + true + true + true + true + true + true + true + true + true + true + + """); + + setFile("test.adoc").toResource("asciidoc/adocfmt/dirty.adoc"); + mavenRunner().withArguments("spotless:apply").runNoError(); + assertFile("test.adoc").sameAsResource("asciidoc/adocfmt/clean_all_options.adoc"); + } +} diff --git a/testlib/src/main/resources/asciidoc/adocfmt/clean_all_options.adoc b/testlib/src/main/resources/asciidoc/adocfmt/clean_all_options.adoc new file mode 100644 index 0000000000..8fab119bf6 --- /dev/null +++ b/testlib/src/main/resources/asciidoc/adocfmt/clean_all_options.adoc @@ -0,0 +1,255 @@ += Asciidoctor Demo +//// +Big ol' comment + +sittin' right 'tween this here title 'n header metadata +//// +Dan Allen +:description: A demo of Asciidoctor. This document \ + exercises numerous features of AsciiDoc \ + to test Asciidoctor compliance. +:library: Asciidoctor +:idprefix: +:numbered: +:imagesdir: images +:experimental: +//:toc: macro +:toc: preamble +:toc-title: pass:[

Contents

] +:css-signature: demo +//:max-width: 800px +//:doctype: book +//:sectids!: +ifdef::env-github[] +:note-caption: :information_source: +:tip-caption: :bulb: +endif::[] + +This is a demonstration of {library} {asciidoctor-version}. +And this is the preamble of this document. + +[[purpose]] +.Purpose +**** +This document exercises many of the features of AsciiDoc to test the {library} implementation. +**** + +TIP: If you want the HTML to have the familiar AsciiDoc Python style, load the asciidoc.css stylesheet using the CLI option `-a stylesheet=asciidoc.css`. + +== First Steps with AsciiDoc + +.Inline Markup +* underlines around a phrase place _emphasis_ +* astericks around a phrase make the text *bold* +* double astericks around one or more **l**etters in a word make those letters bold +* double underscore around a __sub__string in a word emphasizes that substring +* use carrots around characters to make them ^super^script +* use tildes around characters to make them ~sub~script +ifdef::basebackend-html[* to pass through +++HTML+++ directly, surround the text with triple plus] +ifdef::basebackend-docbook[* to pass through +++XML+++ directly, surround the text with triple plus] + +// separate two adjacent lists using a line comment (only the leading // is required) + +- characters can be escaped using a {backslash} +* for instance, you can escape a quote inside emphasized text like _Here\'s Johnny!_ +- you can safely use reserved XML characters like <, > and &, which are escaped when converting +- force a space{sp}between inline elements using the \{sp} attribute +- hold text together with an intrinsic non-breaking{nbsp}space attribute, \{nbsp} +- handle words with unicode characters like in the name Gregory Romé +- claim your copyright (C), registered trademark (R) or trademark (TM) +- select menu:View[Zoom > Reset] to reset the zoom + +You can write text http://example.com[with inline links], optionally{sp}using an explicit link:http://example.com[link prefix]. +In either case, the link can have a http://example.com?foo=bar&lang=en[query string]. + +If you want to break a line + +just end it in a {plus} sign + +and continue typing on the next line. + +=== Lists Upon Lists + +.Adjacent Lists +* this list +* should join + +* to have +* four items + +ifdef::env-github[] +++++ + +++++ +endif::env-github[] + +[[ordered]] +.Ordered Lists +. These items +. will be auto-numbered +.. and can be nested +. A numbered list can nest +* unordered +* list +* items + +.Statement +I swear I left it in _Guy\'s_ car. +Let\'s go look for it. + +[[defs]] +term:: +definition line two +[[another_term]]another term:: + + another definition, which can be literal (indented) or regular paragraph + +This should be a standalone paragraph, not grabbed by the definition list. + +[[nested]] +* first level +written on two lines +* first level ++ +.... +with this literal text +.... + +* first level + + with more literal text + +** second level +*** third level +- fourth level +* back to + +first level + +// this is just a comment + +Let's make a horizontal rule... + +''' + +then take a break. + +//// +We'll be right with you... + +after this brief interruption. +//// + +== ...And We're Back! + +Do you want to see a image:tiger.png[Tiger,50]? + +Do you feel safer with the tiger in a box? + +.Tiger in a Box +image::tiger.png[] + +Fancy some math? + +pass:[$$\sum_{i=1}^N (f_i)^2$$] + +We'd like to include content, but for now the best we can do is link to it. + +include::include.adoc[] + +.Asciidoctor Usage Example. The Listing Should Contain 5 Lines. +[,ruby] +---- +require 'asciidoctor' + +doc = Asciidoctor.load '*This* is http://asciidoc.org[AsciiDoc]!', header_footer: true + +puts doc.convert +---- + +// TODO: Use ifdef to show output according to current backend +.Output of Asciidoctor Usage Example +```html + + + + + + +Untitled + + + + +
+
+

This is AsciiDoc!

+
+
+ + + +``` + +=== Block Quotes and "`Smart`" Ones + +____ +AsciiDoc is _so_ *powerful*! +____ + +This verse comes to mind. + +[verse] +La la la + +Here's another quote: + +[quote, Sir Arthur Conan Doyle, The Adventures of Sherlock Holmes] +____ +When you have eliminated all which is impossible, then whatever remains, +however improbable, must be the truth. +____ + +"`Get moving!`" he shouted. + +== Getting Literal [[literally]] + + Want to get literal? Just prefix a line with a space (just 1 space will do). + +.... +I'll join that party, too. +.... + +We forgot to mention in <> that you can change the numbering style. + +.. first item (yeah!) +.. second item, looking `so mono` +.. third item, `mono` it is! + +// This attribute line will get reattached to the next block +// despite being followed by a trailing blank line +[id='wrapup'] + +== Wrap-up + +NOTE: AsciiDoc is quite cool, you should try it! + +[TIP] +.Info +==== +Go to this URL to learn more about it: + +* http://asciidoc.org + +Or you could return to the xref:first-steps-with-asciidoc[] or <>. +==== + +Here's a reference to the definition of <>, in case you forgot it. + +[NOTE] +One more thing. +Happy documenting! + +[[google]]When all else fails, head over to . diff --git a/testlib/src/main/resources/asciidoc/adocfmt/clean_complex.adoc b/testlib/src/main/resources/asciidoc/adocfmt/clean_complex.adoc new file mode 100644 index 0000000000..96e07ae9fc --- /dev/null +++ b/testlib/src/main/resources/asciidoc/adocfmt/clean_complex.adoc @@ -0,0 +1,258 @@ +Asciidoctor Demo +================ +//// +Big ol' comment + +sittin' right 'tween this here title 'n header metadata +//// +Dan Allen +:description: A demo of Asciidoctor. This document \ + exercises numerous features of AsciiDoc \ + to test Asciidoctor compliance. +:library: Asciidoctor +:idprefix: +:numbered: +:imagesdir: images +:experimental: +//:toc: macro +:toc: preamble +:toc-title: pass:[

Contents

] +:css-signature: demo +//:max-width: 800px +//:doctype: book +//:sectids!: +ifdef::env-github[] +:note-caption: :information_source: +:tip-caption: :bulb: +endif::[] + +This is a demonstration of {library} {asciidoctor-version}. +And this is the preamble of this document. + +[[purpose]] +.Purpose +**** +This document exercises many of the features of AsciiDoc to test the {library} implementation. +**** + +TIP: If you want the HTML to have the familiar AsciiDoc Python style, load the asciidoc.css stylesheet using the CLI option `-a stylesheet=asciidoc.css`. + +== First Steps with AsciiDoc + +.Inline markup +* underlines around a phrase place _emphasis_ +* astericks around a phrase make the text *bold* +* double astericks around one or more **l**etters in a word make those letters bold +* double underscore around a __sub__string in a word emphasizes that substring +* use carrots around characters to make them ^super^script +* use tildes around characters to make them ~sub~script +ifdef::basebackend-html[* to pass through +++HTML+++ directly, surround the text with triple plus] +ifdef::basebackend-docbook[* to pass through +++XML+++ directly, surround the text with triple plus] + +// separate two adjacent lists using a line comment (only the leading // is required) + +- characters can be escaped using a {backslash} +* for instance, you can escape a quote inside emphasized text like _Here\'s Johnny!_ +- you can safely use reserved XML characters like <, > and &, which are escaped when converting +- force a space{sp}between inline elements using the \{sp} attribute +- hold text together with an intrinsic non-breaking{nbsp}space attribute, \{nbsp} +- handle words with unicode characters like in the name Gregory Romé +- claim your copyright (C), registered trademark (R) or trademark (TM) +- select menu:View[Zoom > Reset] to reset the zoom + +You can write text http://example.com[with inline links], optionally{sp}using +an explicit link:http://example.com[link prefix]. In either case, the link can +have a http://example.com?foo=bar&lang=en[query string]. + +If you want to break a line + +just end it in a {plus} sign + +and continue typing on the next line. + +=== Lists Upon Lists + +.Adjacent lists +* this list +* should join + +* to have +* four items + +ifdef::env-github[] +++++ + +++++ +endif::env-github[] + +[[ordered]] +.Ordered lists +. These items +. will be auto-numbered +.. and can be nested +. A numbered list can nest +* unordered +* list +* items + +.Statement +I swear I left it in _Guy\'s_ car. Let\'s go look for it. + +[[defs]] +term:: +definition +line two +[[another_term]]another term:: + + another definition, which can be literal (indented) or regular paragraph + +This should be a standalone paragraph, not grabbed by the definition list. + +[[nested]] +* first level +written on two lines +* first level ++ +.... +with this literal text +.... + +* first level + + with more literal text + +** second level +*** third level +- fourth level +* back to + +first level + +// this is just a comment + +Let's make a horizontal rule... + +''' + +then take a break. + +//// +We'll be right with you... + +after this brief interruption. +//// + +== ...and we're back! + +Do you want to see a image:tiger.png[Tiger,50]? + +Do you feel safer with the tiger in a box? + +.Tiger in a box +image::tiger.png[] + +Fancy some math? + +pass:[$$\sum_{i=1}^N (f_i)^2$$] + +We'd like to include content, but for now the best we can do is link to it. + +include::include.adoc[] + +.Asciidoctor usage example. The listing should contain 5 lines. +[,ruby] +---- +require 'asciidoctor' + +doc = Asciidoctor.load '*This* is http://asciidoc.org[AsciiDoc]!', header_footer: true + +puts doc.convert +---- + +// TODO: Use ifdef to show output according to current backend +.Output of Asciidoctor usage example +```html + + + + + + +Untitled + + + + +
+
+

This is AsciiDoc!

+
+
+ + + +``` + +=== Block Quotes and "`Smart`" Ones + +____ +AsciiDoc is _so_ *powerful*! +____ + +This verse comes to mind. + +[verse] +La la la + +Here's another quote: + +[quote, Sir Arthur Conan Doyle, The Adventures of Sherlock Holmes] +____ +When you have eliminated all which is impossible, then whatever remains, +however improbable, must be the truth. +____ + +"`Get moving!`" he shouted. + +Getting Literal [[literally]] +----------------------------- + + Want to get literal? Just prefix a line with a space (just 1 space will do). + +.... +I'll join that party, too. +.... + +We forgot to mention in <> that you can change the numbering style. + +.. first item (yeah!) +.. second item, looking `so mono` +.. third item, `mono` it is! + +// This attribute line will get reattached to the next block +// despite being followed by a trailing blank line +[id='wrapup'] + +Wrap-up +------- + +NOTE: AsciiDoc is quite cool, you should try it! + +[TIP] +.Info +==== +Go to this URL to learn more about it: + +* http://asciidoc.org + +Or you could return to the xref:first-steps-with-asciidoc[] or <>. +==== + +Here's a reference to the definition of <>, in case you forgot it. + +[NOTE] +One more thing. Happy documenting! + +[[google]]When all else fails, head over to . diff --git a/testlib/src/main/resources/asciidoc/adocfmt/clean_custom.adoc b/testlib/src/main/resources/asciidoc/adocfmt/clean_custom.adoc new file mode 100644 index 0000000000..1751728b10 --- /dev/null +++ b/testlib/src/main/resources/asciidoc/adocfmt/clean_custom.adoc @@ -0,0 +1,255 @@ +Asciidoctor Demo +================ +//// +Big ol' comment + +sittin' right 'tween this here title 'n header metadata +//// +Dan Allen +:description: A demo of Asciidoctor. This document \ + exercises numerous features of AsciiDoc \ + to test Asciidoctor compliance. +:library: Asciidoctor +:idprefix: +:numbered: +:imagesdir: images +:experimental: +//:toc: macro +:toc: preamble +:toc-title: pass:[

Contents

] +:css-signature: demo +//:max-width: 800px +//:doctype: book +//:sectids!: +ifdef::env-github[] +:note-caption: :information_source: +:tip-caption: :bulb: +endif::[] + +This is a demonstration of {library} {asciidoctor-version}. +And this is the preamble of this document. + +[[purpose]] +.Purpose +**** +This document exercises many of the features of AsciiDoc to test the {library} implementation. +**** + +TIP: If you want the HTML to have the familiar AsciiDoc Python style, load the asciidoc.css stylesheet using the CLI option `-a stylesheet=asciidoc.css`. + +== First Steps with AsciiDoc +.Inline markup +* underlines around a phrase place _emphasis_ +* astericks around a phrase make the text *bold* +* double astericks around one or more **l**etters in a word make those letters bold +* double underscore around a __sub__string in a word emphasizes that substring +* use carrots around characters to make them ^super^script +* use tildes around characters to make them ~sub~script +ifdef::basebackend-html[* to pass through +++HTML+++ directly, surround the text with triple plus] +ifdef::basebackend-docbook[* to pass through +++XML+++ directly, surround the text with triple plus] + +// separate two adjacent lists using a line comment (only the leading // is required) + +- characters can be escaped using a {backslash} +* for instance, you can escape a quote inside emphasized text like _Here\'s Johnny!_ +- you can safely use reserved XML characters like <, > and &, which are escaped when converting +- force a space{sp}between inline elements using the \{sp} attribute +- hold text together with an intrinsic non-breaking{nbsp}space attribute, \{nbsp} +- handle words with unicode characters like in the name Gregory Romé +- claim your copyright (C), registered trademark (R) or trademark (TM) +- select menu:View[Zoom > Reset] to reset the zoom + +You can write text http://example.com[with inline links], optionally{sp}using +an explicit link:http://example.com[link prefix]. In either case, the link can +have a http://example.com?foo=bar&lang=en[query string]. + +If you want to break a line + +just end it in a {plus} sign + +and continue typing on the next line. + +=== Lists Upon Lists +.Adjacent lists +* this list +* should join + +* to have +* four items + +ifdef::env-github[] +++++ + +++++ +endif::env-github[] + +[[ordered]] +.Ordered lists +. These items +. will be auto-numbered +.. and can be nested +. A numbered list can nest +* unordered +* list +* items + +.Statement +I swear I left it in _Guy\'s_ car. Let\'s go look for it. + +[[defs]] +term:: +definition +line two +[[another_term]]another term:: + + another definition, which can be literal (indented) or regular paragraph + +This should be a standalone paragraph, not grabbed by the definition list. + +[[nested]] +* first level +written on two lines +* first level ++ +.... +with this literal text +.... + +* first level + + with more literal text + +** second level +*** third level +- fourth level +* back to + +first level + +// this is just a comment + +Let's make a horizontal rule... + +''' + +then take a break. + +//// +We'll be right with you... + +after this brief interruption. +//// + +== ...and we're back! + +Do you want to see a image:tiger.png[Tiger,50]? + +Do you feel safer with the tiger in a box? + +.Tiger in a box +image::tiger.png[] + +Fancy some math? + +pass:[$$\sum_{i=1}^N (f_i)^2$$] + +We'd like to include content, but for now the best we can do is link to it. + +include::include.adoc[] + +.Asciidoctor usage example. The listing should contain 5 lines. +[,ruby] +---- +require 'asciidoctor' + +doc = Asciidoctor.load '*This* is http://asciidoc.org[AsciiDoc]!', header_footer: true + +puts doc.convert +---- + +// TODO: Use ifdef to show output according to current backend +.Output of Asciidoctor usage example +```html + + + + + + +Untitled + + + + +
+
+

This is AsciiDoc!

+
+
+ + + +``` + +=== Block Quotes and "`Smart`" Ones + +____ +AsciiDoc is _so_ *powerful*! +____ + +This verse comes to mind. + +[verse] +La la la + +Here's another quote: + +[quote, Sir Arthur Conan Doyle, The Adventures of Sherlock Holmes] +____ +When you have eliminated all which is impossible, then whatever remains, +however improbable, must be the truth. +____ + +"`Get moving!`" he shouted. + +Getting Literal [[literally]] +----------------------------- + + Want to get literal? Just prefix a line with a space (just 1 space will do). + +.... +I'll join that party, too. +.... + +We forgot to mention in <> that you can change the numbering style. + +.. first item (yeah!) +.. second item, looking `so mono` +.. third item, `mono` it is! + +// This attribute line will get reattached to the next block +// despite being followed by a trailing blank line +[id='wrapup'] + +Wrap-up +------- +NOTE: AsciiDoc is quite cool, you should try it! + +[TIP] +.Info +==== +Go to this URL to learn more about it: + +* http://asciidoc.org + +Or you could return to the xref:first-steps-with-asciidoc[] or <>. +==== + +Here's a reference to the definition of <>, in case you forgot it. + +[NOTE] +One more thing. Happy documenting! + +[[google]]When all else fails, head over to . diff --git a/testlib/src/main/resources/asciidoc/adocfmt/clean_minimal.adoc b/testlib/src/main/resources/asciidoc/adocfmt/clean_minimal.adoc new file mode 100644 index 0000000000..96e07ae9fc --- /dev/null +++ b/testlib/src/main/resources/asciidoc/adocfmt/clean_minimal.adoc @@ -0,0 +1,258 @@ +Asciidoctor Demo +================ +//// +Big ol' comment + +sittin' right 'tween this here title 'n header metadata +//// +Dan Allen +:description: A demo of Asciidoctor. This document \ + exercises numerous features of AsciiDoc \ + to test Asciidoctor compliance. +:library: Asciidoctor +:idprefix: +:numbered: +:imagesdir: images +:experimental: +//:toc: macro +:toc: preamble +:toc-title: pass:[

Contents

] +:css-signature: demo +//:max-width: 800px +//:doctype: book +//:sectids!: +ifdef::env-github[] +:note-caption: :information_source: +:tip-caption: :bulb: +endif::[] + +This is a demonstration of {library} {asciidoctor-version}. +And this is the preamble of this document. + +[[purpose]] +.Purpose +**** +This document exercises many of the features of AsciiDoc to test the {library} implementation. +**** + +TIP: If you want the HTML to have the familiar AsciiDoc Python style, load the asciidoc.css stylesheet using the CLI option `-a stylesheet=asciidoc.css`. + +== First Steps with AsciiDoc + +.Inline markup +* underlines around a phrase place _emphasis_ +* astericks around a phrase make the text *bold* +* double astericks around one or more **l**etters in a word make those letters bold +* double underscore around a __sub__string in a word emphasizes that substring +* use carrots around characters to make them ^super^script +* use tildes around characters to make them ~sub~script +ifdef::basebackend-html[* to pass through +++HTML+++ directly, surround the text with triple plus] +ifdef::basebackend-docbook[* to pass through +++XML+++ directly, surround the text with triple plus] + +// separate two adjacent lists using a line comment (only the leading // is required) + +- characters can be escaped using a {backslash} +* for instance, you can escape a quote inside emphasized text like _Here\'s Johnny!_ +- you can safely use reserved XML characters like <, > and &, which are escaped when converting +- force a space{sp}between inline elements using the \{sp} attribute +- hold text together with an intrinsic non-breaking{nbsp}space attribute, \{nbsp} +- handle words with unicode characters like in the name Gregory Romé +- claim your copyright (C), registered trademark (R) or trademark (TM) +- select menu:View[Zoom > Reset] to reset the zoom + +You can write text http://example.com[with inline links], optionally{sp}using +an explicit link:http://example.com[link prefix]. In either case, the link can +have a http://example.com?foo=bar&lang=en[query string]. + +If you want to break a line + +just end it in a {plus} sign + +and continue typing on the next line. + +=== Lists Upon Lists + +.Adjacent lists +* this list +* should join + +* to have +* four items + +ifdef::env-github[] +++++ + +++++ +endif::env-github[] + +[[ordered]] +.Ordered lists +. These items +. will be auto-numbered +.. and can be nested +. A numbered list can nest +* unordered +* list +* items + +.Statement +I swear I left it in _Guy\'s_ car. Let\'s go look for it. + +[[defs]] +term:: +definition +line two +[[another_term]]another term:: + + another definition, which can be literal (indented) or regular paragraph + +This should be a standalone paragraph, not grabbed by the definition list. + +[[nested]] +* first level +written on two lines +* first level ++ +.... +with this literal text +.... + +* first level + + with more literal text + +** second level +*** third level +- fourth level +* back to + +first level + +// this is just a comment + +Let's make a horizontal rule... + +''' + +then take a break. + +//// +We'll be right with you... + +after this brief interruption. +//// + +== ...and we're back! + +Do you want to see a image:tiger.png[Tiger,50]? + +Do you feel safer with the tiger in a box? + +.Tiger in a box +image::tiger.png[] + +Fancy some math? + +pass:[$$\sum_{i=1}^N (f_i)^2$$] + +We'd like to include content, but for now the best we can do is link to it. + +include::include.adoc[] + +.Asciidoctor usage example. The listing should contain 5 lines. +[,ruby] +---- +require 'asciidoctor' + +doc = Asciidoctor.load '*This* is http://asciidoc.org[AsciiDoc]!', header_footer: true + +puts doc.convert +---- + +// TODO: Use ifdef to show output according to current backend +.Output of Asciidoctor usage example +```html + + + + + + +Untitled + + + + +
+
+

This is AsciiDoc!

+
+
+ + + +``` + +=== Block Quotes and "`Smart`" Ones + +____ +AsciiDoc is _so_ *powerful*! +____ + +This verse comes to mind. + +[verse] +La la la + +Here's another quote: + +[quote, Sir Arthur Conan Doyle, The Adventures of Sherlock Holmes] +____ +When you have eliminated all which is impossible, then whatever remains, +however improbable, must be the truth. +____ + +"`Get moving!`" he shouted. + +Getting Literal [[literally]] +----------------------------- + + Want to get literal? Just prefix a line with a space (just 1 space will do). + +.... +I'll join that party, too. +.... + +We forgot to mention in <> that you can change the numbering style. + +.. first item (yeah!) +.. second item, looking `so mono` +.. third item, `mono` it is! + +// This attribute line will get reattached to the next block +// despite being followed by a trailing blank line +[id='wrapup'] + +Wrap-up +------- + +NOTE: AsciiDoc is quite cool, you should try it! + +[TIP] +.Info +==== +Go to this URL to learn more about it: + +* http://asciidoc.org + +Or you could return to the xref:first-steps-with-asciidoc[] or <>. +==== + +Here's a reference to the definition of <>, in case you forgot it. + +[NOTE] +One more thing. Happy documenting! + +[[google]]When all else fails, head over to . diff --git a/testlib/src/main/resources/asciidoc/adocfmt/dirty.adoc b/testlib/src/main/resources/asciidoc/adocfmt/dirty.adoc new file mode 100644 index 0000000000..6c39f4f1b9 --- /dev/null +++ b/testlib/src/main/resources/asciidoc/adocfmt/dirty.adoc @@ -0,0 +1,256 @@ +Asciidoctor Demo +================ +//// +Big ol' comment + +sittin' right 'tween this here title 'n header metadata +//// +Dan Allen +:description: A demo of Asciidoctor. This document \ + exercises numerous features of AsciiDoc \ + to test Asciidoctor compliance. +:library: Asciidoctor +:idprefix: +:numbered: +:imagesdir: images +:experimental: +//:toc: macro +:toc: preamble +:toc-title: pass:[

Contents

] +:css-signature: demo +//:max-width: 800px +//:doctype: book +//:sectids!: +ifdef::env-github[] +:note-caption: :information_source: +:tip-caption: :bulb: +endif::[] + +This is a demonstration of {library} {asciidoctor-version}. +And this is the preamble of this document. + +[[purpose]] +.Purpose +**** +This document exercises many of the features of AsciiDoc to test the {library} implementation. +**** + +TIP: If you want the HTML to have the familiar AsciiDoc Python style, load the asciidoc.css stylesheet using the CLI option `-a stylesheet=asciidoc.css`. + +== First Steps with AsciiDoc +.Inline markup +* underlines around a phrase place _emphasis_ +* astericks around a phrase make the text *bold* +* double astericks around one or more **l**etters in a word make those letters bold +* double underscore around a __sub__string in a word emphasizes that substring +* use carrots around characters to make them ^super^script +* use tildes around characters to make them ~sub~script +ifdef::basebackend-html[* to pass through +++HTML+++ directly, surround the text with triple plus] +ifdef::basebackend-docbook[* to pass through +++XML+++ directly, surround the text with triple plus] + +// separate two adjacent lists using a line comment (only the leading // is required) + +- characters can be escaped using a {backslash} +* for instance, you can escape a quote inside emphasized text like _Here\'s Johnny!_ +- you can safely use reserved XML characters like <, > and &, which are escaped when converting +- force a space{sp}between inline elements using the \{sp} attribute +- hold text together with an intrinsic non-breaking{nbsp}space attribute, \{nbsp} +- handle words with unicode characters like in the name Gregory Romé +- claim your copyright (C), registered trademark (R) or trademark (TM) +- select menu:View[Zoom > Reset] to reset the zoom + +You can write text http://example.com[with inline links], optionally{sp}using +an explicit link:http://example.com[link prefix]. In either case, the link can +have a http://example.com?foo=bar&lang=en[query string]. + +If you want to break a line + +just end it in a {plus} sign + +and continue typing on the next line. + +=== Lists Upon Lists +.Adjacent lists +* this list +* should join + +* to have +* four items + +ifdef::env-github[] +++++ + +++++ +endif::env-github[] + +[[ordered]] +.Ordered lists +. These items +. will be auto-numbered +.. and can be nested +. A numbered list can nest +* unordered +* list +* items + +.Statement +I swear I left it in _Guy\'s_ car. Let\'s go look for it. + +[[defs]] +term:: +definition +line two +[[another_term]]another term:: + + another definition, which can be literal (indented) or regular paragraph + +This should be a standalone paragraph, not grabbed by the definition list. + +[[nested]] +* first level +written on two lines +* first level ++ +.... +with this literal text +.... + +* first level + + with more literal text + +** second level +*** third level +- fourth level +* back to + +first level + +// this is just a comment + +Let's make a horizontal rule... + +''' + +then take a break. + +//// +We'll be right with you... + +after this brief interruption. +//// + +== ...and we're back! + +Do you want to see a image:tiger.png[Tiger,50]? + +Do you feel safer with the tiger in a box? + +.Tiger in a box +image::tiger.png[] + +Fancy some math? + +pass:[$$\sum_{i=1}^N (f_i)^2$$] + +We'd like to include content, but for now the best we can do is link to it. + +include::include.adoc[] + +.Asciidoctor usage example. The listing should contain 5 lines. +[,ruby] +---- +require 'asciidoctor' + +doc = Asciidoctor.load '*This* is http://asciidoc.org[AsciiDoc]!', header_footer: true + +puts doc.convert +---- + +// TODO: Use ifdef to show output according to current backend +.Output of Asciidoctor usage example +```html + + + + + + +Untitled + + + + +
+
+

This is AsciiDoc!

+
+
+ + + +``` + +=== Block Quotes and "`Smart`" Ones + + +____ +AsciiDoc is _so_ *powerful*! +____ + +This verse comes to mind. + +[verse] +La la la + +Here's another quote: + +[quote, Sir Arthur Conan Doyle, The Adventures of Sherlock Holmes] +____ +When you have eliminated all which is impossible, then whatever remains, +however improbable, must be the truth. +____ + +"`Get moving!`" he shouted. + +Getting Literal [[literally]] +----------------------------- + + Want to get literal? Just prefix a line with a space (just 1 space will do). + +.... +I'll join that party, too. +.... + +We forgot to mention in <> that you can change the numbering style. + +.. first item (yeah!) +.. second item, looking `so mono` +.. third item, `mono` it is! + +// This attribute line will get reattached to the next block +// despite being followed by a trailing blank line +[id='wrapup'] + +Wrap-up +------- +NOTE: AsciiDoc is quite cool, you should try it! + +[TIP] +.Info +===== +Go to this URL to learn more about it: + +* http://asciidoc.org + +Or you could return to the xref:first-steps-with-asciidoc[] or <>. +===== + +Here's a reference to the definition of <>, in case you forgot it. + +[NOTE] +One more thing. Happy documenting! + +[[google]]When all else fails, head over to . diff --git a/testlib/src/test/java/com/diffplug/spotless/asciidoc/AdocfmtStepTest.java b/testlib/src/test/java/com/diffplug/spotless/asciidoc/AdocfmtStepTest.java new file mode 100644 index 0000000000..b41a9157f4 --- /dev/null +++ b/testlib/src/test/java/com/diffplug/spotless/asciidoc/AdocfmtStepTest.java @@ -0,0 +1,82 @@ +/* + * Copyright 2026 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.spotless.asciidoc; + +import org.junit.jupiter.api.Test; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.ResourceHarness; +import com.diffplug.spotless.SerializableEqualityTester; +import com.diffplug.spotless.StepHarness; +import com.diffplug.spotless.TestProvisioner; + +class AdocfmtStepTest extends ResourceHarness { + @Test + void behavior() { + FormatterStep step = AdocfmtStep.create(TestProvisioner.mavenCentral()); + StepHarness.forStep(step).testResource("asciidoc/adocfmt/dirty.adoc", "asciidoc/adocfmt/clean_minimal.adoc"); + } + + @Test + void complexBehavior() { + AdocfmtConfig config = new AdocfmtConfig(); + config.normalizeListBullets = true; + config.normalizeOrderedListMarkers = true; + config.ensureSourceDelimiters = true; + FormatterStep step = AdocfmtStep.create(AdocfmtStep.defaultVersion(), TestProvisioner.mavenCentral(), config); + StepHarness.forStep(step).testResource("asciidoc/adocfmt/dirty.adoc", "asciidoc/adocfmt/clean_complex.adoc"); + } + + @Test + void customConfigBehavior() { + AdocfmtConfig config = new AdocfmtConfig(); + config.ensureHeadingBlankLines = false; + + FormatterStep step = AdocfmtStep.create(AdocfmtStep.defaultVersion(), TestProvisioner.mavenCentral(), config); + + StepHarness.forStep(step).testResource("asciidoc/adocfmt/dirty.adoc", "asciidoc/adocfmt/clean_custom.adoc"); + } + + @Test + void equality() { + new SerializableEqualityTester() { + // fields drive create(); never mutate a config object after passing it to create() + boolean titleCase = false; + boolean normalizeListBullets = false; + + @Override + protected void setupTest(API api) { + // default config == same + api.areDifferentThan(); + // change one config option -> different + titleCase = true; + api.areDifferentThan(); + // change another config option -> different + titleCase = false; + normalizeListBullets = true; + api.areDifferentThan(); + } + + @Override + protected FormatterStep create() { + AdocfmtConfig config = new AdocfmtConfig(); + config.titleCase = titleCase; + config.normalizeListBullets = normalizeListBullets; + return AdocfmtStep.create(AdocfmtStep.defaultVersion(), TestProvisioner.mavenCentral(), config); + } + }.testEquals(); + } +} From a6a4b3b12620a2127bf584f5f50bb19911c2607e Mon Sep 17 00:00:00 2001 From: Daniel Heid Date: Thu, 4 Jun 2026 20:41:39 +0200 Subject: [PATCH 2/4] Add pull request links to docs --- CHANGES.md | 2 +- plugin-gradle/CHANGES.md | 2 +- plugin-maven/CHANGES.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 8ebdac1e2b..3bb39603f6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,7 +11,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added -- Add support for AsciiDoc formatting via `adocfmt`. (#TODO-PR-LINK) +- Add support for AsciiDoc formatting via `adocfmt`. ([#2960](https://github.com/diffplug/spotless/pull/2960)) ### Fixed - Support `ktfmt` 0.63 and use its new builder API for formatting options to better avoid future breaking changes. ### Changes diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index a8db468ed7..6153cb7a63 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -5,7 +5,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added -- Add support for AsciiDoc formatting via `adocfmt`. (#TODO-PR-LINK) +- Add support for AsciiDoc formatting via `adocfmt`. ([#2960](https://github.com/diffplug/spotless/pull/2960)) ### Fixed - Prevent build caches from interfering when executing under the `-PspotlessIdeHook` mode. ([#2365](https://github.com/diffplug/spotless/issues/2365)) ### Changes diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index a54d68f5dd..dfdc2eedfd 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -5,7 +5,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added -- Add support for AsciiDoc formatting via `adocfmt`. (#TODO-PR-LINK) +- Add support for AsciiDoc formatting via `adocfmt`. ([#2960](https://github.com/diffplug/spotless/pull/2960)) ## [3.6.0] - 2026-05-27 ### Added From 500e56eb30bb8c396c6cdef75e98fcbf638ae4ca Mon Sep 17 00:00:00 2001 From: Daniel Heid Date: Thu, 4 Jun 2026 20:55:57 +0200 Subject: [PATCH 3/4] Fix little mistakes --- plugin-gradle/README.md | 2 +- .../java/com/diffplug/gradle/spotless/AsciidocExtension.java | 2 +- .../java/com/diffplug/gradle/spotless/SpotlessExtension.java | 3 +-- plugin-maven/README.md | 1 - .../java/com/diffplug/spotless/maven/asciidoc/Asciidoc.java | 2 +- 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index a9f1140e51..5bf981d550 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -838,7 +838,7 @@ antlr4formatter('1.2.1') // version is optional ```gradle spotless { asciidoc { - target '**/*.adoc', '**/*.asciidoc', '**/*.asc' // default value, you can change if you want + target '**/*.adoc', '**/*.asciidoc' // default value, you can change if you want adocfmt() // has its own section below } } diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AsciidocExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AsciidocExtension.java index d6783ac524..f939ff3aff 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AsciidocExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AsciidocExtension.java @@ -117,7 +117,7 @@ public AdocfmtFormatterConfig ensureSourceDelimiters(boolean ensureSourceDelimit @Override protected void setupTask(SpotlessTask task) { if (target == null) { - target = parseTarget(List.of("**/*.adoc", "**/*.asciidoc", "**/*.asc")); + target = parseTarget(List.of("**/*.adoc", "**/*.asciidoc")); } super.setupTask(task); } diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java index b1764933b4..83c317f7e7 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java @@ -228,7 +228,7 @@ public void yaml(Action closure) { format(YamlExtension.NAME, YamlExtension.class, closure); } - /** Configures the special gherkin-specific extension. */ + /** Configures the special Gherkin-specific extension. */ public void gherkin(Action closure) { requireNonNull(closure); format(GherkinExtension.NAME, GherkinExtension.class, closure); @@ -241,7 +241,6 @@ public void asciidoc(Action closure) { } public void toml(Action closure) { - requireNonNull(closure); format(TomlExtension.NAME, TomlExtension.class, closure); } diff --git a/plugin-maven/README.md b/plugin-maven/README.md index 950e2e624a..b4903a377b 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -716,7 +716,6 @@ Additionally, `editorConfigOverride` options will override what's supplied in `. **/*.adoc **/*.asciidoc - **/*.asc diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Asciidoc.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Asciidoc.java index c4734f2ecb..b923cf0af2 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Asciidoc.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Asciidoc.java @@ -24,7 +24,7 @@ public class Asciidoc extends FormatterFactory { @Override public Set defaultIncludes(MavenProject project) { - return Set.of("**/*.adoc", "**/*.asciidoc", "**/*.asc"); + return Set.of("**/*.adoc", "**/*.asciidoc"); } @Override From 9bbf1b5897eaadeba2ae2a7d8003609332c3d89a Mon Sep 17 00:00:00 2001 From: Daniel Heid Date: Fri, 5 Jun 2026 11:04:55 +0200 Subject: [PATCH 4/4] Require user to specify the target for AsciiDoc formatting --- .../spotless/asciidoc/AdocfmtStep.java | 2 +- plugin-gradle/README.md | 5 +++-- .../gradle/spotless/AsciidocExtension.java | 4 +--- .../spotless/AsciidocExtensionTest.java | 22 ++++++++++++++++++- plugin-maven/README.md | 8 +++---- .../spotless/maven/asciidoc/Asciidoc.java | 3 ++- .../maven/asciidoc/AdocfmtMavenTest.java | 15 ++++++++++++- 7 files changed, 45 insertions(+), 14 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/asciidoc/AdocfmtStep.java b/lib/src/main/java/com/diffplug/spotless/asciidoc/AdocfmtStep.java index b2898c79d4..0072a46b8e 100644 --- a/lib/src/main/java/com/diffplug/spotless/asciidoc/AdocfmtStep.java +++ b/lib/src/main/java/com/diffplug/spotless/asciidoc/AdocfmtStep.java @@ -30,7 +30,7 @@ public final class AdocfmtStep implements Serializable { @Serial private static final long serialVersionUID = 1L; - private static final String DEFAULT_VERSION = "0.1.2"; + private static final String DEFAULT_VERSION = "0.2.0"; private static final String NAME = "adocfmt"; private static final String MAVEN_COORDINATE = "org.drjekyll:adocfmt:"; diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index 5bf981d550..be5451276f 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -838,7 +838,8 @@ antlr4formatter('1.2.1') // version is optional ```gradle spotless { asciidoc { - target '**/*.adoc', '**/*.asciidoc' // default value, you can change if you want + target 'src/docs/**/*.adoc' // you have to set the target manually + adocfmt() // has its own section below } } @@ -849,7 +850,7 @@ spotless { [homepage](https://github.com/dheid/adocfmt). [available versions](https://search.maven.org/artifact/org.drjekyll/adocfmt). ```gradle -adocfmt('0.1.2') // version is optional +adocfmt('0.2.0') // version is optional .normalizeSetextHeadings(false) // convert === underlines to ATX == (default: false) .collapseConsecutiveBlankLines(true) // max 1 blank line (default: true) .oneSentencePerLine(false) // each sentence on its own line (default: false) diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AsciidocExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AsciidocExtension.java index f939ff3aff..cf8f3c883f 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AsciidocExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AsciidocExtension.java @@ -15,8 +15,6 @@ */ package com.diffplug.gradle.spotless; -import java.util.List; - import javax.inject.Inject; import com.diffplug.spotless.asciidoc.AdocfmtConfig; @@ -117,7 +115,7 @@ public AdocfmtFormatterConfig ensureSourceDelimiters(boolean ensureSourceDelimit @Override protected void setupTask(SpotlessTask task) { if (target == null) { - target = parseTarget(List.of("**/*.adoc", "**/*.asciidoc")); + throw noDefaultTargetException(); } super.setupTask(task); } diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/AsciidocExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/AsciidocExtensionTest.java index c312513d06..2025de9b78 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/AsciidocExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/AsciidocExtensionTest.java @@ -17,9 +17,29 @@ import java.io.IOException; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; class AsciidocExtensionTest extends GradleIntegrationHarness { + @Test + void missingTargetFails() throws IOException { + setFile("build.gradle").toContent( + """ + plugins { + id 'com.diffplug.spotless' + } + repositories { mavenCentral() } + spotless { + asciidoc { + adocfmt('0.2.0') + } + } + """); + String output = gradleRunner().withArguments("spotlessApply").buildAndFail().getOutput(); + Assertions.assertThat(output).contains("no target set"); + Assertions.assertThat(output).contains("asciidoc"); + } + @Test void integration() throws IOException { setFile("build.gradle") @@ -32,7 +52,7 @@ void integration() throws IOException { spotless { asciidoc { target 'test.adoc' - adocfmt('0.1.2') + adocfmt('0.2.0') .normalizeSetextHeadings(true) .collapseConsecutiveBlankLines(true) .oneSentencePerLine(true) diff --git a/plugin-maven/README.md b/plugin-maven/README.md index b4903a377b..fa06738721 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -712,10 +712,8 @@ Additionally, `editorConfigOverride` options will override what's supplied in `. ```xml - - - **/*.adoc - **/*.asciidoc + + src/docs/**/*.adoc @@ -729,7 +727,7 @@ Additionally, `editorConfigOverride` options will override what's supplied in `. ```xml - 0.1.2 + 0.2.0 true true true diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Asciidoc.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Asciidoc.java index b923cf0af2..67d38a7852 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Asciidoc.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/asciidoc/Asciidoc.java @@ -15,6 +15,7 @@ */ package com.diffplug.spotless.maven.asciidoc; +import java.util.Collections; import java.util.Set; import org.apache.maven.project.MavenProject; @@ -24,7 +25,7 @@ public class Asciidoc extends FormatterFactory { @Override public Set defaultIncludes(MavenProject project) { - return Set.of("**/*.adoc", "**/*.asciidoc"); + return Collections.emptySet(); } @Override diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/asciidoc/AdocfmtMavenTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/asciidoc/AdocfmtMavenTest.java index f39c3dac7b..87926e0be3 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/asciidoc/AdocfmtMavenTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/asciidoc/AdocfmtMavenTest.java @@ -15,17 +15,30 @@ */ package com.diffplug.spotless.maven.asciidoc; +import static org.assertj.core.api.Assertions.assertThat; + import org.junit.jupiter.api.Test; +import com.diffplug.spotless.ProcessRunner; import com.diffplug.spotless.maven.MavenIntegrationHarness; public class AdocfmtMavenTest extends MavenIntegrationHarness { + @Test + public void missingIncludesFails() throws Exception { + writePom(groupWithSteps("asciidoc", + "", + " 0.2.0", + "")); + ProcessRunner.Result result = mavenRunner().withArguments("spotless:apply").runHasError(); + assertThat(result.stdOutUtf8()).contains("You must specify some files to include"); + } + @Test public void testAdocfmt() throws Exception { writePomWithAsciidocSteps( """ - 0.1.2 + 0.2.0 true true true