diff --git a/docs/src/docs/asciidoc/documenting-your-api.adoc b/docs/src/docs/asciidoc/documenting-your-api.adoc
index c68b9d43..fb9977c8 100644
--- a/docs/src/docs/asciidoc/documenting-your-api.adoc
+++ b/docs/src/docs/asciidoc/documenting-your-api.adoc
@@ -627,10 +627,14 @@ generated snippets.
templates] are provided for each of the snippets that Spring REST Docs can produce. To
customize a snippet's content, you can provide your own template.
-Templates are loaded from the classpath in the `org.springframework.restdocs.templates`
-package and each template is named after the snippet that it will produce. For example, to
+Templates are loaded from the classpath from an `org.springframework.restdocs.templates`
+subpackage. The name of the subpackage is determined by the ID of the template format
+that is in use. The default template format, Asciidoctor, has the ID `asciidoctor` so
+snippets are loaded from `org.springframework.restdocs.templates.asciidoctor`. Each
+template is named after the snippet that it will produce. For example, to
override the template for the `curl-request.adoc` snippet, create a template named
-`curl-request.snippet` in `src/test/resources/org/springframework/restdocs/templates`.
+`curl-request.snippet` in
+`src/test/resources/org/springframework/restdocs/templates/asciidoctor`.
diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/templates/StandardTemplateResourceResolver.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/templates/StandardTemplateResourceResolver.java
index 22912eb3..7e0b38ac 100644
--- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/templates/StandardTemplateResourceResolver.java
+++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/templates/StandardTemplateResourceResolver.java
@@ -22,12 +22,20 @@ import org.springframework.core.io.Resource;
/**
* Standard implementation of {@link TemplateResourceResolver}.
*
- * Templates are resolved by looking for a resource on the classpath named
- * {@code org/springframework/restdocs/templates/{name}.snippet}. If no such
- * resource exists an attempt is made to return a default resource that is appropriate for
- * the configured snippet format.
+ * Templates are resolved by looking for resources on the classpath. The following
+ * locations are checked in order:
+ *
+ * -
+ *
org/springframework/restdocs/templates/${templateFormatId}/${name}.snippet
+ *
+ * org/springframework/restdocs/templates/${name}.snippet
+ * -
+ *
org/springframework/restdocs/templates/${templateFormatId}/default-${name}.snippet
+ *
+ *
*
* @author Andy Wilkinson
+ * @see TemplateFormat#getId()
*/
public class StandardTemplateResourceResolver implements TemplateResourceResolver {
@@ -57,18 +65,37 @@ public class StandardTemplateResourceResolver implements TemplateResourceResolve
@Override
public Resource resolveTemplateResource(String name) {
- ClassPathResource classPathResource = new ClassPathResource(
- "org/springframework/restdocs/templates/" + name + ".snippet");
- if (!classPathResource.exists()) {
- classPathResource = new ClassPathResource(
- "org/springframework/restdocs/templates/"
- + this.templateFormat.getId() + "/" + name + ".snippet");
- if (!classPathResource.exists()) {
- throw new IllegalStateException("Template named '" + name
- + "' could not be resolved");
- }
+ Resource formatSpecificCustomTemplate = getFormatSpecificCustomTemplate(name);
+ if (formatSpecificCustomTemplate.exists()) {
+ return formatSpecificCustomTemplate;
}
- return classPathResource;
+ Resource customTemplate = getCustomTemplate(name);
+ if (customTemplate.exists()) {
+ return customTemplate;
+ }
+ Resource defaultTemplate = getDefaultTemplate(name);
+ if (defaultTemplate.exists()) {
+ return defaultTemplate;
+ }
+ throw new IllegalStateException("Template named '" + name
+ + "' could not be resolved");
+ }
+
+ private Resource getFormatSpecificCustomTemplate(String name) {
+ return new ClassPathResource(String.format(
+ "org/springframework/restdocs/templates/%s/%s.snippet",
+ this.templateFormat.getId(), name));
+ }
+
+ private Resource getCustomTemplate(String name) {
+ return new ClassPathResource(String.format(
+ "org/springframework/restdocs/templates/%s.snippet", name));
+ }
+
+ private Resource getDefaultTemplate(String name) {
+ return new ClassPathResource(String.format(
+ "org/springframework/restdocs/templates/%s/default-%s.snippet",
+ this.templateFormat.getId(), name));
}
}
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/curl-request.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-curl-request.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/curl-request.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-curl-request.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/http-request.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-http-request.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/http-request.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-http-request.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/http-response.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-http-response.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/http-response.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-http-response.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/links.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-links.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/links.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-links.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/path-parameters.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-path-parameters.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/path-parameters.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-path-parameters.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/request-fields.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-request-fields.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/request-fields.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-request-fields.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/request-headers.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-request-headers.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/request-headers.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-request-headers.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/request-parameters.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-request-parameters.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/request-parameters.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-request-parameters.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/response-fields.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-response-fields.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/response-fields.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-response-fields.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/response-headers.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-response-headers.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/response-headers.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/asciidoctor/default-response-headers.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/curl-request.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-curl-request.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/curl-request.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-curl-request.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/http-request.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-http-request.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/http-request.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-http-request.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/http-response.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-http-response.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/http-response.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-http-response.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/links.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-links.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/links.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-links.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/path-parameters.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-path-parameters.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/path-parameters.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-path-parameters.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/request-fields.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-request-fields.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/request-fields.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-request-fields.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/request-headers.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-request-headers.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/request-headers.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-request-headers.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/request-parameters.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-request-parameters.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/request-parameters.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-request-parameters.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/response-fields.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-response-fields.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/response-fields.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-response-fields.snippet
diff --git a/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/response-headers.snippet b/spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-response-headers.snippet
similarity index 100%
rename from spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/response-headers.snippet
rename to spring-restdocs-core/src/main/resources/org/springframework/restdocs/templates/markdown/default-response-headers.snippet
diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/templates/StandardTemplateResourceResolverTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/templates/StandardTemplateResourceResolverTests.java
index 8d8ef578..1d152335 100644
--- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/templates/StandardTemplateResourceResolverTests.java
+++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/templates/StandardTemplateResourceResolverTests.java
@@ -47,29 +47,17 @@ public class StandardTemplateResourceResolverTests {
private final TestClassLoader classLoader = new TestClassLoader();
@Test
- public void customSnippetResolution() throws Exception {
- this.classLoader.addResource(
- "org/springframework/restdocs/templates/test.snippet", getClass()
- .getResource("test.snippet"));
- Resource snippet = doWithThreadContextClassLoader(this.classLoader,
- new Callable() {
-
- @Override
- public Resource call() {
- return StandardTemplateResourceResolverTests.this.resolver
- .resolveTemplateResource("test");
- }
-
- });
-
- assertThat(snippet.getURL(), is(equalTo(getClass().getResource("test.snippet"))));
- }
-
- @Test
- public void fallsBackToDefaultSnippet() throws Exception {
+ public void formatSpecificCustomSnippetHasHighestPrecedence() throws Exception {
this.classLoader.addResource(
"org/springframework/restdocs/templates/asciidoctor/test.snippet",
- getClass().getResource("test.snippet"));
+ getClass().getResource("test-format-specific-custom.snippet"));
+ this.classLoader.addResource(
+ "org/springframework/restdocs/templates/test.snippet", getClass()
+ .getResource("test-custom.snippet"));
+ this.classLoader
+ .addResource(
+ "org/springframework/restdocs/templates/asciidoctor/default-test.snippet",
+ getClass().getResource("test-default.snippet"));
Resource snippet = doWithThreadContextClassLoader(this.classLoader,
new Callable() {
@@ -81,11 +69,59 @@ public class StandardTemplateResourceResolverTests {
});
- assertThat(snippet.getURL(), is(equalTo(getClass().getResource("test.snippet"))));
+ assertThat(
+ snippet.getURL(),
+ is(equalTo(getClass().getResource("test-format-specific-custom.snippet"))));
}
@Test
- public void failsIfCustomAndDefaultSnippetDoNotExist() throws Exception {
+ public void generalCustomSnippetIsUsedInAbsenceOfFormatSpecificCustomSnippet()
+ throws Exception {
+ this.classLoader.addResource(
+ "org/springframework/restdocs/templates/test.snippet", getClass()
+ .getResource("test-custom.snippet"));
+ this.classLoader
+ .addResource(
+ "org/springframework/restdocs/templates/asciidoctor/default-test.snippet",
+ getClass().getResource("test-default.snippet"));
+ Resource snippet = doWithThreadContextClassLoader(this.classLoader,
+ new Callable() {
+
+ @Override
+ public Resource call() {
+ return StandardTemplateResourceResolverTests.this.resolver
+ .resolveTemplateResource("test");
+ }
+
+ });
+
+ assertThat(snippet.getURL(),
+ is(equalTo(getClass().getResource("test-custom.snippet"))));
+ }
+
+ @Test
+ public void defaultSnippetIsUsedInAbsenceOfCustomSnippets() throws Exception {
+ this.classLoader
+ .addResource(
+ "org/springframework/restdocs/templates/asciidoctor/default-test.snippet",
+ getClass().getResource("test-default.snippet"));
+ Resource snippet = doWithThreadContextClassLoader(this.classLoader,
+ new Callable() {
+
+ @Override
+ public Resource call() {
+ return StandardTemplateResourceResolverTests.this.resolver
+ .resolveTemplateResource("test");
+ }
+
+ });
+
+ assertThat(snippet.getURL(),
+ is(equalTo(getClass().getResource("test-default.snippet"))));
+ }
+
+ @Test
+ public void failsIfCustomAndDefaultSnippetsDoNotExist() throws Exception {
this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage(equalTo("Template named 'test' could not be resolved"));
doWithThreadContextClassLoader(this.classLoader, new Callable() {
diff --git a/spring-restdocs-core/src/test/resources/org/springframework/restdocs/templates/test.snippet b/spring-restdocs-core/src/test/resources/org/springframework/restdocs/templates/test-custom.snippet
similarity index 100%
rename from spring-restdocs-core/src/test/resources/org/springframework/restdocs/templates/test.snippet
rename to spring-restdocs-core/src/test/resources/org/springframework/restdocs/templates/test-custom.snippet
diff --git a/spring-restdocs-core/src/test/resources/org/springframework/restdocs/templates/test-default.snippet b/spring-restdocs-core/src/test/resources/org/springframework/restdocs/templates/test-default.snippet
new file mode 100644
index 00000000..e69de29b
diff --git a/spring-restdocs-core/src/test/resources/org/springframework/restdocs/templates/test-format-specific-custom.snippet b/spring-restdocs-core/src/test/resources/org/springframework/restdocs/templates/test-format-specific-custom.snippet
new file mode 100644
index 00000000..e69de29b