1. Introduction
The primary goal of this project is to simplify the generation of an up-to-date RESTful API documentation by combining documentation that’s been hand-written with auto-generated API documentation produced by Swagger. The result is intended to be an up-to-date, easy-to-read, on- and offline user guide. The output of Swagger2Markup can be used as an alternative to swagger-ui and can be served as static content.
The Swagger Specification has been donated to to the Open API Initiative (OAI) and has been renamed to OpenAPI Specification. |
Swagger2Markup converts a Swagger JSON or YAML specification into either AsciiDoc, GitHub Flavored Markdown or Atlassian Confluence Wiki documents which can be combined with hand-written Markup documentation. The Swagger source file can be located locally or remotely via HTTP. Internally Swagger2Markup uses the official swagger-parser and markup-document-builder.
You can use Swagger2Markup to convert your contract-first Swagger YAML file into Markup. As an alternative, you can choose the code-first approach and use Swagger2Markup together with Swagger JAX-RS, Springfox or spring-restdocs. If you are are Gradle or Maven user, you can also use the Swagger2Markup Gradle Plugin or Swagger2markup Maven Plugin.
The project requires at least JDK 8. |
1.1. AsciiDoc
AsciiDoc is preferable to Markdown as it has more features. AsciiDoc is a text document format for writing documentation, articles, books, ebooks, slideshows, web pages and blogs. AsciiDoc files can be converted to HTML, PDF and EPUB. AsciiDoc is much better suited for describing public APIs than JavaDoc or Annotations.
You can generate your HTML5, PDF and EPUB documentation via asciidoctorj or even better via the asciidoctor-gradle-plugin or asciidoctor-maven-plugin.
2. Getting started
Swagger2Markup is a standard .jar file. To start using it, you need to add the library to your project’s classpath. Swagger2Markup is published in JCenter and Maven Central. The artifacts can be viewed at the following locations:
If you use Gradle or Maven, you can include Swagger2Markup as follows.
The groupId has been changed from io.github.robwin to io.github.swagger2markup |
2.1. Gradle
2.1.1. Release
repositories {
jCenter()
}
compile "io.github.swagger2markup:swagger2markup:1.3.1"
2.1.2. Snapshot
repositories {
maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local/' }
}
2.2. Maven
2.2.1. Release
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>jcenter-releases</id>
<name>jcenter</name>
<url>http://jcenter.bintray.com</url>
</repository>
</repositories>
<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup</artifactId>
<version>1.3.1</version>
</dependency>
2.2.2. Snapshot
<repositories>
<repository>
<id>jcenter-snapshots</id>
<name>jcenter</name>
<url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url>
</repository>
</repositories>
3. Swagger2Markup API
3.1. Usage guide
Swagger2Markup converts a Swagger JSON or YAML specification into either AsciiDoc, GitHub Flavored Markdown or Atlassian Confluence Wiki documents. By default the Swagger2Markup converts a Swagger specification into four AsciiDoc files: overview.adoc, paths.adoc , security.adoc and definitions.adoc. But you can also convert a Swagger specification into only one file or a String.
3.1.1. Conversion of a local Swagger file
The entry point of the Swagger2Markup API is the Swagger2MarkupConverter
class. This class provides static factory methods to create a Swagger2MarkupConverter.Builder
.
Path localSwaggerFile = Paths.get("/path/to/swagger.yaml");
Path outputDirectory = Paths.get("build/asciidoc");
Swagger2MarkupConverter.from(localSwaggerFile) (1)
.build() (2)
.toFolder(outputDirectory); (3)
-
Create a
Swagger2MarkupConverter.Builder
by specifying the Path to the local file -
Build an instance of the
Swagger2MarkupConverter
-
Invoke
toFolder
by specifying the output directory
3.1.2. Conversion of a remote Swagger file
You can convert a remote Swagger specification which must be accessible via HTTP.
URL remoteSwaggerFile = new URL("http://petstore.swagger.io/v2/swagger.json");
Path outputDirectory = Paths.get("build/asciidoc");
Swagger2MarkupConverter.from(remoteSwaggerFile) (1)
.build() (2)
.toFolder(outputDirectory); (3)
-
Create a
Swagger2MarkupConverter.Builder
by specifying the URL to the remote file -
Build an instance of the
Swagger2MarkupConverter
-
Invoke
toFolder
by specifying the output directory
3.1.3. Conversion into a file
You can convert the Swagger specification into a file.
Path localSwaggerFile = Paths.get("/path/to/swagger.yaml");
Path outputFile = Paths.get("build/swagger.adoc");
Swagger2MarkupConverter.from(localSwaggerFile)
.build()
.toFile(outputFile);
3.1.4. Conversion to a String
You can convert the Swagger specification to a String.
Path localSwaggerFile = Paths.get("/path/to/swagger.yaml");
String documentation = Swagger2MarkupConverter.from(localSwaggerFile)
.build()
.toString();
3.2. Configuration
Swagger2Markup provides several options to configure the Swagger2MarkupConverter:
-
Using system properties
-
Using a fluent API
-
Using a properties file
-
Using a Java Map
-
Using Apache Commons Configuration
3.2.1. Configuration using the Builder
You can configure the Swagger2MarkupConverter by using the Swagger2MarkupConfigBuilder
to build a custom Swagger2MarkupConfig
. The Swagger2MarkupConfigBuilder
can be used to define Swagger2Markup properties with a fluent API.
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder() (1)
.withMarkupLanguage(MarkupLanguage.MARKDOWN) (2)
.withOutputLanguage(Language.DE) (3)
.withPathsGroupedBy(GroupBy.TAGS) (4)
.build(); (5)
Swagger2MarkupConverter converter = Swagger2MarkupConverter.from(localSwaggerFile)
.withConfig(config) (6)
.build();
-
Create a
Swagger2MarkupConfigBuilder
using the default constructor. -
Configure the output
MarkupLanguage
-
Configure the output
Language
-
Configure additional Swagger2Markup properties
-
Build an instance of the
Swagger2MarkupConfig
-
Use the custom Swagger2MarkupConfig
You can also create a Swagger2MarkupConfig
from a Properties file, a Map
or a Apache Commons Configuration.
3.2.2. Configuration from a Properties file
Properties properties = new Properties();
properties.load(DocumentationTest.class.getResourceAsStream("/config/config.properties")); (1)
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder(properties) (2)
.build();
Swagger2MarkupConverter converter = Swagger2MarkupConverter.from(localSwaggerFile)
.withConfig(config)
.build();
-
Load a
Properties
file from the classpath or local filesystem. -
Create a
Swagger2MarkupConfigBuilder
using the proper constructor.
3.2.3. Configuration from a Map
Map<String, String> configMap = new HashMap<>(); (1)
configMap.put(Swagger2MarkupProperties.MARKUP_LANGUAGE, MarkupLanguage.MARKDOWN.toString());
configMap.put(Swagger2MarkupProperties.OUTPUT_LANGUAGE, Language.DE.toString());
configMap.put(Swagger2MarkupProperties.PATHS_GROUPED_BY, GroupBy.TAGS.toString());
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder(configMap) (2)
.build();
Swagger2MarkupConverter converter = Swagger2MarkupConverter.from(localSwaggerFile)
.withConfig(config)
.build();
-
Create a
Map
and configure theSwagger2MarkupProperties
. -
Create a
Swagger2MarkupConfigBuilder
using the proper constructor.
3.2.4. Configuration from a Apache Commons Configuration
Configuration parameters may be loaded from the following sources using Apache Commons Configuration:
-
Properties files
-
XML documents
-
Property list files (plist)
-
JDBC Datasource
-
Servlet parameters
Configurations configs = new Configurations();
Configuration configuration = configs.properties("config.properties"); (1)
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder(configuration) (2)
.build();
Swagger2MarkupConverter converter = Swagger2MarkupConverter.from(localSwaggerFile)
.withConfig(config)
.build();
-
Create an Apache Commons
Configuration
object using the proper ConfigurationBuilder. -
Create a
Swagger2MarkupConfigBuilder
using the proper constructor.
3.2.5. Swagger2Markup properties
The properties of Swagger2Markup are defined in the class io.github.swagger2markup.Swagger2MarkupProperties
.
The properties are considered in the following order:
-
Java System properties
-
Custom properties
-
Default properties (included in Swagger2Markup)
The following tables list all available properties of Swagger2Markup:
Name | Description | Possible Values | Default |
---|---|---|---|
swagger2markup.markupLanguage |
Specifies the markup language which should be used to generate the files. |
ASCIIDOC, MARKDOWN, CONFLUENCE_MARKUP |
ASCIIDOC |
swagger2markup.swaggerMarkupLanguage |
Specifies the markup language used in Swagger descriptions. |
ASCIIDOC, MARKDOWN, CONFLUENCE_MARKUP |
MARKDOWN |
swagger2markup.pathsGroupedBy |
Specifies how the paths should be grouped |
AS_IS, TAGS, REGEX |
AS_IS |
swagger2markup.outputLanguage |
Specifies the language of the labels |
EN, DE, FR, RU |
EN |
swagger2markup.lineSeparator |
Specifies the line separator which should be used |
UNIX, WINDOWS, MAC |
<System-dependent> |
swagger2markup.generatedExamplesEnabled |
Specifies if HTTP request and response examples should be generated |
true, false |
false |
swagger2markup.flatBodyEnabled |
Optionally isolate the body parameter, if any, from other parameters |
true, false |
false |
swagger2markup.pathSecuritySectionEnabled |
Optionally disable the security section for path sections |
true, false |
true |
swagger2markup.anchorPrefix |
Optionally prefix all anchors for uniqueness if you want to include generated documents into a global documentation |
Any String |
|
swagger2markup.basePathPrefixEnabled |
Prepend the basePath to all paths |
true, false |
false |
swagger2markup.headerRegex |
Regular expression to use when grouping by RegEx |
Any valid RegEx pattern with at least one capture group |
Name | Description | Possible Values | Default |
---|---|---|---|
swagger2markup.tagOrderBy |
Specifies the order of global tags |
AS_IS, NATURAL, CUSTOM |
NATURAL |
swagger2markup.operationOrderBy |
Specifies the order of path operations |
AS_IS, NATURAL, CUSTOM |
NATURAL |
swagger2markup.definitionOrderBy |
Specifies the order of definitions |
AS_IS, NATURAL, CUSTOM |
NATURAL |
swagger2markup.parameterOrderBy |
Specifies the order of operation parameters |
AS_IS, NATURAL, CUSTOM |
NATURAL |
swagger2markup.propertyOrderBy |
Specifies the order of definition properties |
AS_IS, NATURAL, CUSTOM |
NATURAL |
swagger2markup.responseOrderBy |
Specifies the order of responses |
AS_IS, NATURAL, CUSTOM |
NATURAL |
Name | Description | Possible Values | Default |
---|---|---|---|
swagger2markup.overviewDocument |
Specifies the file name of the overview document |
Any String |
"overview" |
swagger2markup.pathsDocument |
Specifies the file name of the paths document |
Any String |
"paths" |
swagger2markup.definitionsDocument |
Specifies the file name of the definitions document |
Any String |
"definitions" |
swagger2markup.securityDocument |
Specifies the file name of the security document |
Any String |
"security" |
Name | Description | Possible Values | Default |
---|---|---|---|
swagger2markup.separatedDefinitionsEnabled |
In addition to the Definitions file, also create separate definition files for each model definition |
true, false |
false |
swagger2markup.separatedOperationsEnabled |
In addition to the Paths file, also create separate operation files for each operation |
true, false |
false |
swagger2markup.separatedOperationsFolder |
Specifies the target folder path for definition files |
Any valid folder name |
"operations" |
swagger2markup.separatedDefinitionsFolder |
Specifies the target folder path for operation files |
Any valid folder name |
"definitions" |
Name | Description | Possible Values | Default |
---|---|---|---|
swagger2markup.interDocumentCrossReferencesEnabled |
Enable use of inter-document cross-references when needed |
true, false |
false |
swagger2markup.interDocumentCrossReferencesPrefix |
Specifies a prefix for all inter-document cross-references for advanced usage |
Any String |
Name | Description | Possible Values | Default |
---|---|---|---|
swagger2markup.inlineSchemaEnabled |
Enable inline object schema support |
true, false |
true |
Name | Description | Possible Values | Default |
---|---|---|---|
swagger2markup.pageBreakLocations |
Specifies where page breaks should be inserted. |
BEFORE_OPERATION, BEFORE_OPERATION_DESCRIPTION, BEFORE_OPERATION_PARAMETERS, BEFORE_OPERATION_RESPONSES, BEFORE_OPERATION_CONSUMES, BEFORE_OPERATION_PRODUCES, BEFORE_OPERATION_EXAMPLE_REQUEST, BEFORE_OPERATION_EXAMPLE_RESPONSE, BEFORE_DEFINITION, AFTER_OPERATION, AFTER_OPERATION_DESCRIPTION, AFTER_OPERATION_PARAMETERS, AFTER_OPERATION_RESPONSES, AFTER_OPERATION_CONSUMES, AFTER_OPERATION_PRODUCES, AFTER_OPERATION_EXAMPLE_REQUEST, AFTER_OPERATION_EXAMPLE_RESPONSE, AFTER_DEFINITION |
empty |
3.3. Logging
Swagger2Markup uses SLF4J for all internal logging, but leaves the underlying log implementation open. To change the log level, you have the set the log level of the io.github.swagger2markup
package.
4. Advanced usage
4.1. Swagger operationId
Swagger2Markup uniquely identify each operations for multiple purposes :
-
generating separated operation files : file name
-
generating unique Markup anchors for operations and all sub-items.
-
searching for extra content for operations : operation folder name for content plugins (Hand-written descriptions, Dynamic content, etc…)
-
…
Swagger specification supports the operationId
field which create an unique name for each operation.
When provided, this operationId
value will be used primarily. Otherwise Swagger2Markup generates an id using normalize(operation.summary + " " + lowerCase(operation.HTTPmethod))
.
It is highly recommended to set an operationId for each operation, so that a lot of actions does not depend on operation summary which can change at anytime.
|
4.2. Swagger schema title
Swagger2Markup displays inline schemas by decomposing them (when schema is complex). In this process, some intermediate references are generated using field names which is not always the best choice.
The Swagger document supports JSON Schema title
items in inline schemas.
It’s recommended to use them in inline schemas so that they’ll be used primarily to field names and this will lead to a better naming.
InlinePet:
type: object
required:
- id
properties:
id:
type: integer
format: int64
category:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
tags:
type: array
items:
type: object
properties:
id:
type: integer
format: int64
name:
type: string

