Remove Asciidoctor from the build in favor of Antora

This commit is contained in:
Rob Winch 2021-09-02 14:38:19 -05:00
parent 871bc1c42c
commit be9ff16583
23 changed files with 4 additions and 472 deletions

View File

@ -76,13 +76,9 @@ dependencies {
implementation 'gradle.plugin.org.gretty:gretty:3.0.1'
implementation 'com.apollographql.apollo:apollo-runtime:2.4.5'
implementation 'com.github.ben-manes:gradle-versions-plugin:0.38.0'
implementation 'io.spring.gradle:docbook-reference-plugin:0.3.1'
implementation 'io.spring.gradle:propdeps-plugin:0.0.10.RELEASE'
implementation 'io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.15'
implementation 'io.spring.nohttp:nohttp-gradle:0.0.10'
implementation 'org.aim42:htmlSanityCheck:1.1.6'
implementation 'org.asciidoctor:asciidoctor-gradle-jvm:3.1.0'
implementation 'org.asciidoctor:asciidoctor-gradle-jvm-pdf:3.1.0'
implementation 'org.hidetake:gradle-ssh-plugin:2.10.1'
implementation 'org.jfrog.buildinfo:build-info-extractor-gradle:4.9.10'
implementation 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'

View File

@ -1,12 +1,9 @@
package io.spring.gradle.convention
import org.aim42.htmlsanitycheck.HtmlSanityCheckPlugin
import org.aim42.htmlsanitycheck.HtmlSanityCheckTask
import org.aim42.htmlsanitycheck.check.BrokenHttpLinksChecker
import org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.PluginManager
import org.gradle.api.tasks.bundling.Zip
@ -19,54 +16,18 @@ public class DocsPlugin implements Plugin<Project> {
public void apply(Project project) {
PluginManager pluginManager = project.getPluginManager();
pluginManager.apply("org.asciidoctor.jvm.convert");
pluginManager.apply("org.asciidoctor.jvm.pdf");
pluginManager.apply(AsciidoctorConventionPlugin);
pluginManager.apply(BasePlugin);
pluginManager.apply(DeployDocsPlugin);
pluginManager.apply(JavadocApiPlugin);
pluginManager.apply(HtmlSanityCheckPlugin)
String projectName = Utils.getProjectName(project);
String pdfFilename = projectName + "-reference.pdf";
project.tasks.withType(AbstractAsciidoctorTask) { t ->
project.configure(t) {
sources {
include "**/*.adoc"
exclude '_*/**'
}
}
}
project.tasks.withType(HtmlSanityCheckTask) { HtmlSanityCheckTask t ->
project.configure(t) {
t.dependsOn 'asciidoctor'
t.checkerClasses = [BrokenHttpLinksChecker]
t.checkingResultsDir = new File(project.getBuildDir(), "/report/htmlchecks")
t.failOnErrors = false
t.httpConnectionTimeout = 3000
t.sourceDir = new File(project.getBuildDir(), "/docs/asciidoc/")
t.sourceDocuments = project.files(new File(project.getBuildDir(), "/docs/asciidoc/index.html"))
}
}
Task docsZip = project.tasks.create('docsZip', Zip) {
dependsOn 'api', 'asciidoctor'
dependsOn 'api'
group = 'Distribution'
archiveBaseName = project.rootProject.name
archiveClassifier = 'docs'
description = "Builds -${classifier} archive containing all " +
"Docs for deployment at docs.spring.io"
from(project.tasks.asciidoctor.outputs) {
into 'reference/html5'
include '**'
}
from(project.tasks.asciidoctorPdf.outputs) {
into 'reference/pdf'
include '**'
rename "index.pdf", pdfFilename
}
from(project.tasks.api.outputs) {
into 'api'
}

View File

@ -1,208 +0,0 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* 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
*
* https://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 io.spring.gradle.convention;
import org.asciidoctor.gradle.base.AsciidoctorAttributeProvider;
import org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask;
import org.asciidoctor.gradle.jvm.AsciidoctorJExtension;
import org.asciidoctor.gradle.jvm.AsciidoctorJPlugin;
import org.asciidoctor.gradle.jvm.AsciidoctorTask;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import org.gradle.api.file.CopySpec;
import org.gradle.api.file.FileTree;
import org.gradle.api.tasks.Sync;
import java.io.File;
import java.net.URI;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
/**
* Conventions that are applied in the presence of the {@link AsciidoctorJPlugin}. When
* the plugin is applied:
*
* <ul>
* <li>All warnings are made fatal.
* <li>A task is created to resolve and unzip our documentation resources (CSS and
* Javascript).
* <li>For each {@link AsciidoctorTask} (HTML only):
* <ul>
* <li>A configuration named asciidoctorExtensions is ued to add the
* <a href="https://github.com/spring-io/spring-asciidoctor-extensions#block-switch">block
* switch</a> extension
* <li>{@code doctype} {@link AsciidoctorTask#options(Map) option} is configured.
* <li>{@link AsciidoctorTask#attributes(Map) Attributes} are configured for syntax
* highlighting, CSS styling, docinfo, etc.
* </ul>
* <li>For each {@link AbstractAsciidoctorTask} (HTML and PDF):
* <ul>
* <li>{@link AsciidoctorTask#attributes(Map) Attributes} are configured to enable
* warnings for references to missing attributes, the year is added as @{code today-year},
* etc
* <li>{@link AbstractAsciidoctorTask#baseDirFollowsSourceDir() baseDirFollowsSourceDir()}
* is enabled.
* </ul>
* </ul>
*
* @author Andy Wilkinson
* @author Rob Winch
*/
public class AsciidoctorConventionPlugin implements Plugin<Project> {
public void apply(Project project) {
project.getPlugins().withType(AsciidoctorJPlugin.class, (asciidoctorPlugin) -> {
createDefaultAsciidoctorRepository(project);
makeAllWarningsFatal(project);
Sync unzipResources = createUnzipDocumentationResourcesTask(project);
project.getTasks().withType(AbstractAsciidoctorTask.class, (asciidoctorTask) -> {
asciidoctorTask.dependsOn(unzipResources);
configureExtensions(project, asciidoctorTask);
configureCommonAttributes(project, asciidoctorTask);
configureOptions(asciidoctorTask);
asciidoctorTask.baseDirFollowsSourceDir();
asciidoctorTask.useIntermediateWorkDir();
asciidoctorTask.resources(new Action<CopySpec>() {
@Override
public void execute(CopySpec resourcesSpec) {
resourcesSpec.from(unzipResources);
resourcesSpec.from(asciidoctorTask.getSourceDir(), new Action<CopySpec>() {
@Override
public void execute(CopySpec resourcesSrcDirSpec) {
// https://github.com/asciidoctor/asciidoctor-gradle-plugin/issues/523
// For now copy the entire sourceDir over so that include files are
// available in the intermediateWorkDir
// resourcesSrcDirSpec.include("images/**");
}
});
}
});
if (asciidoctorTask instanceof AsciidoctorTask) {
configureHtmlOnlyAttributes(project, asciidoctorTask);
}
});
});
}
private void createDefaultAsciidoctorRepository(Project project) {
project.getGradle().afterProject(new Action<Project>() {
@Override
public void execute(Project project) {
RepositoryHandler repositories = project.getRepositories();
if (repositories.isEmpty()) {
repositories.mavenCentral();
repositories.maven(repo -> {
repo.setUrl(URI.create("https://repo.spring.io/release"));
});
}
}
});
}
private void makeAllWarningsFatal(Project project) {
project.getExtensions().getByType(AsciidoctorJExtension.class).fatalWarnings(".*");
}
private void configureExtensions(Project project, AbstractAsciidoctorTask asciidoctorTask) {
Configuration extensionsConfiguration = project.getConfigurations().maybeCreate("asciidoctorExtensions");
extensionsConfiguration.defaultDependencies(new Action<DependencySet>() {
@Override
public void execute(DependencySet dependencies) {
dependencies.add(project.getDependencies().create("io.spring.asciidoctor:spring-asciidoctor-extensions-block-switch:0.4.2.RELEASE"));
}
});
asciidoctorTask.configurations(extensionsConfiguration);
}
private Sync createUnzipDocumentationResourcesTask(Project project) {
Configuration documentationResources = project.getConfigurations().maybeCreate("documentationResources");
documentationResources.getDependencies()
.add(project.getDependencies().create("io.spring.docresources:spring-doc-resources:0.2.5"));
Sync unzipResources = project.getTasks().create("unzipDocumentationResources",
Sync.class, new Action<Sync>() {
@Override
public void execute(Sync sync) {
sync.dependsOn(documentationResources);
sync.from(new Callable<List<FileTree>>() {
@Override
public List<FileTree> call() throws Exception {
List<FileTree> result = new ArrayList<>();
documentationResources.getAsFileTree().forEach(new Consumer<File>() {
@Override
public void accept(File file) {
result.add(project.zipTree(file));
}
});
return result;
}
});
File destination = new File(project.getBuildDir(), "docs/resources");
sync.into(project.relativePath(destination));
}
});
return unzipResources;
}
private void configureOptions(AbstractAsciidoctorTask asciidoctorTask) {
asciidoctorTask.options(Collections.singletonMap("doctype", "book"));
}
private void configureHtmlOnlyAttributes(Project project, AbstractAsciidoctorTask asciidoctorTask) {
Map<String, Object> attributes = new HashMap<>();
attributes.put("source-highlighter", "highlight.js");
attributes.put("highlightjsdir", "js/highlight");
attributes.put("highlightjs-theme", "github");
attributes.put("linkcss", true);
attributes.put("icons", "font");
attributes.put("stylesheet", "css/spring.css");
asciidoctorTask.getAttributeProviders().add(new AsciidoctorAttributeProvider() {
@Override
public Map<String, Object> getAttributes() {
Object version = project.getVersion();
Map<String, Object> attrs = new HashMap<>();
if (version != null && version.toString() != Project.DEFAULT_VERSION) {
attrs.put("revnumber", version);
}
return attrs;
}
});
asciidoctorTask.attributes(attributes);
}
private void configureCommonAttributes(Project project, AbstractAsciidoctorTask asciidoctorTask) {
Map<String, Object> attributes = new HashMap<>();
attributes.put("attribute-missing", "warn");
attributes.put("icons", "font");
attributes.put("idprefix", "");
attributes.put("idseparator", "-");
attributes.put("docinfo", "shared");
attributes.put("sectanchors", "");
attributes.put("sectnums", "");
attributes.put("today-year", LocalDate.now().getYear());
asciidoctorTask.attributes(attributes);
}
}

View File

@ -1,87 +0,0 @@
package io.spring.gradle.convention;
import io.spring.gradle.TestKit;
import org.codehaus.groovy.runtime.ResourceGroovyMethods;
import org.gradle.testkit.runner.BuildResult;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.File;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import static org.assertj.core.api.Assertions.assertThat;
import static org.gradle.testkit.runner.TaskOutcome.FAILED;
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS;
public class DocsPluginITest {
private TestKit testKit;
@BeforeEach
void setup(@TempDir Path tempDir) {
this.testKit = new TestKit(tempDir.toFile());
}
@Test
public void buildTriggersDocs() throws Exception {
BuildResult result = testKit.withProjectResource("samples/docs/simple/")
.withArguments("build")
.build();
assertThat(result.task(":build").getOutcome()).isEqualTo(SUCCESS);
assertThat(result.task(":docs").getOutcome()).isEqualTo(SUCCESS);
assertThat(result.task(":docsZip").getOutcome()).isEqualTo(SUCCESS);
File zip = new File(testKit.getRootDir(), "build/distributions/simple-1.0.0.BUILD-SNAPSHOT-docs.zip");
try (ZipFile file = new ZipFile(zip)) {
List<? extends ZipEntry> entries = Collections.list(file.entries());
assertThat(entries)
.extracting(ZipEntry::getName)
.contains("docs/reference/html5/index.html")
.contains("docs/reference/pdf/simple-reference.pdf");
}
}
@Test
public void asciidocCopiesImages() throws Exception {
BuildResult result = testKit.withProjectResource("samples/docs/simple/").withArguments("asciidoctor").build();
assertThat(result.task(":asciidoctor").getOutcome()).isEqualTo(SUCCESS);
assertThat(new File(testKit.getRootDir(), "build/docs/asciidoc/images")).exists();
}
@Test
public void asciidocDocInfoFromResourcesUsed() throws Exception {
BuildResult result = this.testKit.withProjectResource("samples/docs/simple/")
.withArguments("asciidoctor")
.build();
assertThat(result.task(":asciidoctor").getOutcome()).isEqualTo(SUCCESS);
assertThat(ResourceGroovyMethods.getText(new File(testKit.getRootDir(), "build/docs/asciidoc/index.html")))
.contains("<script type=\"text/javascript\" src=\"js/tocbot/tocbot.min.js\"></script>");
}
@Test
public void missingAttributeFails() throws Exception {
BuildResult result = this.testKit.withProjectResource("samples/docs/missing-attribute/")
.withArguments(":asciidoctor")
.buildAndFail();
assertThat(result.task(":asciidoctor").getOutcome()).isEqualTo(FAILED);
}
@Test
public void missingInclude() throws Exception {
BuildResult result = this.testKit.withProjectResource("samples/docs/missing-include/")
.withArguments(":asciidoctor")
.buildAndFail();
assertThat(result.task(":asciidoctor").getOutcome()).isEqualTo(FAILED);
}
@Test
public void missingCrossReference() throws Exception {
BuildResult result = this.testKit.withProjectResource("samples/docs/missing-cross-reference/")
.withArguments(":asciidoctor")
.buildAndFail();
assertThat(result.task(":asciidoctor").getOutcome()).isEqualTo(FAILED);
}
}

View File

@ -1,6 +0,0 @@
plugins {
id 'io.spring.convention.docs'
id 'java'
}
version = '1.0.0.BUILD-SNAPSHOT'

View File

@ -1 +0,0 @@
rootProject.name = 'simple'

View File

@ -1,3 +0,0 @@
= Example Manual
This will fail due to {missing} attribute

View File

@ -1,6 +0,0 @@
plugins {
id 'io.spring.convention.docs'
id 'java'
}
version = '1.0.0.BUILD-SNAPSHOT'

View File

@ -1 +0,0 @@
rootProject.name = 'missing-include'

View File

@ -1,3 +0,0 @@
= Example Manual
This will fail due to <<missing>> cross reference

View File

@ -1,6 +0,0 @@
plugins {
id 'io.spring.convention.docs'
id 'java'
}
version = '1.0.0.BUILD-SNAPSHOT'

View File

@ -1 +0,0 @@
rootProject.name = 'missing-include'

View File

@ -1,5 +0,0 @@
= Example Manual
This will fail due to missing include
include::missing.adoc[]

View File

@ -1,13 +0,0 @@
plugins {
id 'io.spring.convention.docs'
id 'java'
}
version = '1.0.0.BUILD-SNAPSHOT'
asciidoctorj {
attributes \
'build-gradle': project.buildFile,
'sourcedir': project.sourceSets.main.java.srcDirs[0],
'endpoint-url': 'https://example.org'
}

View File

@ -1 +0,0 @@
rootProject.name = 'simple'

View File

@ -1 +0,0 @@
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.js"></script>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

View File

@ -1,60 +0,0 @@
= Example Manual
Doc Writer <doc.writer@example.org>
2014-09-09
:example-caption!:
ifndef::imagesdir[:imagesdir: images]
ifndef::sourcedir[:sourcedir: ../java]
This is a user manual for an example project.
== Introduction
This project does something.
We just haven't decided what that is yet.
== Source Code
[source,java]
.Java code from project
----
include::{sourcedir}/example/StringUtils.java[tags=contains,indent=0]
----
This page was built by the following command:
$ ./gradlew asciidoctor
== Images
[.thumb]
image::sunset.jpg[scaledwidth=75%]
== Attributes
.Built-in
asciidoctor-version:: {asciidoctor-version}
safe-mode-name:: {safe-mode-name}
docdir:: {docdir}
docfile:: {docfile}
imagesdir:: {imagesdir}
revnumber:: {revnumber}
.Custom
sourcedir:: {sourcedir}
endpoint-url:: {endpoint-url}
== Includes
.include::subdir/_b.adoc[]
====
include::subdir/_b.adoc[]
====
WARNING: Includes can be tricky!
== build.gradle
[source,groovy]
----
include::{build-gradle}[]
----

View File

@ -1,7 +0,0 @@
content from _src/docs/asciidoc/subdir/_b.adoc_.
.include::_c.adoc[]
[example]
--
include::_c.adoc[]
--

View File

@ -1 +0,0 @@
content from _src/docs/asciidoc/subdir/c.adoc_.

View File

@ -1,9 +0,0 @@
package example;
public class StringUtils {
// tag::contains[]
public boolean contains(String haystack, String needle) {
return haystack.contains(needle);
}
// end::contains[]
}

View File

@ -2,10 +2,3 @@ apply plugin: 'java'
apply plugin: 'io.spring.convention.docs'
version = "1.0.0.BUILD-SNAPSHOT"
asciidoctorj {
attributes \
'build-gradle': project.buildFile,
'sourcedir': project.sourceSets.main.java.srcDirs[0],
'endpoint-url': 'https://example.org'
}

View File

@ -1,3 +1,4 @@
apply plugin: 'io.spring.convention.docs'
apply plugin: 'java'
tasks.register("generateAntora") {