Collapse Maven and Gradle setup into one section with switchable examples
This commit adds an Asciidoctor extension that post-processes code blocks, collapsing any secondary blocks into the preceding primary block. The primary block is then augmented with a switch. This switch contains one item for each block. Clicking an item causes the associated block’s content to be displayed. Each item is named using its block’s title. The getting started instructions have been updated to take advantage of this new switching support, with the Maven and Gradle instructions being collapsed into a single section. Closes gh-189
This commit is contained in:
7
buildSrc/build.gradle
Normal file
7
buildSrc/build.gradle
Normal file
@@ -0,0 +1,7 @@
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'org.asciidoctor:asciidoctorj:1.5.2'
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* 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 org.springframework.restdocs.asciidoctor
|
||||
|
||||
import org.asciidoctor.Asciidoctor
|
||||
import org.asciidoctor.extension.spi.ExtensionRegistry
|
||||
|
||||
class CodeBlockSwitchExtension implements ExtensionRegistry {
|
||||
|
||||
@Override
|
||||
public void register(Asciidoctor asciidoctor) {
|
||||
asciidoctor.javaExtensionRegistry().postprocessor(new CodeBlockSwitchPostProcessor());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2014-2015 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
|
||||
*
|
||||
* 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 org.springframework.restdocs.asciidoctor
|
||||
|
||||
import org.asciidoctor.ast.Document
|
||||
import org.asciidoctor.extension.Postprocessor
|
||||
|
||||
class CodeBlockSwitchPostProcessor extends Postprocessor {
|
||||
|
||||
String process(Document document, String output) {
|
||||
def css = getClass().getResource("/codeBlockSwitch.css").text
|
||||
def javascript = getClass().getResource("/codeBlockSwitch.js").text
|
||||
def replacement = """<style>
|
||||
$css
|
||||
</style>
|
||||
<script src=\"http://cdnjs.cloudflare.com/ajax/libs/zepto/1.1.6/zepto.min.js\"></script>
|
||||
<script type="text/javascript">
|
||||
$javascript
|
||||
</script>
|
||||
</head>
|
||||
"""
|
||||
return output.replace("</head>", replacement);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
org.springframework.restdocs.asciidoctor.CodeBlockSwitchExtension
|
||||
23
buildSrc/src/main/resources/codeBlockSwitch.css
Normal file
23
buildSrc/src/main/resources/codeBlockSwitch.css
Normal file
@@ -0,0 +1,23 @@
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.switch {
|
||||
border-width: 1px 1px 0 1px;
|
||||
border-style: solid;
|
||||
border-color: #7a2518;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.switch--item {
|
||||
padding: 10px;
|
||||
background-color: #ffffff;
|
||||
color: #7a2518;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.switch--item.selected {
|
||||
background-color: #7a2519;
|
||||
color: #ffffff;
|
||||
}
|
||||
45
buildSrc/src/main/resources/codeBlockSwitch.js
Normal file
45
buildSrc/src/main/resources/codeBlockSwitch.js
Normal file
@@ -0,0 +1,45 @@
|
||||
function addBlockSwitches() {
|
||||
$('.primary').each(function() {
|
||||
primary = $(this);
|
||||
createSwitchItem(primary, createBlockSwitch(primary)).item.addClass("selected");
|
||||
primary.children('.title').remove();
|
||||
});
|
||||
$('.secondary').each(function(idx, node) {
|
||||
secondary = $(node);
|
||||
primary = findPrimary(secondary);
|
||||
switchItem = createSwitchItem(secondary, primary.children('.switch'));
|
||||
switchItem.content.addClass('hidden');
|
||||
findPrimary(secondary).append(switchItem.content);
|
||||
secondary.remove();
|
||||
});
|
||||
}
|
||||
|
||||
function createBlockSwitch(primary) {
|
||||
blockSwitch = $('<div class="switch"></div>');
|
||||
primary.prepend(blockSwitch);
|
||||
return blockSwitch;
|
||||
}
|
||||
|
||||
function findPrimary(secondary) {
|
||||
candidate = secondary.prev();
|
||||
while (!candidate.is('.primary')) {
|
||||
candidate = candidate.prev();
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
|
||||
function createSwitchItem(block, blockSwitch) {
|
||||
blockName = block.children('.title').text();
|
||||
content = block.children('.content').first().append(block.next('.colist'));
|
||||
item = $('<div class="switch--item">' + blockName + '</div>');
|
||||
item.on('click', '', content, function(e) {
|
||||
$(this).addClass('selected');
|
||||
$(this).siblings().removeClass('selected');
|
||||
e.data.siblings('.content').addClass('hidden');
|
||||
e.data.removeClass('hidden');
|
||||
});
|
||||
blockSwitch.append(item);
|
||||
return {'item': item, 'content': content};
|
||||
}
|
||||
|
||||
$(addBlockSwitches);
|
||||
@@ -28,82 +28,14 @@ The code that produces the generated snippets can be found in `src/test/java`.
|
||||
[[getting-started-build-configuration]]
|
||||
=== Build configuration
|
||||
|
||||
The first step in using Spring REST Docs is to configure your project's build.
|
||||
The first step in using Spring REST Docs is to configure your project's build. The
|
||||
{samples}/rest-notes-spring-hateoas[Spring HATEOAS] and
|
||||
{samples}/rest-notes-spring-data-rest[Spring Data REST] samples contain a `build.gradle`
|
||||
and `pom.xml` respectively that you may wish to use as a reference. The key parts of
|
||||
the configuration are described below.
|
||||
|
||||
|
||||
|
||||
[[getting-started-build-configuration-gradle]]
|
||||
==== Gradle build configuration
|
||||
|
||||
The {samples}/rest-notes-spring-hateoas[Spring HATEOAS sample] contains a `build.gradle`
|
||||
file that you may wish to use as a reference. The key parts of the configuration are
|
||||
described below.
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim,attributes"]
|
||||
----
|
||||
plugins { <1>
|
||||
id "org.asciidoctor.convert" version "1.5.2"
|
||||
}
|
||||
|
||||
dependencies { <2>
|
||||
testCompile 'org.springframework.restdocs:spring-restdocs-mockmvc:{project-version}'
|
||||
}
|
||||
|
||||
ext { <3>
|
||||
snippetsDir = file('build/generated-snippets')
|
||||
}
|
||||
|
||||
test { <4>
|
||||
outputs.dir snippetsDir
|
||||
}
|
||||
|
||||
asciidoctor { <5>
|
||||
attributes 'snippets': snippetsDir <6>
|
||||
inputs.dir snippetsDir <7>
|
||||
dependsOn test <8>
|
||||
}
|
||||
----
|
||||
<1> Apply the Asciidoctor plugin.
|
||||
<2> Add a dependency on `spring-restdocs-mockmvc` in the `testCompile` configuration.
|
||||
<3> Configure a property to define the output location for generated snippets.
|
||||
<4> Configure the `test` task to add the snippets directory as an output.
|
||||
<5> Configure the `asciidoctor` task
|
||||
<6> Define an attribute named `snippets` that can be used when including the generated
|
||||
snippets in your documentation.
|
||||
<7> Configure the snippets directory as an input.
|
||||
<8> Make the task depend on the test task so that the tests are run before the
|
||||
documentation is created.
|
||||
|
||||
|
||||
[[getting-started-build-configuration-gradle-packaging-the-documentation]]
|
||||
==== Packaging the documentation
|
||||
|
||||
You may want to package the generated documentation in your project's jar file, for
|
||||
example to have it {spring-boot-docs}/#boot-features-spring-mvc-static-content[served as
|
||||
static content] by Spring Boot. You can do so by configuring the `jar` task to depend on
|
||||
the `asciidoctor` task and to copy the generated documentation into the jar's static
|
||||
directory:
|
||||
|
||||
[source,groovy,indent=0]
|
||||
----
|
||||
jar {
|
||||
dependsOn asciidoctor
|
||||
from ("${asciidoctor.outputDir}/html5") {
|
||||
into 'static/docs'
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[getting-started-build-configuration-maven]]
|
||||
==== Maven build configuration
|
||||
|
||||
The {samples}/rest-notes-spring-data-rest[Spring Data REST sample] contains a `pom.xml`
|
||||
file that you may wish to use as a reference. The key parts of the configuration are
|
||||
described below.
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,attributes"]
|
||||
[source,xml,indent=0,subs="verbatim,attributes",role="primary"]
|
||||
.Maven
|
||||
----
|
||||
<dependency> <1>
|
||||
<groupId>org.springframework.restdocs</groupId>
|
||||
@@ -150,7 +82,6 @@ described below.
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
----
|
||||
<1> Add a dependency on `spring-restdocs-mockmvc` in the `test` scope.
|
||||
<2> Configure a property to define the output location for generated snippets.
|
||||
@@ -163,19 +94,55 @@ described below.
|
||||
<<getting-started-build-configuration-maven-packaging, package the documentation>> in your
|
||||
project's jar you should use the `prepare-package` phase.
|
||||
|
||||
[[getting-started-build-configuration-maven-packaging]]
|
||||
[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"]
|
||||
.Gradle
|
||||
----
|
||||
plugins { <1>
|
||||
id "org.asciidoctor.convert" version "1.5.2"
|
||||
}
|
||||
|
||||
dependencies { <2>
|
||||
testCompile 'org.springframework.restdocs:spring-restdocs-mockmvc:{project-version}'
|
||||
}
|
||||
|
||||
ext { <3>
|
||||
snippetsDir = file('build/generated-snippets')
|
||||
}
|
||||
|
||||
test { <4>
|
||||
outputs.dir snippetsDir
|
||||
}
|
||||
|
||||
asciidoctor { <5>
|
||||
attributes 'snippets': snippetsDir <6>
|
||||
inputs.dir snippetsDir <7>
|
||||
dependsOn test <8>
|
||||
}
|
||||
----
|
||||
<1> Apply the Asciidoctor plugin.
|
||||
<2> Add a dependency on `spring-restdocs-mockmvc` in the `testCompile` configuration.
|
||||
<3> Configure a property to define the output location for generated snippets.
|
||||
<4> Configure the `test` task to add the snippets directory as an output.
|
||||
<5> Configure the `asciidoctor` task
|
||||
<6> Define an attribute named `snippets` that can be used when including the generated
|
||||
snippets in your documentation.
|
||||
<7> Configure the snippets directory as an input.
|
||||
<8> Make the task depend on the test task so that the tests are run before the
|
||||
documentation is created.
|
||||
|
||||
|
||||
[[getting-started-build-configuration-gradle-packaging-the-documentation]]
|
||||
==== Packaging the documentation
|
||||
|
||||
You may want to package the generated documentation in your project's jar file, for
|
||||
example to have it {spring-boot-docs}/#boot-features-spring-mvc-static-content[served as
|
||||
static content] by Spring Boot.
|
||||
static content] by Spring Boot. To do so, configure your project's build so that:
|
||||
|
||||
First, configure the Asciidoctor plugin so that it runs in the `prepare-package` phase, as
|
||||
<<getting-started-build-configuration-maven-plugin-phase, described above>>. Now configure
|
||||
Maven's resources plugin to copy the generated documentation into a location where it'll
|
||||
be included in the project's jar:
|
||||
1. The documentation is generated before the jar is built
|
||||
2. The generated documentation is included in the jar
|
||||
|
||||
[source,xml,indent=0]
|
||||
[source,xml,indent=0,role="primary",role="primary"]
|
||||
.Maven
|
||||
----
|
||||
<plugin> <1>
|
||||
<groupId>org.asciidoctor</groupId>
|
||||
@@ -192,7 +159,7 @@ be included in the project's jar:
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<configuration> <3>
|
||||
<outputDirectory>
|
||||
${project.build.outputDirectory}/static/docs
|
||||
</outputDirectory>
|
||||
@@ -211,7 +178,22 @@ be included in the project's jar:
|
||||
<1> The existing declaration for the Asciidoctor plugin.
|
||||
<2> The resource plugin must be declared after the Asciidoctor plugin as they are bound
|
||||
to the same phase (`prepare-package`) and the resource plugin must run after the
|
||||
Asciidoctor plugin.
|
||||
Asciidoctor plugin to ensure that the documentation is generated before it's copied.
|
||||
<3> Copy the generated documentation into the build output's `static/docs` directory,
|
||||
from where it will be included in the jar file.
|
||||
|
||||
[source,groovy,indent=0,role="secondary"]
|
||||
.Gradle
|
||||
----
|
||||
jar {
|
||||
dependsOn asciidoctor <1>
|
||||
from ("${asciidoctor.outputDir}/html5") { <2>
|
||||
into 'static/docs'
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> Ensure that the documentation has been generated before the jar is built.
|
||||
<2> Copy the generated documentation into the jar's `static/docs` directory.
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user