InlineTitlePet:
type: object
required:
- id
properties:
id:
type: integer
format: int64
category:
type: object
title: CategoryModel
properties:
id:
type: integer
format: int64
name:
type: string
tags:
type: array
items:
type: object
title: TagModel
properties:
id:
type: integer
format: int64
name:
type: string

5. Extension SPI
Swagger2Markup provides an Extension SPI to extend the functionality of Swagger2Markup. Five types of extension are available. An extension is an abstract class which must be implemented.
Name | Class | Description |
---|---|---|
io.github.swagger2markup.spi.OverviewDocumentExtension |
Can be used to extend the content of the Overview document |
|
io.github.swagger2markup.spi.PathsDocumentExtension |
Can be used to extend the content of the Paths document |
|
io.github.swagger2markup.spi.SecurityDocumentExtension |
Can be used to extend the content of the Security document |
|
io.github.swagger2markup.spi.DefinitionsDocumentExtension |
Can be used to extend the content of the Definitions document |
|
io.github.swagger2markup.spi.SwaggerModelExtension |
Can be used to modify the Swagger model before it is converted |
5.1. Creation of an extension
To create a custom extension, you have to create a class (e.g. io.myname.MyExtension
) which extends an extension, e.g. io.github.swagger2markup.spi.DefinitionsDocumentExtension
. Every extension point provides two methods which must be implemented:
-
init
: This method is invoked once and can be used to initialize the extension. -
apply
: This method is invoked multiple times depending on the type of the extension. ThePosition
can be retrieved from theContext
and can be used to extend the document at specific extension points.
public class MyExtension extends DefinitionsDocumentExtension {
private static final String EXTENSION_ID = "myExtension";
private String extensionProperty;
@Override
public void init(Swagger2MarkupConverter.Context globalContext) {
// init is executed once
Swagger2MarkupProperties extensionProperties = globalContext.getConfig().getExtensionsProperties(); (1)
extensionProperty = extensionProperties.getRequiredString(EXTENSION_ID + ".propertyName");
Swagger model = globalContext.getSwagger();
}
@Override
public void apply(Context context) {
MarkupDocBuilder markupBuilder = context.getMarkupDocBuilder(); (2)
Position position = context.getPosition(); (3)
String definitionName = context.getDefinitionName().get();
Model definitionModel = context.getModel().get();
if (position.equals(Position.DEFINITION_END)) {
markupBuilder.sectionTitleLevel1(definitionName) (4)
.paragraph(definitionModel.getDescription())
.importMarkup(new StringReader("*Markup*"), MarkupLanguage.ASCIIDOC);
}
// apply is executed per definition
}
}
-
You can retrieve extension properties from the config to configure the extension.
-
You can retrieve a
MarkupDocBuilder
from theContext
. -
You can retrieve the current
Position
from the Context. -
You can use a
MarkupDocBuilder
to add Markup using a fluent API or import Markup from files.
5.2. Registration of an extension
Swagger2Markup extensions must be registered in the Swagger2MarkupExtensionRegistry
. The default Swagger2MarkupExtensionRegistry
of Swagger2Markup uses the java.util.ServiceLoader
to load and register Swagger2Markup extensions automatically.
5.2.1. Automatic registration
To register your extension automatically, the following steps are required:
-
Create a file called
META-INF/services/io.github.swagger2markup.spi.DefinitionsDocumentExtension
which contains your extensions’s full qualified name, e.g.io.myname.MyExtension
. -
When a
.jar
file containing your extension is added to the classpath of Swagger2Markup, the extensions will be automatically registered.
5.2.2. Manual registration
To register your extension manually, you have to use the Swagger2MarkupExtensionRegistryBuilder
.
Swagger2MarkupExtensionRegistry registry = new Swagger2MarkupExtensionRegistryBuilder() (1)
.withDefinitionsDocumentExtension(new MyExtension()) (2)
.build(); (3)
Swagger2MarkupConverter converter = Swagger2MarkupConverter.from(localSwaggerFile)
.withExtensionRegistry(registry) (4)
.build();
-
Create a
Swagger2MarkupExtensionRegistryBuilder
using the default constructor -
Register your custom extension
-
Build an instance of
Swagger2MarkupExtensionRegistry
-
Use the custom Swagger2MarkupExtensionRegistry
5.3. Extensions points
5.3.1. OverviewDocumentExtension
The OverviewDocumentExtension allows to extend the overview document at positions :
-
DOCUMENT_BEFORE: Before the document title (title level offset = 0)
-
DOCUMENT_BEGIN: After the document title (title level offset = 1)
-
DOCUMENT_END: At the end of the document (title level offset = 1)
-
DOCUMENT_AFTER: At the very end of the document (title level offset = 0)
Extension content titles must always start from level 1. The title level will be adapted depending on position. |
5.3.2. PathsDocumentExtension
The PathsDocumentExtension allows to extend the paths document at positions :
-
DOCUMENT_BEFORE: Before the document title (title level offset = 0)
-
DOCUMENT_BEGIN: After the document title (title level offset = 1)
-
OPERATION_BEFORE: Before each operation title (title level offset = 1)
-
OPERATION_BEGIN: After each operation title (title level offset = 2)
-
OPERATION_END: At the end of each operation (title level offset = 2)
-
OPERATION_AFTER: At the very end of each operation (title level offset = 1)
-
DOCUMENT_END: At the end of the document (title level offset = 1)
-
DOCUMENT_AFTER: At the very end of the document (title level offset = 0)
Moreover, the PathsDocumentExtension allows to extend operation sections at positions :
-
OPERATION_DESCRIPTION_BEFORE: Before each description section title (title level offset = 2)
-
OPERATION_DESCRIPTION_BEGIN: After each description section title (title level offset = 3)
-
OPERATION_DESCRIPTION_END: At the end of each description section (title level offset = 3)
-
OPERATION_DESCRIPTION_AFTER: At the very end of each description section (title level offset = 2)
-
OPERATION_PARAMETERS_BEFORE: Before each parameters section title (title level offset = 2)
-
OPERATION_PARAMETERS_BEGIN: After each parameters section title (title level offset = 3)
-
OPERATION_PARAMETERS_END: At the end of each parameters section (title level offset = 3)
-
OPERATION_PARAMETERS_AFTER: At the very end of each parameters section (title level offset = 2)
-
OPERATION_RESPONSES_BEFORE: Before each responses section title (title level offset = 2)
-
OPERATION_RESPONSES_BEGIN: After each responses section title (title level offset = 3)
-
OPERATION_RESPONSES_END: At the end of each responses section (title level offset = 3)
-
OPERATION_RESPONSES_AFTER: At the very end of each responses section (title level offset = 2)
-
OPERATION_SECURITY_BEFORE: Before each security section title (title level offset = 2)
-
OPERATION_SECURITY_BEGIN: After each security section title (title level offset = 3)
-
OPERATION_SECURITY_END: At the end of each security section (title level offset = 3)
-
OPERATION_SECURITY_AFTER: At the very end of each security section (title level offset = 2)
Extension content titles must always start from level 1. The title level will be adapted depending on position. |
5.3.3. SecurityDocumentExtension
The SecurityDocumentExtension allows to extend the security document at positions :
-
DOCUMENT_BEFORE: Before the document title (title level offset = 0)
-
DOCUMENT_BEGIN: After the document title (title level offset = 1)
-
SECURITY_SCHEME_BEFORE: Before each security scheme title (title level offset = 1)
-
SECURITY_SCHEME_BEGIN: After each security scheme title (title level offset = 2)
-
SECURITY_SCHEME_END: At the end of each security scheme (title level offset = 2)
-
SECURITY_SCHEME_AFTER: At the very end of each security scheme (title level offset = 1)
-
DOCUMENT_END: At the end of the document (title level offset = 1)
-
DOCUMENT_AFTER: At the very end of the document (title level offset = 0)
Extension content titles must always start from level 1. The title level will be adapted depending on position. |
5.3.4. DefinitionsDocumentExtension
The DefinitionsDocumentExtension allows to extend the definitions document at positions :
-
DOCUMENT_BEFORE: Before the document title (title level offset = 0)
-
DOCUMENT_BEGIN: After the document title (title level offset = 1)
-
DEFINITION_BEFORE: Before each definition title (title level offset = 1)
-
DEFINITION_BEGIN: After each definition title (title level offset = 2)
-
DEFINITION_END: At the end of each definition (title level offset = 2)
-
DEFINITION_AFTER: At the very end of each definition (title level offset = 1)
-
DOCUMENT_END: At the end of the document (title level offset = 1)
-
DOCUMENT_AFTER: At the very end of the document (title level offset = 0)
Extension content titles must always start from level 1. The title level will be adapted depending on position. |
5.3.5. SwaggerModelExtension
The SwaggerModelExtension allows to modify the Swagger model before it is processed by Swagger2Markup. For example, you could use this extension to delete Paths from the Swagger model which should not be rendered.
Example:
public class MySwaggerModelExtension extends SwaggerModelExtension {
public void apply(Swagger swagger) {
swagger.setHost("newHostName"); (1)
swagger.basePath("newBasePath");
Map<String, Path> paths = swagger.getPaths(); (2)
paths.remove("/remove");
swagger.setPaths(paths);
}
}
-
You can change any Swagger model property
-
You could even remove elements from the Swagger model
5.4. Content markup language
Most content extensions supports to provide content in any markup language which will be converted, if needed, to configured Swagger2Markup converter markup language at import.
The content files markup language can be any markup-document-builder supported language :
-
ASCIIDOC : AsciiDoc. Mandatory content file extension :
adoc
-
MARKDOWN : Github Flavored Markdown. Mandatory content file extension :
md
-
CONFLUENCE_MARKUP : Confluence Wiki markup. Mandatory content file extension :
txt
Currently supported conversions are :
|
5.5. Provided Extensions
Swagger2Markup provides some extensions which can be used out-of-the-box. You just have to add the extension to your classpath.
Name | Description |
---|---|
Allows to dynamically import Markup from files. |
|
Allows to import Curl, HTTP request and response snippets from Spring Rest Docs. |
|
Allows to import JSON or XML Schema files. |
5.5.1. Dynamic file import extension
Usage guide
repositories {
jCenter()
}
compile "io.github.swagger2markup:swagger2markup-import-files-ext:1.3.2-SNAPSHOT"
The extension searches for markup files in configurable paths to append the markup to the documents at supported positions.
The markup files must conform to a naming convention to be found. The files must start with the position where the document should be extended and end with the markup file extension (e.g adoc
or md
).
See documentation of Extensions points.
Here the list of all document naming conventions for each position. You have to replace *
with an arbitrary, meaningful, identifier.
You can provide multiple contents for the same position, just specify different identifiers in place of * in the file name. The concurrent contents for a given position will all be added to the document in a determinist order, sorting content file by natural order.
|
All extensions, relatively to each extension contentPath :
-
DOCUMENT_BEFORE :
document-before-*.<markup.ext>
-
DOCUMENT_BEGIN :
document-begin-*.<markup.ext>
-
DOCUMENT_END :
document-end-*.<markup.ext>
-
DOCUMENT_AFTER :
document-after-*.<markup.ext>
Paths extensions, relatively to each extension contentPath :
-
OPERATION_BEFORE :
<operationId>/operation-before-*.<markup.ext>
-
OPERATION_BEGIN :
<operationId>/operation-begin-*.<markup.ext>
-
OPERATION_END :
<operationId>/operation-end-*.<markup.ext>
-
OPERATION_AFTER :
<operationId>/operation-after-*.<markup.ext>
-
OPERATION_DESCRIPTION_BEFORE:
<operationId>/operation-description-before-*.<markup.ext>
-
OPERATION_DESCRIPTION_BEGIN:
<operationId>/operation-description-begin-*.<markup.ext>
-
OPERATION_DESCRIPTION_END:
<operationId>/operation-description-end-*.<markup.ext>
-
OPERATION_DESCRIPTION_AFTER:
<operationId>/operation-description-after-*.<markup.ext>
-
OPERATION_PARAMETERS_BEFORE:
<operationId>/operation-parameters-before-*.<markup.ext>
-
OPERATION_PARAMETERS_BEGIN:
<operationId>/operation-parameters-begin-*.<markup.ext>
-
OPERATION_PARAMETERS_END:
<operationId>/operation-parameters-end-*.<markup.ext>
-
OPERATION_PARAMETERS_AFTER:
<operationId>/operation-parameters-after-*.<markup.ext>
-
OPERATION_RESPONSES_BEFORE:
<operationId>/operation-responses-before-*.<markup.ext>
-
OPERATION_RESPONSES_BEGIN:
<operationId>/operation-responses-begin-*.<markup.ext>
-
OPERATION_RESPONSES_END:
<operationId>/operation-responses-end-*.<markup.ext>
-
OPERATION_RESPONSES_AFTER:
<operationId>/operation-responses-after-*.<markup.ext>
-
OPERATION_SECURITY_BEFORE:
<operationId>/operation-security-before-*.<markup.ext>
-
OPERATION_SECURITY_BEGIN:
<operationId>/operation-security-begin*.<markup.ext>
-
OPERATION_SECURITY_END:
<operationId>/operation-security-end-*.<markup.ext>
-
OPERATION_SECURITY_AFTER:
<operationId>/operation-security-after-*.<markup.ext>
Definitions extensions, relatively to each extension contentPath :
-
DEFINITION_BEFORE :
<definitionName>/definition-before-*.<markup.ext>
-
DEFINITION_BEGIN :
<definitionName>/definition-begin-*.<markup.ext>
-
DEFINITION_END :
<definitionName>/definition-end-*.<markup.ext>
-
DEFINITION_AFTER :
<definitionName>/definition-after-*.<markup.ext>
Security extensions, relatively to each extension contentPath :
-
SECURITY_SCHEME_BEFORE :
<securitySchemeName>/security-scheme-before-*.<markup.ext>
-
SECURITY_SCHEME_BEGIN :
<securitySchemeName>/security-scheme-begin-*.<markup.ext>
-
SECURITY_SCHEME_END :
<securitySchemeName>/security-scheme-end-*.<markup.ext>
-
SECURITY_SCHEME_AFTER :
<securitySchemeName>/security-scheme-after-*.<markup.ext>
<operationId> value depends on Swagger specification. If you provided an operationId for operations in the Swagger document, the value will be used primarily. It is highly recommended to set operationId for operations : see Swagger operationId. In all cases, all placeholder values are case-sensitive.
|
It’s highly recommended to configure a different contentPath for each extension (dynamicOverview, dynamicDefinitions, etc…) because content files for DOCUMENT_* positions have the same naming convention. |
overview/document-before-intro.adoc (1) paths/document-before-intro.adoc (2) paths/updatePet/operation-begin-description.adoc paths/updatePet/operation-end-example1.adoc paths/updatePet/operation-end-example2.adoc (3) definitions/Pet/definition-begin-description.adoc
-
"overview", "paths" and "definitions" are different configured contentPath for different extensions.
-
the document name is the same but will be used only in Paths document because contentPath is different (cf 1.).
-
both example1 and example2 content files will be added to "updatePet" operation. They’ll be applied consecutively, with their names sorted by natural order.
Content markup language
By default, the markup language is set to ASCIIDOC. Set extension Configuration to change content markup language.
Configuration
The extension adds the following properties to Swagger2Markup which must be configured:
Name | Description | Default | Example |
---|---|---|---|
|
The path to the files which should be imported |
- |
|
|
The markup language of the content files |
|
|
|
The path to the files which should be imported |
- |
|
|
The markup language of the content files |
|
|
|
The path to the files which should be imported |
- |
|
|
The markup language of the content files |
|
|
|
TThe path to the files which should be imported |
- |
|
|
The markup language of the content files |
|
|
5.5.2. Spring RestDocs extension
Swagger2Markup can be used together with spring-restdocs. Swagger2Markup can include the generated CURL request, HTTP request and HTTP response example snippets from spring-restdocs into the generated Markup documents. See spring-restdocs how to configure it.
Usage guide
repositories {
jCenter()
}
compile "io.github.swagger2markup:swagger2markup-spring-restdocs-ext:1.3.2-SNAPSHOT"
The extension searches for Spring RestDocs snippet files in a configurable path to append the snippets at the end of a path operation section. By default the following snippets are searched :
-
<operationId>/http-request.<markup.ext>
-
<operationId>/http-response.<markup.ext>
-
<operationId>/curl-request.<markup.ext>
<operationId> value depends on Swagger specification. If you provided an operationId for operations in the Swagger document, the value will be used primarily. It is highly recommended to set operationId for operations : see Swagger operationId. In all cases, <operationId> is case-sensitive.
|
Swagger Example:
paths:
/pets:
post:
summary: Add a new pet to the store
operationId: addPet
...
The following Unit Test uses Spring RestDocs to tests the /pets
endoint and writes the example files into the build/snippets
folder. Have a look at the Spring Boot and Springfox chapter for a full example using Spring Boot, Springfox and Spring RestDocs.
@Rule
public final RestDocumentation restDocumentation = new RestDocumentation("build/snippets");
@Test
public void addAPetToTheStore() throws Exception {
this.mockMvc.perform(post("/pets/").content(createPet())
.contentType(MediaType.APPLICATION_JSON))
.andDo(document("addPet", preprocessResponse(prettyPrint())))
.andExpect(status().isOk());
}
Example: build/snippets/addPet/http-request.adoc
.
Content markup language
By default, the markup language is set to ASCIIDOC. Set extension Configuration to change content markup language.
Configuration
The extension adds the following properties to Swagger2Markup which must be configured:
Name | Description | Default | Example |
---|---|---|---|
|
The path to the Spring RestDocs snippets |
- |
|
|
The markup language of the content files |
|
|
|
Boolean value. Set to false to disable default snippet files |
|
|
5.5.3. Schema file import extension
Usage guide
repositories {
jCenter()
}
compile "io.github.swagger2markup:swagger2markup-import-schemas-ext:1.3.2-SNAPSHOT"
The extension searches for Schema files in a configurable path to append the Schema file content at the end of a definition section. The Schema files must conform to a naming convention to be found. The files must be called schema.xsd
or schema.json
and must be stored in a folder which matches the name of a definition.
Example: /schemas/Pet/schema.json
.
Configuration
The extension adds the following properties to Swagger2Markup which must be configured:
Name | Description | Example |
---|---|---|
|
The path to the schema files |
|
6. Gradle Plugin
Swagger2Markup provides a Gradle plugin. The Gradle plugin is published in JCenter and Maven Central.
The Gradle Plugin requires at least JDK 8. |
6.1. Usage guide
Add the following snippet to your Gradle build file:
buildscript {
repositories {
jcenter()
maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local/' }
}
dependencies {
classpath 'io.github.swagger2markup:swagger2markup-gradle-plugin:1.3.1'
}
}
apply plugin: 'io.github.swagger2markup'
The plugin adds a new task named convertSwagger2markup
. You can run the task as follows:
gradlew convertSwagger2markup
6.2. Configuration
You can customize the task by configuring a Map of Swagger2Markup properties.
convertSwagger2markup {
swaggerInput file("src/docs/swagger/swagger_petstore.yaml").getAbsolutePath()
outputDir file("${buildDir}/asciidoc")
config = ['swagger2markup.markupLanguage' : 'ASCIIDOC',
'swagger2markup.pathsGroupedBy' : 'TAGS']
}
Name | Description | Type | Example |
---|---|---|---|
swaggerInput |
The URL or file path to the Swagger specification |
String |
|
outputDir |
The directory where the output should be stored. |
File |
|
outputFile |
The file path (without extension) where the output should be stored. |
File |
|
config |
The Swagger2Markup properties to configure the converter |
Map |
6.3. Example
You can copy the template project from GitHub to get started.
7. Maven Plugin
Swagger2Markup provides a Maven plugin. The Maven plugin is published in JCenter and Maven Central.
The Maven Plugin requires at least JDK 8. |
7.1. Usage guide
Add the following snippet to your Maven POM file:
<pluginRepositories>
<pluginRepository>
<id>jcenter-snapshots</id>
<name>jcenter</name>
<url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url>
</pluginRepository>
<pluginRepository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>jcenter-releases</id>
<name>jcenter</name>
<url>http://jcenter.bintray.com</url>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-maven-plugin</artifactId>
<version>1.3.1</version>
</plugin>
</plugins>
</build>
The plugin adds a new task goal swagger2markup:convertSwagger2markup
. You can run the goal as follows:
mvn swagger2markup:convertSwagger2markup
7.2. Configuration
You can customize the task by configuring a Map of Swagger2Markup properties.
<build>
<plugins>
<plugin>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-maven-plugin</artifactId>
<version>1.3.1</version>
<configuration>
<swaggerInput>${project.basedir}/src/docs/swagger/swagger_petstore.yaml</swaggerInput>
<outputDir>${project.build.directory}/asciidoc</outputDir>
<config>
<swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>
</config>
</configuration>
</plugin>
</plugins>
</build>
Name | Description | Type | Example |
---|---|---|---|
swaggerInput |
The URL or file path to the Swagger specification |
String |
|
outputDir |
The directory where the output should be stored. |
File |
|
outputFile |
The file path (without extension) where the output should be stored. |
File |
|
config |
The Swagger2Markup properties to configure the converter |
Map |
7.3. Example
You can copy the template project from GitHub to get started.
8. Command Line Interface
Swagger2Markup provides a Command line interface (CLI). The CLI is published in JCenter and Maven Central. The artifacts can be viewed at the following locations:
The CLI requires at least JDK 8. |
8.1. Usage guide
8.1.1. Show help
You can show the help:
java -jar swagger2markup-cli-1.3.1.jar help convert
Output:
NAME swagger2markup convert - Converts a Swagger JSON or YAML file into Markup documents. SYNOPSIS swagger2markup convert [(-c <configFile> | --config <configFile>)] [(-d <outputDir> | --outputDir <outputDir>)] [(-f <outputFile> | --outputFile <outputFile>)] (-i <swaggerInput> | --swaggerInput <swaggerInput>) OPTIONS -c <configFile>, --config <configFile> Config file. -d <outputDir>, --outputDir <outputDir> Output directory. Converts the Swagger specification into multiple files. -f <outputFile>, --outputFile <outputFile> Output file. Converts the Swagger specification into one file. -h, --help Display help information -i <swaggerInput>, --swaggerInput <swaggerInput> Swagger input. Can either be a URL or a file path.
8.1.2. Conversion into a folder
You can convert a Swagger file into a folder as follows:
java -jar swagger2markup-cli-1.3.1.jar convert -i /path/to/swagger_petstore.yaml -d /tmp/asiidoc
It generates the Markup documents into the /tmp/asiidoc
folder.
8.1.3. Conversion into a file
You can convert a local Swagger file into a file as follows:
java -jar swagger2markup-cli-1.3.1.jar convert -i /path/to/swagger_petstore.yaml -f /tmp/asiidoc/swagger
The input file must not have a file extension |
It generates the Markup documents into the file /tmp/asiidoc/swagger.adoc
.
8.1.4. Conversion of a remote Swagger file
You can convert a remote Swagger specification which must be accessible via HTTP.
java -jar swagger2markup-cli-1.3.1.jar convert -i "http://petstore.swagger.io/v2/swagger.json" -d /tmp
8.2. Configuration
Create a config.properties
file to customize the Swagger2Markup properties. For Example:
swagger2markup.markupLanguage=MARKDOWN swagger2markup.outputLanguage=DE
Invoke the CLI as follows:
java -jar swagger2markup-cli-1.3.1.jar convert -i /path/to/swagger_petstore.yaml -o /tmp -c /path/to/config.properties
9. Docker image
The Swagger2Markup-CLI has been published as a Docker image on DockerHub.
9.1. Usage guide
You can pull the Swagger2Markup image as follows:
docker pull swagger2markup/swagger2markup
You can convert a Swagger Spec by running a Docker container as follows:
docker run --rm -v $(pwd):/opt swagger2markup/swagger2markup convert -i /opt/swagger.yaml -f /opt/swagger -c /opt/config.properties
10. Spring Boot and Springfox
If you use Spring Boot and Springfox or Swagger JAX-RS, you can do the following:
-
generate an up-to-date Swagger JSON file during an unit or integration test
-
convert the Swagger JSON file into AsciiDoc
-
add hand-written AsciiDoc documentation
-
convert AsciiDoc into HTML and PDF
-
copy the HTML and PDF artifacts into an executable Spring Boot Jar file and serve it as static content
This transformation pipeline can be done with Gradle or Maven in the build phase. That way there is no runtime overhead and there are no additional runtime libraries required.
The Swagger2MarkupConverter can be used to make a request to a remote Swagger endpoint during an integration test. The Swagger2MarkupConverter allows to write the generated documents into any folder. In this this example it is src/docs/asciidoc/generated
.
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {Application.class, SwaggerConfig.class})
@WebIntegrationTest
public class Swagger2MarkupTest {
@Test
public void convertRemoteSwaggerToAsciiDoc() {
// Remote Swagger source
Swagger2MarkupConverter.from(new URL("http://localhost:8080/v2/api-docs")).build()
.toFolder(Paths.get("src/docs/asciidoc/generated"));
}
}
Spring’s MVC Test framework can also be used to make a request to a Springfox Swagger endpoint during an unit test. A custom ResultHandler Swagger2MarkupResultHandler
can be used to write the Swagger JSON response into a directory. The custom ResultHandler is part of springfox-staticdocs
. That way you also verify that your Swagger endpoint is working.
The Swagger JSON response can be converted using the Gradle Plugin or Maven Plugin.
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {Application.class, SwaggerConfig.class})
public class Swagger2MarkupTest {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
@Test
public void convertSwaggerToAsciiDoc() throws Exception {
this.mockMvc.perform(get("/v2/api-docs")
.accept(MediaType.APPLICATION_JSON))
.andDo(Swagger2MarkupResultHandler
.outputDirectory("src/docs/asciidoc/generated").build())
.andExpect(status().isOk());
}
}
10.1. Demo
The quickest way to get started is to look at the demo project spring-swagger2markup-demo. The demo shows how to generate static docs (HTML5 and PDF) by using the Swagger2Markup Gradle Plugin and serve the generated documentation as static content in a Spring Boot App under http://localhost:9080/docs/index.html and http://localhost:9080/docs/index.pdf.
If you want to start the Spring Boot application, please run:
gradlew clean build
java -jar build/libs/spring-swagger2markup-demo-{project-version}.jar
If you only want to generate the HTML and PDF documentation, please run:
gradlew clean asciidoctor
11. Contributing
11.1. Questions
You can ask questions about Swagger2Markup in Gitter.
11.2. Bugs
If you believe you have found a bug, please take a moment to search the existing issues. If no one else has reported the problem, please open a new issue that describes the problem in detail and, ideally, includes a test that reproduces it.
11.3. Enhancements
If you’d like an enhancement to be made to Swagger2Markup, pull requests are most welcome. The source code is on GitHub. You may want to search the existing issues and pull requests to see if the enhancement is already being worked on. You may also want to open a new issue to discuss a possible enhancement before work on it begins.
12. License
Copyright 2017 Robert Winkler
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.