Add AsciidoctorJ 1.6 and 2.0 compatibility

AsciidoctorJ 1.6 is not backwards compatible with AsciidoctorJ 1.5
and AsciidoctorJ 2.0 is not backwards compatible with AsciidoctorJ 1.6
or 1.5. The backwards incompatibilities are such that they cannot be
worked around using reflection so code needs to be compiled against
each of the three versions. To this end, this commit splits
spring-restdocs-asciidoctor into several separate modules:

1. spring-restdocs-asciidoctor-support
2. spring-restdocs-asciidoctor-1.5
3. spring-restdocs-asciidoctor-1.6
4. spring-restdocs-asciidoctor-2.0

spring-restdocs-asciidoctor-support contains support code that is not
tied to a specific version of AsciidoctorJ and can be used with
1.5, 1.6 and 2.0. The other three modules contain code that is
specific to a particular version of AsciidoctorJ. Each
version-specific module uses class names that are unique across all
three modules and is written in such a way that they will back off
when used in an environment with a different version of AsciidoctorJ.
The existing spring-restdocs-asciidoctor module has been modified to
merge the version specific jars and the support jar together into a
single jar that supports AsciidoctorJ 1.5, 1.6, and 2.0.

The above-described changes should allow users to depend upon
spring-restdocs-asciidoctor as before and to now be able to use
AsciidoctorJ 1.5, 1.6, or 2.0.

Closes gh-581
This commit is contained in:
Andy Wilkinson
2019-06-18 12:03:42 +01:00
parent 00da0834df
commit ff18f8034d
23 changed files with 427 additions and 69 deletions

View File

