From 2f33522e6dbade76d0623345837cdff87eb92431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cas=20Eli=C3=ABns?= Date: Tue, 3 Jan 2017 11:21:31 +0100 Subject: [PATCH] Issue #214 Added support for page breaks (#226) * Added support for page breaks * Added documentation and config file support for page breaks and regex --- RELEASENOTES.adoc | 10 +- build.gradle | 4 +- src/docs/asciidoc/usage_guide.adoc | 10 +- .../swagger2markup/PageBreakLocations.java | 37 + .../swagger2markup/Swagger2MarkupConfig.java | 8 + .../Swagger2MarkupProperties.java | 23 +- .../builder/Swagger2MarkupConfigBuilder.java | 32 +- .../component/PathOperationComponent.java | 44 +- .../internal/document/PathsDocument.java | 25 +- .../swagger2markup/AsciidocConverterTest.java | 25 + .../asciidoc/page_breaks/definitions.adoc | 132 +++ .../asciidoc/page_breaks/overview.adoc | 44 + .../expected/asciidoc/page_breaks/paths.adoc | 905 ++++++++++++++++++ .../asciidoc/page_breaks/security.adoc | 29 + 14 files changed, 1295 insertions(+), 33 deletions(-) create mode 100644 src/main/java/io/github/swagger2markup/PageBreakLocations.java create mode 100644 src/test/resources/expected/asciidoc/page_breaks/definitions.adoc create mode 100644 src/test/resources/expected/asciidoc/page_breaks/overview.adoc create mode 100644 src/test/resources/expected/asciidoc/page_breaks/paths.adoc create mode 100644 src/test/resources/expected/asciidoc/page_breaks/security.adoc diff --git a/RELEASENOTES.adoc b/RELEASENOTES.adoc index d486fe3a..5f5f91b9 100644 --- a/RELEASENOTES.adoc +++ b/RELEASENOTES.adoc @@ -114,4 +114,12 @@ * Issue #205: Fixed the option to influence resource ordering * Issue #198: Chinese chinese language encoding * Issue #207: Properties that start with an underscore are displayed correctly now -* Refactored Swagger2Markup to use a Component-Based design. A document can be composed of components and components can be composed of other components. \ No newline at end of file +* Refactored Swagger2Markup to use a Component-Based design. A document can be composed of components and components can be composed of other components. + +=== Version 1.1.2 +* Issue #214: Add page break locations +* Issue #223: Improve example rendering +* Issue #215: Add ability to group operations by RegEx +* Added new configuration options: pageBreakLocations, headerRegex +* Added new valid value for configuration headerRegex: REGEX +* Updated markup-document-builder from 1.1.0 to 1.1.1-SNAPSHOT \ No newline at end of file diff --git a/build.gradle b/build.gradle index d01024a1..c4bdab4a 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ buildscript { } } description = 'swagger2markup Build' -version = '1.1.2-SNAPSHOT' +version = '1.2.0' ext.releaseVersion = '1.1.1' group = 'io.github.swagger2markup' @@ -41,7 +41,7 @@ repositories { } dependencies { - compile 'io.github.swagger2markup:markup-document-builder:1.1.0' + compile 'io.github.swagger2markup:markup-document-builder:1.1.1-SNAPSHOT' compile 'io.swagger:swagger-compat-spec-parser:1.0.23' compile 'org.apache.commons:commons-configuration2:2.1' compile 'commons-beanutils:commons-beanutils:1.9.2' diff --git a/src/docs/asciidoc/usage_guide.adoc b/src/docs/asciidoc/usage_guide.adoc index c9925a5b..c0f44b9d 100644 --- a/src/docs/asciidoc/usage_guide.adoc +++ b/src/docs/asciidoc/usage_guide.adoc @@ -136,7 +136,7 @@ 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 | AS_IS +|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 | |swagger2markup.generatedExamplesEnabled| Specifies if HTTP request and response examples should be generated | true, false | false @@ -144,6 +144,7 @@ The following tables list all available properties of Swagger2Markup: |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 | |=== [options="header"] @@ -193,6 +194,13 @@ The following tables list all available properties of Swagger2Markup: |swagger2markup.inlineSchemaEnabled| Enable inline object schema support | true, false | true |=== +[options="header"] +.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 +|=== + === Logging Swagger2Markup uses http://www.slf4j.org/[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. diff --git a/src/main/java/io/github/swagger2markup/PageBreakLocations.java b/src/main/java/io/github/swagger2markup/PageBreakLocations.java new file mode 100644 index 00000000..29b162fd --- /dev/null +++ b/src/main/java/io/github/swagger2markup/PageBreakLocations.java @@ -0,0 +1,37 @@ +/* + * Copyright 2016 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. + */ +package io.github.swagger2markup; + +public enum PageBreakLocations { + 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 +} \ No newline at end of file diff --git a/src/main/java/io/github/swagger2markup/Swagger2MarkupConfig.java b/src/main/java/io/github/swagger2markup/Swagger2MarkupConfig.java index efe044b6..52f525e7 100644 --- a/src/main/java/io/github/swagger2markup/Swagger2MarkupConfig.java +++ b/src/main/java/io/github/swagger2markup/Swagger2MarkupConfig.java @@ -21,6 +21,7 @@ import io.swagger.models.parameters.Parameter; import java.util.Comparator; +import java.util.List; import java.util.regex.Pattern; /** @@ -219,4 +220,11 @@ public interface Swagger2MarkupConfig { * @return the extension properties */ Swagger2MarkupProperties getExtensionsProperties(); + + /** + * Returns the list of page break locations + * + * @return List of PageBreakLocations + */ + List getPageBreakLocations(); } diff --git a/src/main/java/io/github/swagger2markup/Swagger2MarkupProperties.java b/src/main/java/io/github/swagger2markup/Swagger2MarkupProperties.java index c68c8dc3..9ee2623c 100644 --- a/src/main/java/io/github/swagger2markup/Swagger2MarkupProperties.java +++ b/src/main/java/io/github/swagger2markup/Swagger2MarkupProperties.java @@ -25,10 +25,8 @@ import java.net.URI; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Properties; +import java.util.*; +import java.util.regex.Pattern; public class Swagger2MarkupProperties { @@ -65,6 +63,7 @@ public class Swagger2MarkupProperties { public static final String PROPERTY_ORDER_BY = PROPERTIES_PREFIX + ".propertyOrderBy"; public static final String RESPONSE_ORDER_BY = PROPERTIES_PREFIX + ".responseOrderBy"; public static final String LINE_SEPARATOR = PROPERTIES_PREFIX + ".lineSeparator"; + public static final String PAGE_BREAK_LOCATIONS = PROPERTIES_PREFIX + ".pageBreakLocations"; /** * Prefix for Swagger2Markup extension properties @@ -337,4 +336,20 @@ public List getKeys() { public List getKeys(String prefix) { return IteratorUtils.toList(configuration.getKeys(prefix)); } + + public List getPageBreakLocations(String key) { + List result = configuration.getList(PageBreakLocations.class, key); + if(result == null) result = new ArrayList(); + + return result; + } + + public Optional getHeaderPattern(String key) { + Optional property = getString(key); + if (property.isPresent()) { + return Optional.of(Pattern.compile(property.get())); + } else { + return Optional.empty(); + } + } } diff --git a/src/main/java/io/github/swagger2markup/builder/Swagger2MarkupConfigBuilder.java b/src/main/java/io/github/swagger2markup/builder/Swagger2MarkupConfigBuilder.java index e60c1de4..bae49e66 100644 --- a/src/main/java/io/github/swagger2markup/builder/Swagger2MarkupConfigBuilder.java +++ b/src/main/java/io/github/swagger2markup/builder/Swagger2MarkupConfigBuilder.java @@ -30,10 +30,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; -import java.util.Comparator; -import java.util.Map; -import java.util.Optional; -import java.util.Properties; +import java.util.*; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -107,6 +104,12 @@ public Swagger2MarkupConfigBuilder(Configuration configuration) { config.lineSeparator = LineSeparator.valueOf(lineSeparator.get()); } + config.pageBreakLocations = swagger2MarkupProperties.getPageBreakLocations(PAGE_BREAK_LOCATIONS); + + Optional headerPattern = swagger2MarkupProperties.getHeaderPattern(HEADER_REGEX); + + config.headerPattern = headerPattern.orElse(null); + Configuration swagger2markupConfiguration = compositeConfiguration.subset(PROPERTIES_PREFIX); Configuration extensionsConfiguration = swagger2markupConfiguration.subset(EXTENSION_PREFIX); config.extensionsProperties = new Swagger2MarkupProperties(extensionsConfiguration); @@ -486,11 +489,23 @@ public Swagger2MarkupConfigBuilder withBasePathPrefix() { * @return this builder */ public Swagger2MarkupConfigBuilder withAnchorPrefix(String anchorPrefix) { - Validate.notNull(anchorPrefix, "%s must no be null", "anchorPrefix"); + Validate.notNull(anchorPrefix, "%s must not be null", "anchorPrefix"); config.anchorPrefix = anchorPrefix; return this; } + /** + * Set the page break locations + * + * @param locations List of locations to create new pages + * @return this builder + */ + public Swagger2MarkupConfigBuilder withPageBreaks(List locations) { + Validate.notNull(locations, "%s must not be null", "locations"); + config.pageBreakLocations = locations; + return this; + } + /** * Specifies the line separator which should be used. * @@ -540,6 +555,8 @@ static class DefaultSwagger2MarkupConfig implements Swagger2MarkupConfig { private String separatedOperationsFolder; private String separatedDefinitionsFolder; + private List pageBreakLocations; + private Pattern headerPattern; private Swagger2MarkupProperties extensionsProperties; @@ -718,5 +735,10 @@ public Swagger2MarkupProperties getExtensionsProperties() { public boolean isBasePathPrefixEnabled() { return basePathPrefixEnabled; } + + @Override + public List getPageBreakLocations() { + return pageBreakLocations; + } } } \ No newline at end of file diff --git a/src/main/java/io/github/swagger2markup/internal/component/PathOperationComponent.java b/src/main/java/io/github/swagger2markup/internal/component/PathOperationComponent.java index 5d980462..f1e62a53 100644 --- a/src/main/java/io/github/swagger2markup/internal/component/PathOperationComponent.java +++ b/src/main/java/io/github/swagger2markup/internal/component/PathOperationComponent.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import io.github.swagger2markup.GroupBy; +import io.github.swagger2markup.PageBreakLocations; import io.github.swagger2markup.Swagger2MarkupConverter; import io.github.swagger2markup.internal.resolver.DocumentResolver; import io.github.swagger2markup.internal.type.ObjectType; @@ -41,6 +42,7 @@ import java.util.*; import static io.github.swagger2markup.Labels.*; +import static io.github.swagger2markup.PageBreakLocations.*; import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.copyMarkupDocBuilder; import static io.github.swagger2markup.internal.utils.MarkupDocBuilderUtils.markupDescription; import static io.github.swagger2markup.spi.PathsDocumentExtension.Position; @@ -80,21 +82,46 @@ public static PathOperationComponent.Parameters parameters(PathOperation operati @Override public MarkupDocBuilder apply(MarkupDocBuilder markupDocBuilder, Parameters params) { PathOperation operation = params.operation; + List locations = config.getPageBreakLocations(); + applyPathsDocumentExtension(new PathsDocumentExtension.Context(Position.OPERATION_BEFORE, markupDocBuilder, operation)); + + if (locations.contains(BEFORE_OPERATION)) markupDocBuilder.pageBreak(); buildOperationTitle(markupDocBuilder, operation); + applyPathsDocumentExtension(new PathsDocumentExtension.Context(Position.OPERATION_BEGIN, markupDocBuilder, operation)); buildDeprecatedSection(markupDocBuilder, operation); + + if (locations.contains(BEFORE_OPERATION_DESCRIPTION)) markupDocBuilder.pageBreak(); buildDescriptionSection(markupDocBuilder, operation); + if (locations.contains(AFTER_OPERATION_DESCRIPTION)) markupDocBuilder.pageBreak(); + + if (locations.contains(BEFORE_OPERATION_PARAMETERS)) markupDocBuilder.pageBreak(); inlineDefinitions(markupDocBuilder, buildParametersSection(markupDocBuilder, operation), operation.getPath() + " " + operation.getMethod()); + if (locations.contains(AFTER_OPERATION_PARAMETERS)) markupDocBuilder.pageBreak(); + inlineDefinitions(markupDocBuilder, buildBodyParameterSection(markupDocBuilder, operation), operation.getPath() + " " + operation.getMethod()); + + if (locations.contains(BEFORE_OPERATION_RESPONSES)) markupDocBuilder.pageBreak(); inlineDefinitions(markupDocBuilder, buildResponsesSection(markupDocBuilder, operation), operation.getPath() + " " + operation.getMethod()); + if (locations.contains(AFTER_OPERATION_RESPONSES)) markupDocBuilder.pageBreak(); + + if (locations.contains(BEFORE_OPERATION_CONSUMES)) markupDocBuilder.pageBreak(); buildConsumesSection(markupDocBuilder, operation); + if (locations.contains(AFTER_OPERATION_CONSUMES)) markupDocBuilder.pageBreak(); + + if (locations.contains(BEFORE_OPERATION_PRODUCES)) markupDocBuilder.pageBreak(); buildProducesSection(markupDocBuilder, operation); + if (locations.contains(AFTER_OPERATION_PRODUCES)) markupDocBuilder.pageBreak(); + buildTagsSection(markupDocBuilder, operation); buildSecuritySchemeSection(markupDocBuilder, operation); - buildExamplesSection(markupDocBuilder, operation); + buildExamplesSection(markupDocBuilder, operation, locations); applyPathsDocumentExtension(new PathsDocumentExtension.Context(Position.OPERATION_END, markupDocBuilder, operation)); applyPathsDocumentExtension(new PathsDocumentExtension.Context(Position.OPERATION_AFTER, markupDocBuilder, operation)); + + if (locations.contains(AFTER_OPERATION)) markupDocBuilder.pageBreak(); + return markupDocBuilder; } @@ -317,17 +344,23 @@ private int getSectionTitleLevel() { * * @param operation the Swagger Operation */ - private void buildExamplesSection(MarkupDocBuilder markupDocBuilder, PathOperation operation) { + private void buildExamplesSection(MarkupDocBuilder markupDocBuilder, PathOperation operation, List locations) { Map generatedRequestExampleMap = ExamplesUtil.generateRequestExampleMap(config.isGeneratedExamplesEnabled(), operation, definitions, definitionDocumentResolver, markupDocBuilder); Map generatedResponseExampleMap = ExamplesUtil.generateResponseExampleMap(config.isGeneratedExamplesEnabled(), operation, definitions, definitionDocumentResolver, markupDocBuilder); - exampleMap(markupDocBuilder, generatedRequestExampleMap, labels.getLabel(EXAMPLE_REQUEST), labels.getLabel(REQUEST)); - exampleMap(markupDocBuilder, generatedResponseExampleMap, labels.getLabel(EXAMPLE_RESPONSE), labels.getLabel(RESPONSE)); + boolean beforeExampleRequestBreak = locations.contains(BEFORE_OPERATION_EXAMPLE_REQUEST); + boolean afterExampleRequestBreak = locations.contains(AFTER_OPERATION_EXAMPLE_REQUEST); + boolean beforeExampleResponseBreak = locations.contains(BEFORE_OPERATION_EXAMPLE_RESPONSE); + boolean afterExampleResponseBreak = locations.contains(AFTER_OPERATION_EXAMPLE_RESPONSE); + + exampleMap(markupDocBuilder, generatedRequestExampleMap, labels.getLabel(EXAMPLE_REQUEST), labels.getLabel(REQUEST), beforeExampleRequestBreak, afterExampleRequestBreak); + exampleMap(markupDocBuilder, generatedResponseExampleMap, labels.getLabel(EXAMPLE_RESPONSE), labels.getLabel(RESPONSE), beforeExampleResponseBreak, afterExampleResponseBreak); } - private void exampleMap(MarkupDocBuilder markupDocBuilder, Map exampleMap, String operationSectionTitle, String sectionTitle) { + private void exampleMap(MarkupDocBuilder markupDocBuilder, Map exampleMap, String operationSectionTitle, String sectionTitle, boolean beforeBreak, boolean afterBreak) { if (exampleMap.size() > 0) { + if (beforeBreak) markupDocBuilder.pageBreak(); buildSectionTitle(markupDocBuilder, operationSectionTitle); for (Map.Entry entry : exampleMap.entrySet()) { @@ -376,6 +409,7 @@ private void exampleMap(MarkupDocBuilder markupDocBuilder, Map e markupDocBuilder.listingBlock(Json.pretty(entry.getValue()), "json"); } } + if (afterBreak) markupDocBuilder.pageBreak(); } } diff --git a/src/main/java/io/github/swagger2markup/internal/document/PathsDocument.java b/src/main/java/io/github/swagger2markup/internal/document/PathsDocument.java index 73e0afd1..2346262c 100644 --- a/src/main/java/io/github/swagger2markup/internal/document/PathsDocument.java +++ b/src/main/java/io/github/swagger2markup/internal/document/PathsDocument.java @@ -18,6 +18,7 @@ import com.google.common.collect.Multimap; import io.github.swagger2markup.GroupBy; import io.github.swagger2markup.Labels; +import io.github.swagger2markup.Swagger2MarkupConfig; import io.github.swagger2markup.Swagger2MarkupConverter; import io.github.swagger2markup.internal.component.PathOperationComponent; import io.github.swagger2markup.internal.resolver.DefinitionDocumentResolverFromOperation; @@ -68,22 +69,16 @@ public PathsDocument(Swagger2MarkupConverter.Context context) { this.operationDocumentNameResolver = new OperationDocumentNameResolver(context); this.operationDocumentResolverDefault = new OperationDocumentResolverDefault(context); - if (config.isGeneratedExamplesEnabled()) { - if (logger.isDebugEnabled()) { + if (logger.isDebugEnabled()) { + if (config.isGeneratedExamplesEnabled()) { logger.debug("Generate examples is enabled."); - } - } else { - if (logger.isDebugEnabled()) { + } else { logger.debug("Generate examples is disabled."); } - } - if (config.isSeparatedOperationsEnabled()) { - if (logger.isDebugEnabled()) { + if (config.isSeparatedOperationsEnabled()) { logger.debug("Create separated operation files is enabled."); - } - } else { - if (logger.isDebugEnabled()) { + } else { logger.debug("Create separated operation files is disabled."); } } @@ -121,7 +116,7 @@ private void buildsPathsSection(MarkupDocBuilder markupDocBuilder, Map pathOperations = PathUtils.toPathOperationsList(paths, getBasePath(), config.getOperationOrdering()); if (CollectionUtils.isNotEmpty(pathOperations)) { if (config.getPathsGroupedBy() == GroupBy.AS_IS) { - pathOperations.forEach(operation -> buildOperation(markupDocBuilder, operation)); + pathOperations.forEach(operation -> buildOperation(markupDocBuilder, operation, config)); } else if (config.getPathsGroupedBy() == GroupBy.TAGS) { Validate.notEmpty(context.getSwagger().getTags(), "Tags must not be empty, when operations are grouped by tags"); // Group operations by tag @@ -135,7 +130,7 @@ private void buildsPathsSection(MarkupDocBuilder markupDocBuilder, Map buildOperation(markupDocBuilder, operation)); + operationsGroupedByTag.get(tagName).forEach(operation -> buildOperation(markupDocBuilder, operation, config)); }); } else if (config.getPathsGroupedBy() == GroupBy.REGEX) { @@ -148,7 +143,7 @@ private void buildsPathsSection(MarkupDocBuilder markupDocBuilder, Map buildOperation(markupDocBuilder, operation)); + operationsGroupedByRegex.get(header).forEach(operation -> buildOperation(markupDocBuilder, operation, config)); } } } @@ -197,7 +192,7 @@ private void applyPathsDocumentExtension(Context context) { * * @param operation operation */ - private void buildOperation(MarkupDocBuilder markupDocBuilder, PathOperation operation) { + private void buildOperation(MarkupDocBuilder markupDocBuilder, PathOperation operation, Swagger2MarkupConfig config) { if (config.isSeparatedOperationsEnabled()) { MarkupDocBuilder pathDocBuilder = copyMarkupDocBuilder(markupDocBuilder); applyPathOperationComponent(pathDocBuilder, operation); diff --git a/src/test/java/io/github/swagger2markup/AsciidocConverterTest.java b/src/test/java/io/github/swagger2markup/AsciidocConverterTest.java index 21e193c8..0d89e3cf 100644 --- a/src/test/java/io/github/swagger2markup/AsciidocConverterTest.java +++ b/src/test/java/io/github/swagger2markup/AsciidocConverterTest.java @@ -760,4 +760,29 @@ public void testWithFormat() throws IOException, URISyntaxException { Path expectedFilesDirectory = Paths.get(AsciidocConverterTest.class.getResource("/expected/asciidoc/format").toURI()); DiffUtils.assertThatAllFilesAreEqual(expectedFilesDirectory, outputDirectory, "testWithFormat.html"); } + + @Test + public void testWithPageBreaks() throws IOException, URISyntaxException { + //Given + String swaggerJsonString = IOUtils.toString(getClass().getResourceAsStream("/json/swagger_examples.json")); + Path outputDirectory = Paths.get("build/test/asciidoc/page_breaks"); + FileUtils.deleteQuietly(outputDirectory.toFile()); + + //When + Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder() + .withoutInlineSchema() + .withPageBreaks(new ArrayList<>(asList(PageBreakLocations.BEFORE_OPERATION, PageBreakLocations.BEFORE_OPERATION_EXAMPLE_REQUEST))) + .build(); + + Swagger2MarkupConverter.from(swaggerJsonString) + .withConfig(config) + .build() + .toFolder(outputDirectory); + + //Then + String[] files = outputDirectory.toFile().list(); + assertThat(files).hasSize(4).containsAll(expectedFiles); + Path expectedFilesDirectory = Paths.get(AsciidocConverterTest.class.getResource("/expected/asciidoc/page_breaks").toURI()); + DiffUtils.assertThatAllFilesAreEqual(expectedFilesDirectory, outputDirectory, "testWithPageBreaks.html"); + } } diff --git a/src/test/resources/expected/asciidoc/page_breaks/definitions.adoc b/src/test/resources/expected/asciidoc/page_breaks/definitions.adoc new file mode 100644 index 00000000..0dcd78a6 --- /dev/null +++ b/src/test/resources/expected/asciidoc/page_breaks/definitions.adoc @@ -0,0 +1,132 @@ + +[[_definitions]] +== Definitions + +[[_category]] +=== Category + +[options="header", cols=".^3,.^11,.^4"] +|=== +|Name|Description|Schema +|**id** + +__optional__|**Example** : `123`|integer(int64) +|**name** + +__optional__|**Example** : `"Canines"`|string +|=== + + +[[_complexobject]] +=== ComplexObject + +[options="header", cols=".^3,.^4"] +|=== +|Name|Schema +|**subObject** + +__optional__|object +|=== + + +[[_identified]] +=== Identified + +[options="header", cols=".^3,.^4"] +|=== +|Name|Schema +|**id** + +__optional__|integer(int64) +|=== + + +[[_order]] +=== Order + +[options="header", cols=".^3,.^11,.^4"] +|=== +|Name|Description|Schema +|**complete** + +__optional__||boolean +|**id** + +__optional__|**Example** : `77`|integer(int64) +|**petId** + +__optional__||integer(int64) +|**quantity** + +__optional__||integer(int32) +|**shipDate** + +__optional__||string(date-time) +|**status** + +__optional__|Order Status + +**Example** : `"DONE"`|string +|=== + + +[[_pet]] +=== Pet +Test description + + +[options="header", cols=".^3,.^11,.^4"] +|=== +|Name|Description|Schema +|**category** + +__optional__||<<_category,Category>> +|**id** + +__optional__||integer(int64) +|**name** + +__required__|**Example** : `"doggie"`|string +|**nicknames** + +__optional__||< string, string > map +|**photoUrls** + +__required__||< string > array +|**status** + +__optional__|pet status in the store|string +|**tags** + +__optional__||< <<_tag,Tag>> > array +|**weight** + +__optional__|the weight of the pet|number +|=== + + +[[_tag]] +=== Tag + +[options="header", cols=".^3,.^4"] +|=== +|Name|Schema +|**id** + +__optional__|integer(int64) +|**name** + +__optional__|string +|=== + + +[[_user]] +=== User +[%hardbreaks] +__Polymorphism__ : Composition + + +[options="header", cols=".^3,.^11,.^4"] +|=== +|Name|Description|Schema +|**email** + +__optional__||string +|**firstName** + +__optional__||string +|**id** + +__optional__||integer(int64) +|**lastName** + +__optional__||string +|**password** + +__optional__||string +|**phone** + +__optional__||string +|**pictures** + +__optional__||< string(byte) > array +|**userStatus** + +__optional__|User Status|integer(int32) +|**username** + +__optional__||string +|=== + + + diff --git a/src/test/resources/expected/asciidoc/page_breaks/overview.adoc b/src/test/resources/expected/asciidoc/page_breaks/overview.adoc new file mode 100644 index 00000000..961da6fd --- /dev/null +++ b/src/test/resources/expected/asciidoc/page_breaks/overview.adoc @@ -0,0 +1,44 @@ += Swagger Petstore API + + +[[_overview]] +== Overview +This is a sample server Petstore server. + +http://swagger.wordnik.com[Learn about Swagger] or join the IRC channel `#swagger` on irc.freenode.net. + +For this sample, you can use the api key `special-key` to test the authorization filters + + +=== Version information +[%hardbreaks] +__Version__ : 1.0.0 + + +=== Contact information +[%hardbreaks] +__Contact__ : apiteam@wordnik.com + + +=== License information +[%hardbreaks] +__License__ : Apache 2.0 +__License URL__ : http://www.apache.org/licenses/LICENSE-2.0.html +__Terms of service__ : http://helloreverb.com/terms/ + + +=== URI scheme +[%hardbreaks] +__Host__ : petstore.swagger.wordnik.com +__BasePath__ : /v2 +__Schemes__ : HTTP + + +=== Tags + +* pet : Pet resource +* store : Store resource +* user : User resource + + + diff --git a/src/test/resources/expected/asciidoc/page_breaks/paths.adoc b/src/test/resources/expected/asciidoc/page_breaks/paths.adoc new file mode 100644 index 00000000..d25d6226 --- /dev/null +++ b/src/test/resources/expected/asciidoc/page_breaks/paths.adoc @@ -0,0 +1,905 @@ + +[[_paths]] +== Paths + +<<< + +[[_addpet]] +=== Add a new pet to the store +.... +POST /pets +.... + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4"] +|=== +|Type|Name|Description|Schema +|**Body**|**body** + +__optional__|Pet object that needs to be added to the store|<<_pet,Pet>> +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**405**|Invalid input|No Content +|=== + + +==== Consumes + +* `application/json` +* `application/xml` + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* pet + + +==== Security + +[options="header", cols=".^3,.^4,.^13"] +|=== +|Type|Name|Scopes +|**oauth2**|**<<_petstore_auth,petstore_auth>>**|write_pets,read_pets +|=== + + +==== Example HTTP response + +===== Response 405 +[source,json] +---- +{ + "name" : "Puma", + "type" : 22, + "color" : "Black", + "gender" : "Female", + "breed" : "Mixed" +} +---- + +[source,xml] +---- +Puma22BlackFemaleMixed +---- + + +<<< + +[[_updatepet]] +=== Update an existing pet +.... +PUT /pets +.... + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4"] +|=== +|Type|Name|Description|Schema +|**Body**|**body** + +__optional__|Pet object that needs to be added to the store|<<_pet,Pet>> +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**400**|Invalid ID supplied|No Content +|**404**|Pet not found|No Content +|**405**|Validation exception|No Content +|=== + + +==== Consumes + +* `application/json` +* `application/xml` + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* pet + + +==== Security + +[options="header", cols=".^3,.^4,.^13"] +|=== +|Type|Name|Scopes +|**oauth2**|**<<_petstore_auth,petstore_auth>>**|write_pets,read_pets +|=== + + +<<< + +[[_findpetsbystatus]] +=== Finds Pets by status +.... +GET /pets/findByStatus +.... + + +==== Description +Multiple status values can be provided with comma seperated strings + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4"] +|=== +|Type|Name|Description|Schema +|**Query**|**status** + +__optional__|Status values that need to be considered for filter|< string > array(multi) +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**200**|successful operation|< <<_pet,Pet>> > array +|**400**|Invalid status value|No Content +|=== + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* pet + + +==== Security + +[options="header", cols=".^3,.^4,.^13"] +|=== +|Type|Name|Scopes +|**oauth2**|**<<_petstore_auth,petstore_auth>>**|write_pets,read_pets +|=== + + +<<< + +[[_findpetsbytags]] +=== Finds Pets by tags +.... +GET /pets/findByTags +.... + + +==== Description +Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing. + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4"] +|=== +|Type|Name|Description|Schema +|**Query**|**tags** + +__optional__|Tags to filter by|< string > array(multi) +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**200**|successful operation|< <<_pet,Pet>> > array +|**400**|Invalid tag value|No Content +|=== + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* pet + + +==== Security + +[options="header", cols=".^3,.^4,.^13"] +|=== +|Type|Name|Scopes +|**oauth2**|**<<_petstore_auth,petstore_auth>>**|write_pets,read_pets +|=== + + +<<< + +[[_updatepetwithform]] +=== Updates a pet in the store with form data +.... +POST /pets/{petId} +.... + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4"] +|=== +|Type|Name|Description|Schema +|**Path**|**petId** + +__required__|ID of pet that needs to be updated|string +|**FormData**|**name** + +__required__|Updated name of the pet|string +|**FormData**|**status** + +__required__|Updated status of the pet|string +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**405**|Invalid input|No Content +|=== + + +==== Consumes + +* `application/x-www-form-urlencoded` + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* pet + + +==== Security + +[options="header", cols=".^3,.^4,.^13"] +|=== +|Type|Name|Scopes +|**oauth2**|**<<_petstore_auth,petstore_auth>>**|write_pets,read_pets +|=== + + +<<< + +[[_getpetbyid]] +=== Find pet by ID +.... +GET /pets/{petId} +.... + + +==== Description +Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4"] +|=== +|Type|Name|Description|Schema +|**Path**|**petId** + +__required__|ID of the pet|integer(int64) +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**200**|successful operation|<<_pet,Pet>> +|**400**|Invalid ID supplied|No Content +|**404**|Pet not found|No Content +|=== + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* pet + + +==== Security + +[options="header", cols=".^3,.^4,.^13"] +|=== +|Type|Name|Scopes +|**apiKey**|**<<_api_key,api_key>>**| +|**oauth2**|**<<_petstore_auth,petstore_auth>>**|write_pets,read_pets +|=== + + +<<< + +[[_deletepet]] +=== Deletes a pet +.... +DELETE /pets/{petId} +.... + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4"] +|=== +|Type|Name|Description|Schema +|**Header**|**api_key** + +__required__||string +|**Path**|**petId** + +__required__|Pet id to delete|integer(int64) +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**400**|Invalid pet value|No Content +|=== + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* pet + + +==== Security + +[options="header", cols=".^3,.^4,.^13"] +|=== +|Type|Name|Scopes +|**oauth2**|**<<_petstore_auth,petstore_auth>>**|write_pets,read_pets +|=== + + +<<< + +[[_placeorder]] +=== Place an order for a pet +.... +POST /stores/order +.... + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4"] +|=== +|Type|Name|Description|Schema +|**Body**|**body** + +__optional__|order placed for purchasing the pet|<<_order,Order>> +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**200**|successful operation|<<_order,Order>> +|**400**|Invalid Order|No Content +|=== + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* store + + +<<< + +==== Example HTTP request + +===== Request body +[source,json] +---- +{ + "id" : 99, + "petId" : 122, + "quantity" : 2, + "shipDate" : "2016-02-22T23:02:05Z", + "status" : "PENDING", + "complete" : true +} +---- + + +==== Example HTTP response + +===== Response 200 +[source,json] +---- +{ + "id" : 99, + "petId" : 122, + "quantity" : 2, + "shipDate" : "2016-02-22T23:02:05Z", + "status" : "PENDING", + "complete" : true +} +---- + + +<<< + +[[_getorderbyid]] +=== Find purchase order by ID +.... +GET /stores/order/{orderId} +.... + + +==== Description +For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4"] +|=== +|Type|Name|Description|Schema +|**Path**|**orderId** + +__required__|ID of pet that needs to be fetched|string +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**200**|successful operation|<<_order,Order>> +|**400**|Invalid ID supplied|No Content +|**404**|Order not found|No Content +|=== + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* store + + +==== Example HTTP response + +===== Response 200 +[source,json] +---- +{ + "id" : 99, + "petId" : 122, + "quantity" : 2, + "shipDate" : "2016-02-22T23:02:05Z", + "status" : "PENDING", + "complete" : true +} +---- + + +<<< + +[[_deleteorder]] +=== Delete purchase order by ID +.... +DELETE /stores/order/{orderId} +.... + + +==== Description +For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4"] +|=== +|Type|Name|Description|Schema +|**Path**|**orderId** + +__required__|ID of the order that needs to be deleted|string +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**400**|Invalid ID supplied|No Content +|**404**|Order not found|No Content +|=== + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* store + + +<<< + +[[_createuser]] +=== Create user +.... +POST /users +.... + + +==== Description +This can only be done by the logged in user. + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4"] +|=== +|Type|Name|Description|Schema +|**Body**|**body** + +__optional__|Created user object|<<_user,User>> +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**default**|successful operation|No Content +|=== + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* user + + +<<< + +[[_createuserswitharrayinput]] +=== Creates list of users with given input array +.... +POST /users/createWithArray +.... + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4"] +|=== +|Type|Name|Description|Schema +|**Body**|**body** + +__optional__|List of user object|< <<_user,User>> > array +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**default**|successful operation|No Content +|=== + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* user + + +<<< + +[[_createuserswithlistinput]] +=== Creates list of users with given input array +.... +POST /users/createWithList +.... + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4"] +|=== +|Type|Name|Description|Schema +|**Body**|**body** + +__optional__|List of user object|< <<_user,User>> > array +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**default**|successful operation|No Content +|=== + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* user + + +<<< + +[[_loginuser]] +=== Logs user into the system +.... +GET /users/login +.... + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4,.^2"] +|=== +|Type|Name|Description|Schema|Default +|**Query**|**password** + +__optional__|The password for login in clear text|string|`"testPassword"` +|**Query**|**username** + +__optional__|The user name for login|string|`"testUser"` +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**200**|successful operation|string +|**400**|Invalid username/password supplied|No Content +|=== + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* user + + +<<< + +[[_logoutuser]] +=== Logs out current logged in user session +.... +GET /users/logout +.... + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**default**|successful operation|No Content +|=== + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* user + + +<<< + +[[_getuserbyname]] +=== Get user by user name +.... +GET /users/{username} +.... + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4,.^2"] +|=== +|Type|Name|Description|Schema|Default +|**Path**|**username** + +__required__|The name that needs to be fetched. Use user1 for testing.|string|`"testUser"` +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**200**|successful operation|<<_user,User>> +|**400**|Invalid username supplied|No Content +|**404**|User not found|No Content +|=== + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* user + + +<<< + +[[_updateuser]] +=== Updated user +.... +PUT /users/{username} +.... + + +==== Description +This can only be done by the logged in user. + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4"] +|=== +|Type|Name|Description|Schema +|**Path**|**username** + +__required__|name that need to be deleted|string +|**Body**|**body** + +__optional__|Updated user object|<<_user,User>> +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**400**|Invalid user supplied|No Content +|**404**|User not found|No Content +|=== + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* user + + +<<< + +[[_deleteuser]] +=== Delete user +.... +DELETE /users/{username} +.... + + +==== Description +This can only be done by the logged in user. + + +==== Parameters + +[options="header", cols=".^2,.^3,.^9,.^4"] +|=== +|Type|Name|Description|Schema +|**Path**|**username** + +__required__|The name that needs to be deleted|string +|=== + + +==== Responses + +[options="header", cols=".^2,.^14,.^4"] +|=== +|HTTP Code|Description|Schema +|**400**|Invalid username supplied|No Content +|**404**|User not found|No Content +|=== + + +==== Produces + +* `application/json` +* `application/xml` + + +==== Tags + +* user + + + diff --git a/src/test/resources/expected/asciidoc/page_breaks/security.adoc b/src/test/resources/expected/asciidoc/page_breaks/security.adoc new file mode 100644 index 00000000..108c1ed6 --- /dev/null +++ b/src/test/resources/expected/asciidoc/page_breaks/security.adoc @@ -0,0 +1,29 @@ + +[[_securityscheme]] +== Security + +[[_petstore_auth]] +=== petstore_auth +[%hardbreaks] +__Type__ : oauth2 +__Flow__ : implicit +__Token URL__ : http://petstore.swagger.wordnik.com/api/oauth/dialog + + +[options="header", cols=".^3,.^17"] +|=== +|Name|Description +|write_pets|modify pets in your account +|read_pets|read your pets +|=== + + +[[_api_key]] +=== api_key +[%hardbreaks] +__Type__ : apiKey +__Name__ : api_key +__In__ : HEADER + + +