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.

Swagger2Markup
Figure 1. HTML example using AsciiDoctor - path section
Swagger2Markup definitions
Figure 2. HTML example using AsciiDoctor - definition section

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)
  1. Create a Swagger2MarkupConverter.Builder by specifying the Path to the local file

  2. Build an instance of the Swagger2MarkupConverter

  3. 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)
  1. Create a Swagger2MarkupConverter.Builder by specifying the URL to the remote file

  2. Build an instance of the Swagger2MarkupConverter

  3. 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();
  1. Create a Swagger2MarkupConfigBuilder using the default constructor.

  2. Configure the output MarkupLanguage

  3. Configure the output Language

  4. Configure additional Swagger2Markup properties

  5. Build an instance of the Swagger2MarkupConfig

  6. 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();
  1. Load a Properties file from the classpath or local filesystem.

  2. 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();
  1. Create a Map and configure the Swagger2MarkupProperties.

  2. 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();
  1. Create an Apache Commons Configuration object using the proper ConfigurationBuilder.

  2. 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:

  1. Java System properties

  2. Custom properties

  3. Default properties (included in Swagger2Markup)

The following tables list all available properties of Swagger2Markup:

Table 1. Mostly used properties
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

Table 2. Properties which configure the order of Swagger Objects
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

Table 3. Properties which configure document file names
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"

Table 4. Properties which configure the generation of separate files
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"

Table 5. Properties which configure inter-document cross references
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

Table 6. Properties which configure inline schema rendering
Name Description Possible Values Default

swagger2markup.inlineSchemaEnabled

Enable inline object schema support

true, false

true

Table 7. Properties which configure page breaking
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.

Example 1. Inline schema without title items
  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
untitledSwagger
Example 2. Inline schema with title items
  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
titledSwagger

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.

Table 8. Swagger2Markup extensions
Name Class Description

OverviewDocumentExtension

io.github.swagger2markup.spi.OverviewDocumentExtension

Can be used to extend the content of the Overview document

PathsDocumentExtension

io.github.swagger2markup.spi.PathsDocumentExtension

Can be used to extend the content of the Paths document

SecurityDocumentExtension

io.github.swagger2markup.spi.SecurityDocumentExtension

Can be used to extend the content of the Security document

DefinitionsDocumentExtension

io.github.swagger2markup.spi.DefinitionsDocumentExtension

Can be used to extend the content of the Definitions document

SwaggerModelExtension

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. The Position can be retrieved from the Context 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
    }
}
  1. You can retrieve extension properties from the config to configure the extension.

  2. You can retrieve a MarkupDocBuilder from the Context.

  3. You can retrieve the current Position from the Context.

  4. 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();
  1. Create a Swagger2MarkupExtensionRegistryBuilder using the default constructor

  2. Register your custom extension

  3. Build an instance of Swagger2MarkupExtensionRegistry

  4. 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);
    }
}
  1. You can change any Swagger model property

  2. 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 :

  • Markdown → AsciiDoc

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.

Table 9. Swagger2Markup extensions
Name Description

Dynamic file import extension

Allows to dynamically import Markup from files.

Spring RestDocs extension

Allows to import Curl, HTTP request and response snippets from Spring Rest Docs.

Schema file import extension

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 :

Paths extensions, relatively to each extension contentPath :

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.
Example 3. Example of provided content files for petstore Swagger sample
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
  1. "overview", "paths" and "definitions" are different configured contentPath for different extensions.

  2. the document name is the same but will be used only in Paths document because contentPath is different (cf 1.).

  3. 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:

Table 10. Extension properties
Name Description Default Example

swagger2markup.extensions.dynamicOverview.contentPath

The path to the files which should be imported

-

src/test/resources/docs/asciidoc/overview

swagger2markup.extensions.dynamicOverview.markupLanguage

The markup language of the content files

ASCIIDOC

MARKDOWN

swagger2markup.extensions.dynamicDefinitions.contentPath

The path to the files which should be imported

-

src/test/resources/docs/asciidoc/definitions

swagger2markup.extensions.dynamicDefinitions.markupLanguage

The markup language of the content files

ASCIIDOC

MARKDOWN

swagger2markup.extensions.dynamicPaths.contentPath

The path to the files which should be imported

-

src/test/resources/docs/asciidoc/paths

swagger2markup.extensions.dynamicPaths.markupLanguage

The markup language of the content files

ASCIIDOC

MARKDOWN

swagger2markup.extensions.dynamicSecurity.contentPath

TThe path to the files which should be imported

-

src/test/resources/docs/asciidoc/security

swagger2markup.extensions.dynamicSecurity.markupLanguage

The markup language of the content files

ASCIIDOC

MARKDOWN

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> 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:

Table 11. Extension properties
Name Description Default Example

swagger2markup.extensions.springRestDocs.snippetBaseUri

The path to the Spring RestDocs snippets

-

src/test/resources/docs/asciidoc/paths

swagger2markup.extensions.springRestDocs.markupLanguage

The markup language of the content files

ASCIIDOC

MARKDOWN

swagger2markup.extensions.springRestDocs.defaultSnippets

Boolean value. Set to false to disable default snippet files

true

false

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:

Table 12. Extension properties
Name Description Example

swagger2markup.extensions.schema.schemaBaseUri

The path to the schema files

src/test/resources/docs/asciidoc/schemas

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']
}
Table 13. Gradle Plugin properties
Name Description Type Example

swaggerInput

The URL or file path to the Swagger specification

String

file("src/docs/swagger/swagger_petstore.yaml").getAbsolutePath() or http://petstore.swagger.io/v2/swagger.json

outputDir

The directory where the output should be stored.

File

file("${buildDir}/asciidoc")

outputFile

The file path (without extension) where the output should be stored.

File

file("${buildDir}/asciidoc/swagger")

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>
Table 14. Maven Plugin properties
Name Description Type Example

swaggerInput

The URL or file path to the Swagger specification

String

${project.basedir}/src/docs/swagger/swagger_petstore.yaml or http://petstore.swagger.io/v2/swagger.json

outputDir

The directory where the output should be stored.

File

${project.build.directory}/asciidoc

outputFile

The file path (without extension) where the output should be stored.

File

${project.build.directory}/asciidoc/swagger

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:

config.properties
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.