Skip to content

Commit

Permalink
Collapse Maven and Gradle setup into one section with switchable exam…
Browse files Browse the repository at this point in the history
…ples

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
  • Loading branch information
wilkinsona committed Jan 27, 2016
1 parent 4389914 commit 5f4541b
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 86 deletions.
7 changes: 7 additions & 0 deletions buildSrc/build.gradle
@@ -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 changes: 23 additions & 0 deletions buildSrc/src/main/resources/codeBlockSwitch.css
@@ -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 changes: 45 additions & 0 deletions buildSrc/src/main/resources/codeBlockSwitch.js
@@ -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);
154 changes: 68 additions & 86 deletions docs/src/docs/asciidoc/getting-started.adoc
Expand Up @@ -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.



[[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"]
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.

[source,xml,indent=0,subs="verbatim,attributes",role="primary"]
.Maven
----
<dependency> <1>
<groupId>org.springframework.restdocs</groupId>
Expand Down Expand Up @@ -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.
Expand All @@ -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>
Expand All @@ -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>
Expand All @@ -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.



Expand Down

0 comments on commit 5f4541b

Please sign in to comment.