@@ -83,7 +83,6 @@ subprojects {
dependency 'io.rest-assured:rest-assured:3.0.7'
dependency 'org.apache.pdfbox:pdfbox:2.0.7'
dependency 'org.assertj:assertj-core:2.9.1'
dependency 'org.asciidoctor:asciidoctorj:1.5.8.1'
dependency 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.16'
dependency 'org.hamcrest:hamcrest-core:1.3'
dependency 'org.hamcrest:hamcrest-library:1.3'
@@ -123,27 +122,12 @@ subprojects {
}
configure(subprojects - project(":docs")) { subproject ->
def codeProjects = subprojects - project(":docs")
configure(codeProjects) {
apply plugin: 'io.spring.javaformat'
apply plugin: 'checkstyle'
apply from: "${rootProject.projectDir}/gradle/publish-maven.gradle"
if (project.hasProperty('platformVersion') && subproject.path != ':spring-restdocs-asciidoctor') {
apply plugin: 'spring-io'
repositories {
maven { url "https://repo.spring.io/libs-snapshot" }
}
dependencyManagement {
springIoTestRuntime {
imports {
mavenBom "io.spring.platform:platform-bom:${platformVersion}"
}
}
}
}
checkstyle {
configFile = rootProject.file('config/checkstyle/checkstyle.xml')
configProperties = [ 'checkstyle.config.dir' : rootProject.file('config/checkstyle') ]
@@ -158,7 +142,10 @@ configure(subprojects - project(":docs")) { subproject ->
checkstyle "io.spring.javaformat:spring-javaformat-checkstyle:$javaFormatVersion"
jacoco 'org.jacoco:org.jacoco.agent::runtime'
}
}
def publishedCodeProjects = codeProjects.findAll { codeProject -> !codeProject.name.contains('spring-restdocs-asciidoctor')}
configure(publishedCodeProjects) { subproject ->
javadoc {
description = "Generates project-level javadoc for use in -javadoc jar"
options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
@@ -243,8 +230,7 @@ task api (type: Javadoc) {
options.links = javadocLinks
options.addStringOption '-quiet'
source subprojects.findAll { project -> project.path != ":spring-restdocs-asciidoctor" }
.collect { project -> project.sourceSets.main.allJava }
source publishedCodeProjects.collect { project -> project.sourceSets.main.allJava }
destinationDir = new File(buildDir, "api")

View File

@@ -1,3 +1,6 @@
version=2.0.4.BUILD-SNAPSHOT
javaFormatVersion=0.0.7-SNAPSHOT
org.gradle.daemon=false
asciidoctorj15Version=1.5.8.1
asciidoctorj16Version=1.6.2
asciidoctorj20Version=2.0.0-RC.3

View File

@@ -2,6 +2,10 @@ rootProject.name = 'spring-restdocs'
include 'docs'
include 'spring-restdocs-asciidoctor'
include 'spring-restdocs-asciidoctor-1.5'
include 'spring-restdocs-asciidoctor-1.6'
include 'spring-restdocs-asciidoctor-2.0'
include 'spring-restdocs-asciidoctor-support'
include 'spring-restdocs-core'
include 'spring-restdocs-mockmvc'
include 'spring-restdocs-restassured'

View File

@@ -0,0 +1,10 @@
description = 'AsciidoctorJ 1.5 extensions for Spring REST Docs'
dependencies {
compileOnly "org.asciidoctor:asciidoctorj:$asciidoctorj15Version"
implementation project(':spring-restdocs-asciidoctor-support')
testCompile 'junit:junit'
testCompile "org.asciidoctor:asciidoctorj:$asciidoctorj15Version"
testCompile 'org.assertj:assertj-core'
testRuntime project(':spring-restdocs-asciidoctor-support')
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 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.
@@ -26,7 +26,7 @@ import org.asciidoctor.extension.PreprocessorReader;
*
* @author Andy Wilkinson
*/
final class DefaultAttributesPreprocessor extends Preprocessor {
final class DefaultAttributesAsciidoctorJ15Preprocessor extends Preprocessor {
private final SnippetsDirectoryResolver snippetsDirectoryResolver = new SnippetsDirectoryResolver();

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2014-2019 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 org.springframework.restdocs.asciidoctor;
import org.asciidoctor.Asciidoctor;
import org.asciidoctor.extension.spi.ExtensionRegistry;
/**
* AsciidoctorJ 1.5 {@link ExtensionRegistry} for Spring REST Docs.
*
* @author Andy Wilkinson
*/
public final class RestDocsAsciidoctorJ15ExtensionRegistry implements ExtensionRegistry {
@Override
public void register(Asciidoctor asciidoctor) {
if (!asciidoctorJ15()) {
return;
}
asciidoctor.javaExtensionRegistry()
.preprocessor(new DefaultAttributesAsciidoctorJ15Preprocessor());
asciidoctor.rubyExtensionRegistry()
.loadClass(RestDocsAsciidoctorJ15ExtensionRegistry.class
.getResourceAsStream("/extensions/operation_block_macro.rb"))
.blockMacro("operation", "OperationBlockMacro");
}
private boolean asciidoctorJ15() {
try {
return !Class.forName("org.asciidoctor.extension.JavaExtensionRegistry")
.isInterface();
}
catch (Throwable ex) {
return false;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 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.
@@ -26,36 +26,45 @@ import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link DefaultAttributesPreprocessor}.
* Tests for {@link DefaultAttributesAsciidoctorJ15Preprocessor}.
*
* @author Andy Wilkinson
*/
public class DefaultAttributesPreprocessorTests {
public class DefaultAttributesAsciidoctorJ15PreprocessorTests {
@Test
public void snippetsAttributeIsSet() {
Options options = new Options();
options.setAttributes(new Attributes("projectdir=../../.."));
String converted = Asciidoctor.Factory.create().convert("{snippets}", options);
String converted = createAsciidoctor().convert("{snippets}",
createOptions("projectdir=../../.."));
assertThat(converted)
.contains("build" + File.separatorChar + "generated-snippets");
}
@Test
public void snippetsAttributeFromConvertArgumentIsNotOverridden() {
Options options = new Options();
options.setAttributes(new Attributes("snippets=custom projectdir=../../.."));
String converted = Asciidoctor.Factory.create().convert("{snippets}", options);
String converted = createAsciidoctor().convert("{snippets}",
createOptions("snippets=custom projectdir=../../.."));
assertThat(converted).contains("custom");
}
@Test
public void snippetsAttributeFromDocumentPreambleIsNotOverridden() {
Options options = new Options();
options.setAttributes(new Attributes("projectdir=../../.."));
String converted = Asciidoctor.Factory.create()
.convert(":snippets: custom\n{snippets}", options);
String converted = createAsciidoctor().convert(":snippets: custom\n{snippets}",
createOptions("projectdir=../../.."));
assertThat(converted).contains("custom");
}
private Options createOptions(String attributes) {
Options options = new Options();
options.setAttributes(new Attributes(attributes));
return options;
}
private Asciidoctor createAsciidoctor() {
Asciidoctor asciidoctor = Asciidoctor.Factory.create();
asciidoctor.javaExtensionRegistry()
.preprocessor(new DefaultAttributesAsciidoctorJ15Preprocessor());
return asciidoctor;
}
}

View File

@@ -0,0 +1,10 @@
description = 'AsciidoctorJ 1.6 extensions for Spring REST Docs'
dependencies {
compileOnly "org.asciidoctor:asciidoctorj:$asciidoctorj16Version"
implementation project(':spring-restdocs-asciidoctor-support')
testCompile 'junit:junit'
testCompile "org.asciidoctor:asciidoctorj:$asciidoctorj16Version"
testCompile 'org.assertj:assertj-core'
testRuntime project(':spring-restdocs-asciidoctor-support')
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2014-2019 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 org.springframework.restdocs.asciidoctor;
import org.asciidoctor.ast.Document;
import org.asciidoctor.extension.Preprocessor;
import org.asciidoctor.extension.PreprocessorReader;
/**
* {@link Preprocessor} that sets defaults for REST Docs-related {@link Document}
* attributes.
*
* @author Andy Wilkinson
*/
final class DefaultAttributesAsciidoctorJ16Preprocessor extends Preprocessor {
private final SnippetsDirectoryResolver snippetsDirectoryResolver = new SnippetsDirectoryResolver();
@Override
public void process(Document document, PreprocessorReader reader) {
document.setAttribute("snippets", this.snippetsDirectoryResolver
.getSnippetsDirectory(document.getAttributes()), false);
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2014-2019 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 org.springframework.restdocs.asciidoctor;
import org.asciidoctor.Asciidoctor;
import org.asciidoctor.extension.spi.ExtensionRegistry;
/**
* AsciidoctorJ 1.6 {@link ExtensionRegistry} for Spring REST Docs.
*
* @author Andy Wilkinson
*/
public final class RestDocsAsciidoctorJ16ExtensionRegistry implements ExtensionRegistry {
@Override
public void register(Asciidoctor asciidoctor) {
if (!asciidoctorJ16()) {
return;
}
asciidoctor.javaExtensionRegistry()
.preprocessor(new DefaultAttributesAsciidoctorJ16Preprocessor());
asciidoctor.rubyExtensionRegistry()
.loadClass(RestDocsAsciidoctorJ16ExtensionRegistry.class
.getResourceAsStream("/extensions/operation_block_macro.rb"))
.blockMacro("operation", "OperationBlockMacro");
}
private boolean asciidoctorJ16() {
try {
return Class.forName("org.asciidoctor.extension.JavaExtensionRegistry")
.isInterface();
}
catch (Throwable ex) {
return false;
}
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2014-2019 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 org.springframework.restdocs.asciidoctor;
import java.io.File;
import org.asciidoctor.Asciidoctor;
import org.asciidoctor.Attributes;
import org.asciidoctor.Options;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link DefaultAttributesAsciidoctorJ16Preprocessor}.
*
* @author Andy Wilkinson
*/
public class DefaultAttributesAsciidoctorJ16PreprocessorTests {
@Test
public void snippetsAttributeIsSet() {
String converted = createAsciidoctor().convert("{snippets}",
createOptions("projectdir=../../.."));
assertThat(converted)
.contains("build" + File.separatorChar + "generated-snippets");
}
@Test
public void snippetsAttributeFromConvertArgumentIsNotOverridden() {
String converted = createAsciidoctor().convert("{snippets}",
createOptions("snippets=custom projectdir=../../.."));
assertThat(converted).contains("custom");
}
@Test
public void snippetsAttributeFromDocumentPreambleIsNotOverridden() {
String converted = createAsciidoctor().convert(":snippets: custom\n{snippets}",
createOptions("projectdir=../../.."));
assertThat(converted).contains("custom");
}
private Options createOptions(String attributes) {
Options options = new Options();
options.setAttributes(new Attributes(attributes));
return options;
}
private Asciidoctor createAsciidoctor() {
Asciidoctor asciidoctor = Asciidoctor.Factory.create();
asciidoctor.javaExtensionRegistry()
.preprocessor(new DefaultAttributesAsciidoctorJ16Preprocessor());
return asciidoctor;
}
}

View File

@@ -0,0 +1,10 @@
description = 'AsciidoctorJ 2.0 extensions for Spring REST Docs'
dependencies {
compileOnly "org.asciidoctor:asciidoctorj:$asciidoctorj20Version"
implementation project(':spring-restdocs-asciidoctor-support')
testCompile 'junit:junit'
testCompile "org.asciidoctor:asciidoctorj:$asciidoctorj15Version"
testCompile 'org.assertj:assertj-core'
testRuntime project(':spring-restdocs-asciidoctor-support')
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2014-2019 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 org.springframework.restdocs.asciidoctor;
import org.asciidoctor.ast.Document;
import org.asciidoctor.extension.Preprocessor;
import org.asciidoctor.extension.PreprocessorReader;
/**
* {@link Preprocessor} that sets defaults for REST Docs-related {@link Document}
* attributes.
*
* @author Andy Wilkinson
*/
final class DefaultAttributesAsciidoctorJ20Preprocessor extends Preprocessor {
private final SnippetsDirectoryResolver snippetsDirectoryResolver = new SnippetsDirectoryResolver();
@Override
public void process(Document document, PreprocessorReader reader) {
document.setAttribute("snippets", this.snippetsDirectoryResolver
.getSnippetsDirectory(document.getAttributes()), false);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 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.
@@ -17,24 +17,23 @@
package org.springframework.restdocs.asciidoctor;
import org.asciidoctor.Asciidoctor;
import org.asciidoctor.extension.spi.ExtensionRegistry;
import org.asciidoctor.jruby.extension.spi.ExtensionRegistry;
/**
* Asciidoctor {@link ExtensionRegistry} for Spring REST Docs.
* AsciidoctorJ 2.0 {@link ExtensionRegistry} for Spring REST Docs.
*
* @author Andy Wilkinson
*/
public final class RestDocsExtensionRegistry implements ExtensionRegistry {
public final class RestDocsAsciidoctorJ20ExtensionRegistry implements ExtensionRegistry {
@Override
public void register(Asciidoctor asciidoctor) {
asciidoctor.javaExtensionRegistry()
.preprocessor(new DefaultAttributesPreprocessor());
.preprocessor(new DefaultAttributesAsciidoctorJ20Preprocessor());
asciidoctor.rubyExtensionRegistry()
.loadClass(RestDocsExtensionRegistry.class
.loadClass(RestDocsAsciidoctorJ20ExtensionRegistry.class
.getResourceAsStream("/extensions/operation_block_macro.rb"))
.blockMacro("operation", "OperationBlockMacro");
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2014-2019 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 org.springframework.restdocs.asciidoctor;
import java.io.File;
import org.asciidoctor.Asciidoctor;
import org.asciidoctor.Attributes;
import org.asciidoctor.Options;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link DefaultAttributesAsciidoctorJ20Preprocessor}.
*
* @author Andy Wilkinson
*/
public class DefaultAttributesAsciidoctorJ20PreprocessorTests {
@Test
public void snippetsAttributeIsSet() {
String converted = createAsciidoctor().convert("{snippets}",
createOptions("projectdir=../../.."));
assertThat(converted)
.contains("build" + File.separatorChar + "generated-snippets");
}
@Test
public void snippetsAttributeFromConvertArgumentIsNotOverridden() {
String converted = createAsciidoctor().convert("{snippets}",
createOptions("snippets=custom projectdir=../../.."));
assertThat(converted).contains("custom");
}
@Test
public void snippetsAttributeFromDocumentPreambleIsNotOverridden() {
String converted = createAsciidoctor().convert(":snippets: custom\n{snippets}",
createOptions("projectdir=../../.."));
assertThat(converted).contains("custom");
}
private Options createOptions(String attributes) {
Options options = new Options();
options.setAttributes(new Attributes(attributes));
return options;
}
private Asciidoctor createAsciidoctor() {
Asciidoctor asciidoctor = Asciidoctor.Factory.create();
asciidoctor.javaExtensionRegistry()
.preprocessor(new DefaultAttributesAsciidoctorJ20Preprocessor());
return asciidoctor;
}
}

View File

@@ -0,0 +1,6 @@
description = 'Support code for AsciidoctorJ extensions for Spring REST Docs'
dependencies {
testCompile 'junit:junit'
testCompile 'org.assertj:assertj-core'
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.

View File

@@ -1,11 +1,28 @@
description = 'Asciidoctor extensions for Spring REST Docs'
configurations {
merge
testRuntime { extendsFrom merge }
}
dependencies {
provided 'org.asciidoctor:asciidoctorj'
testCompile 'junit:junit'
merge project(':spring-restdocs-asciidoctor-1.5')
merge project(':spring-restdocs-asciidoctor-1.6')
merge project(':spring-restdocs-asciidoctor-2.0')
testCompile 'org.apache.pdfbox:pdfbox'
testCompile 'org.asciidoctor:asciidoctorj'
testCompile 'org.asciidoctor:asciidoctorj:1.5.8.1'
testCompile 'org.assertj:assertj-core'
testCompile 'junit:junit'
testCompile 'org.springframework:spring-core'
testRuntime 'org.asciidoctor:asciidoctorj-pdf'
}
jar {
from configurations.merge.collect { file -> zipTree(file) }
}
matrixTest {
asciidoctorj {
group = 'org.asciidoctor'
artifact = 'asciidoctorj'
versions = [ asciidoctorj16Version, asciidoctorj20Version ]
}
}

View File

@@ -1,20 +0,0 @@
/*
* Copyright 2014-2016 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.
*/
/**
* Spring REST Docs Asciidoctor extensions.
*/
package org.springframework.restdocs.asciidoctor;

View File

@@ -1 +1,2 @@
org.springframework.restdocs.asciidoctor.RestDocsExtensionRegistry
org.springframework.restdocs.asciidoctor.RestDocsAsciidoctorJ15ExtensionRegistry
org.springframework.restdocs.asciidoctor.RestDocsAsciidoctorJ16ExtensionRegistry

View File

@@ -0,0 +1 @@
org.springframework.restdocs.asciidoctor.RestDocsAsciidoctorJ20ExtensionRegistry