Feature/open api v3 support (#405)

This commit is contained in:
Robert Winkler
2020-03-06 08:31:21 +01:00
committed by GitHub
parent 69baeb6339
commit 4a3ee6c5ca
438 changed files with 14506 additions and 794 deletions

View File

@@ -54,6 +54,9 @@ configure(project.coreProjects) {
options.encoding = 'UTF-8'
options.compilerArgs += ["-Xlint:unchecked", "-parameters"]
}
tasks.withType(Javadoc){
options.encoding = 'UTF-8'
}
jmh {
duplicateClassesStrategy = 'warn'
}

View File

@@ -6,6 +6,7 @@ ext {
dependencyOverrides = [:]
}
implLibraries = [
asciiDocJApi : "org.asciidoctor:asciidoctorj-api:2.2.0",
commonsBeanUtils : "commons-beanutils:commons-beanutils:1.9.4",
commonsCodec : "commons-codec:commons-codec:1.13",
commonsCollections4: "org.apache.commons:commons-collections4:4.4",
@@ -13,16 +14,20 @@ implLibraries = [
commonsLang3 : "org.apache.commons:commons-lang3:3.9",
commonsIO : "commons-io:commons-io:2.6",
commonsText : "org.apache.commons:commons-text:1.8",
guava : 'com.google.guava:guava:27.0.1-android',
jacksonDatabind : 'com.fasterxml.jackson.core:jackson-databind:2.9.10',
mark2Ascii : "nl.jworks.markdown_to_asciidoc:markdown_to_asciidoc:1.1",
paleo : "ch.netzwerg:paleo-core:0.14.0",
pegdown : "org.pegdown:pegdown:1.6.0",
slf4j : "org.slf4j:slf4j-api:1.7.28",
swaggerConverterV2 : "io.swagger.parser.v3:swagger-parser-v2-converter:2.0.15",
swaggerV2 : "io.swagger:swagger-parser:1.0.47",
swaggerV2Converter : "io.swagger.parser.v3:swagger-parser-v2-converter:2.0.15",
swaggerV3 : "io.swagger.parser.v3:swagger-parser:2.0.15",
vavr : "io.vavr:vavr:0.10.2"
]
testLibraries = [
asciiDocJ : "org.asciidoctor:asciidoctorj:2.1.0",
asciiDocJ : "org.asciidoctor:asciidoctorj:2.2.0",
assertj : "org.assertj:assertj-core:3.13.2",
assertjDiff: "io.github.robwin:assertj-diff:0.1.1",
junit : "junit:junit:4.12",
@@ -36,9 +41,9 @@ dependencyOverrides = [
commonsIO : implLibraries.commonsIO,
commonsLang3 : implLibraries.commonsLang3,
findBugs : 'com.google.code.findbugs:jsr305:3.0.2',
guava : 'com.google.guava:guava:27.0.1-android',
guava : implLibraries.guava,
jaksonCore : 'com.github.fge:jackson-coreutils:1.8',
jacksonDatabind: 'com.fasterxml.jackson.core:jackson-databind:2.9.10',
jacksonDatabind: implLibraries.jacksonDatabind,
jnrConstants : 'com.github.jnr:jnr-constants:0.9.12',
jnrEnxio : 'com.github.jnr:jnr-enxio:0.19',
jnrPosix : 'com.github.jnr:jnr-posix:3.0.49',

View File

@@ -0,0 +1,34 @@
ext.moduleName="io.github.swagger2markup.openapi2markup"
dependencies {
configurations.all {
resolutionStrategy.force dependencyOverrides.commonsCodec
resolutionStrategy.force dependencyOverrides.commonsIO
resolutionStrategy.force dependencyOverrides.commonsLang3
resolutionStrategy.force dependencyOverrides.jnrConstants
resolutionStrategy.force dependencyOverrides.jnrEnxio
resolutionStrategy.force dependencyOverrides.jnrPosix
resolutionStrategy.force dependencyOverrides.jodaTime
resolutionStrategy.force dependencyOverrides.slf4j
resolutionStrategy.force dependencyOverrides.jacksonDatabind
resolutionStrategy.force dependencyOverrides.guava
resolutionStrategy.force dependencyOverrides.findBugs
resolutionStrategy.force dependencyOverrides.jaksonCore
resolutionStrategy.force dependencyOverrides.assertj
}
// implementation implLibraries.swaggerV2Converter
compile project(':swagger2markup-asciidoc')
compile project(':swagger2markup-core')
implementation implLibraries.asciiDocJApi
implementation implLibraries.commonsText
implementation implLibraries.commonsBeanUtils
implementation implLibraries.slf4j
implementation implLibraries.swaggerV3
implementation implLibraries.commonsCollections4
implementation implLibraries.commonsConf2
implementation implLibraries.vavr
testImplementation testLibraries.assertj
testImplementation testLibraries.assertjDiff
testImplementation testLibraries.junit
testImplementation testLibraries.logback
}

View File

@@ -0,0 +1,380 @@
/*
* 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.
*/
package io.github.swagger2markup;
import io.github.swagger2markup.adoc.ast.impl.DocumentImpl;
import io.github.swagger2markup.config.Labels;
import io.github.swagger2markup.config.MarkupLanguage;
import io.github.swagger2markup.config.OpenAPILabels;
import io.github.swagger2markup.config.builder.OpenAPI2MarkupConfigBuilder;
import io.github.swagger2markup.extension.OpenAPI2MarkupExtensionRegistry;
import io.github.swagger2markup.extension.builder.OpenAPI2MarkupExtensionRegistryBuilder;
import io.github.swagger2markup.internal.document.ComponentsDocument;
import io.github.swagger2markup.internal.document.OverviewDocument;
import io.github.swagger2markup.internal.document.PathsDocument;
import io.github.swagger2markup.internal.document.SecurityDocument;
import io.github.swagger2markup.utils.URIUtils;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.parser.OpenAPIV3Parser;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.Validate;
import org.asciidoctor.ast.Document;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class OpenAPI2MarkupConverter extends AbstractSchema2MarkupConverter<OpenAPI> {
private final OverviewDocument overviewDocument;
private final PathsDocument pathsDocument;
private final ComponentsDocument componentsDocument;
private final SecurityDocument securityDocument;
private final OpenAPIContext openAPIContext;
public OpenAPI2MarkupConverter(OpenAPIContext context) {
super(context);
this.openAPIContext = context;
this.overviewDocument = new OverviewDocument(context);
this.pathsDocument = new PathsDocument(context);
this.componentsDocument = new ComponentsDocument(context);
this.securityDocument = new SecurityDocument(context);
}
/**
* Creates a OpenAPI2MarkupConverter.Builder from a URI.
*
* @param swaggerUri the URI
* @return a OpenAPI2MarkupConverter
*/
public static Builder from(URI swaggerUri) {
Validate.notNull(swaggerUri, "swaggerUri must not be null");
String scheme = swaggerUri.getScheme();
if (scheme != null && swaggerUri.getScheme().startsWith("http")) {
try {
return from(swaggerUri.toURL());
} catch (MalformedURLException e) {
throw new RuntimeException("Failed to convert URI to URL", e);
}
} else if (scheme != null && swaggerUri.getScheme().startsWith("file")) {
return from(Paths.get(swaggerUri));
} else {
return from(URIUtils.convertUriWithoutSchemeToFileScheme(swaggerUri));
}
}
/**
* Creates a OpenAPI2MarkupConverter.Builder using a remote URL.
*
* @param swaggerURL the remote URL
* @return a OpenAPI2MarkupConverter
*/
public static Builder from(URL swaggerURL) {
Validate.notNull(swaggerURL, "swaggerURL must not be null");
return new Builder(swaggerURL);
}
/**
* Creates a OpenAPI2MarkupConverter.Builder using a local Path.
*
* @param swaggerPath the local Path
* @return a OpenAPI2MarkupConverter
*/
public static Builder from(Path swaggerPath) {
Validate.notNull(swaggerPath, "swaggerPath must not be null");
if (Files.notExists(swaggerPath)) {
throw new IllegalArgumentException(String.format("swaggerPath does not exist: %s", swaggerPath));
}
try {
if (Files.isHidden(swaggerPath)) {
throw new IllegalArgumentException("swaggerPath must not be a hidden file");
}
} catch (IOException e) {
throw new RuntimeException("Failed to check if swaggerPath is a hidden file", e);
}
return new Builder(swaggerPath);
}
/**
* Creates a OpenAPI2MarkupConverter.Builder from a given Swagger model.
*
* @param openAPI the Swagger source.
* @return a OpenAPI2MarkupConverter
*/
public static Builder from(OpenAPI openAPI) {
Validate.notNull(openAPI, "schema must not be null");
return new Builder(openAPI);
}
/**
* Creates a OpenAPI2MarkupConverter.Builder from a given Swagger YAML or JSON String.
*
* @param swaggerString the Swagger YAML or JSON String.
* @return a OpenAPI2MarkupConverter
*/
public static Builder from(String swaggerString) {
Validate.notEmpty(swaggerString, "swaggerString must not be null");
return from(new StringReader(swaggerString));
}
/**
* Creates a OpenAPI2MarkupConverter.Builder from a given Swagger YAML or JSON reader.
*
* @param schemaReader the schema YAML or JSON reader.
* @return a OpenAPI2MarkupConverter
*/
public static Builder from(Reader schemaReader) {
Validate.notNull(schemaReader, "swaggerReader must not be null");
OpenAPI openAPI;
try {
//TODO
openAPI = new OpenAPIV3Parser().read(IOUtils.toString(schemaReader));
} catch (IOException e) {
throw new RuntimeException("Swagger source can not be parsed", e);
}
if (openAPI == null)
throw new IllegalArgumentException("Swagger source is in a wrong format");
return new Builder(openAPI);
}
@Override
public void toFolder(Path outputDirectory) {
Validate.notNull(outputDirectory, "outputDirectory must not be null");
openAPIContext.setOutputPath(outputDirectory);
writeToFile(applyOverviewDocument(), outputDirectory.resolve(openAPIContext.config.getOverviewDocument()));
writeToFile(applyPathsDocument(), outputDirectory.resolve(openAPIContext.config.getPathsDocument()));
writeToFile(applyComponentsDocument(), outputDirectory.resolve(openAPIContext.config.getDefinitionsDocument()));
writeToFile(applySecurityDocument(), outputDirectory.resolve(openAPIContext.config.getSecurityDocument()));
}
@Override
public void toFile(Path outputFile) {
Validate.notNull(outputFile, "outputFile must not be null");
writeToFile(applyOverviewDocument(), outputFile);
writeToFile(applyPathsDocument(), outputFile);
writeToFile(applyComponentsDocument(), outputFile);
writeToFile(applySecurityDocument(), outputFile);
}
@Override
public void toFileWithoutExtension(Path outputFile) {
Validate.notNull(outputFile, "outputFile must not be null");
writeToFileWithoutExtension(applyOverviewDocument(), outputFile);
writeToFileWithoutExtension(applyPathsDocument(), outputFile);
writeToFileWithoutExtension(applyComponentsDocument(), outputFile);
writeToFileWithoutExtension(applySecurityDocument(), outputFile);
}
@Override
public String toString() {
return applyOverviewDocument().convert() +
applyPathsDocument().convert() +
applyComponentsDocument().convert() +
applySecurityDocument().convert();
}
private Document applyOverviewDocument() {
return overviewDocument.apply(
openAPIContext.createDocument(),
OverviewDocument.parameters(openAPIContext.getSchema()));
}
private Document applyPathsDocument() {
return pathsDocument.apply(
openAPIContext.createDocument(),
PathsDocument.parameters(openAPIContext.getSchema()));
}
private Document applyComponentsDocument() {
return componentsDocument.apply(
openAPIContext.createDocument(),
ComponentsDocument.parameters(openAPIContext.getSchema().getComponents()));
}
private Document applySecurityDocument() {
return securityDocument.apply(
openAPIContext.createDocument(),
SecurityDocument.parameters(openAPIContext.getSchema()));
}
private void writeToFile(Document document, Path path) {
MarkupLanguage markupLanguage = openAPIContext.config.getMarkupLanguage();
if (isMarkupLanguageSupported(markupLanguage)) {
String fileExtension = markupLanguage.getFileNameExtensions().get(0);
writeToFileWithoutExtension(document, path.resolveSibling(path.getFileName().toString() + fileExtension));
} else {
throw new RuntimeException("Given Markup language '"+markupLanguage+"' is not supported by "+getClass().getName());
}
}
private boolean isMarkupLanguageSupported(MarkupLanguage markupLanguage) {
return markupLanguage == MarkupLanguage.ASCIIDOC;
}
private void writeToFileWithoutExtension(Document document, Path file) {
if (file.getParent() != null) {
try {
Files.createDirectories(file.getParent());
} catch (IOException e) {
throw new RuntimeException("Failed create directory", e);
}
}
try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) {
writer.write(document.convert());
} catch (IOException e) {
throw new RuntimeException("Failed to write file", e);
}
if (logger.isInfoEnabled()) {
logger.info("Markup document written to: {}", file);
}
}
public static class OpenAPIContext extends Context<OpenAPI> {
private OpenAPI2MarkupConfigBuilder.OpenSchema2MarkupConfig config;
private OpenAPI2MarkupExtensionRegistry extensionRegistry;
public OpenAPIContext(OpenAPI2MarkupConfigBuilder.OpenSchema2MarkupConfig config,
OpenAPI2MarkupExtensionRegistry extensionRegistry,
OpenAPI schema, URI swaggerLocation, Labels labels) {
super(config, extensionRegistry, schema, swaggerLocation, labels);
this.config = config;
this.extensionRegistry = extensionRegistry;
}
@Override
public OpenAPI2MarkupConfigBuilder.OpenSchema2MarkupConfig getConfig() {
return config;
}
@Override
public OpenAPI2MarkupExtensionRegistry getExtensionRegistry() {
return extensionRegistry;
}
public Document createDocument() {
return new DocumentImpl();
}
}
public static class Builder {
private final OpenAPI openAPI;
private final URI schemaLocation;
private OpenAPI2MarkupConfigBuilder.OpenSchema2MarkupConfig config;
private OpenAPI2MarkupExtensionRegistry extensionRegistry;
/**
* Creates a Builder from a remote URL.
*
* @param schemaUrl the remote URL
*/
Builder(URL schemaUrl) {
try {
this.schemaLocation = schemaUrl.toURI();
} catch (URISyntaxException e) {
throw new IllegalArgumentException("swaggerURL is in a wrong format", e);
}
this.openAPI = readSchema(schemaUrl.toString());
}
/**
* Creates a Builder from a local Path.
*
* @param swaggerPath the local Path
*/
Builder(Path swaggerPath) {
this.schemaLocation = swaggerPath.toAbsolutePath().toUri();
this.openAPI = readSchema(swaggerPath.toString());
}
/**
* Creates a Builder using a given Swagger model.
*
* @param openAPI the Swagger source.
*/
Builder(OpenAPI openAPI) {
this.openAPI = openAPI;
this.schemaLocation = null;
}
/**
* Uses the SwaggerParser to read the Swagger source.
*
* @param schemaLocation the location of the Swagger source
* @return the Swagger model
*/
private OpenAPI readSchema(String schemaLocation) {
OpenAPI openAPI = new OpenAPIV3Parser().read(schemaLocation);
if (openAPI == null) {
throw new IllegalArgumentException("Failed to read the schema");
}
return openAPI;
}
public Builder withConfig(OpenAPI2MarkupConfigBuilder.OpenSchema2MarkupConfig config) {
Validate.notNull(config, "config must not be null");
this.config = config;
return this;
}
public Builder withExtensionRegistry(OpenAPI2MarkupExtensionRegistry registry) {
Validate.notNull(registry, "registry must not be null");
this.extensionRegistry = registry;
return this;
}
public OpenAPI2MarkupConverter build() {
if (config == null)
config = new OpenAPI2MarkupConfigBuilder().build();
if (extensionRegistry == null)
extensionRegistry = new OpenAPI2MarkupExtensionRegistryBuilder().build();
OpenAPILabels openApiLabels = new OpenAPILabels(config);
OpenAPIContext context = new OpenAPIContext(config, extensionRegistry, openAPI, schemaLocation, openApiLabels);
initExtensions(context);
applySwaggerExtensions(context);
return new OpenAPI2MarkupConverter(context);
}
private void initExtensions(OpenAPIContext context) {
extensionRegistry.getSwaggerModelExtensions().forEach(extension -> extension.setGlobalContext(context));
extensionRegistry.getOverviewDocumentExtensions().forEach(extension -> extension.setGlobalContext(context));
extensionRegistry.getDefinitionsDocumentExtensions().forEach(extension -> extension.setGlobalContext(context));
extensionRegistry.getPathsDocumentExtensions().forEach(extension -> extension.setGlobalContext(context));
extensionRegistry.getSecurityDocumentExtensions().forEach(extension -> extension.setGlobalContext(context));
}
private void applySwaggerExtensions(OpenAPIContext context) {
extensionRegistry.getSwaggerModelExtensions().forEach(extension -> extension.apply(context.getSchema()));
}
}
}

View File

@@ -0,0 +1,36 @@
/*
* 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.
*/
package io.github.swagger2markup;
import org.apache.commons.configuration2.Configuration;
import java.util.Map;
import java.util.Properties;
public class OpenAPI2MarkupProperties extends Schema2MarkupProperties {
public OpenAPI2MarkupProperties(Properties properties) {
super(properties);
}
public OpenAPI2MarkupProperties(Map<String, String> map) {
super(map);
}
public OpenAPI2MarkupProperties(Configuration configuration) {
super(configuration);
}
}

View File

@@ -0,0 +1,71 @@
package io.github.swagger2markup.config;
import io.github.swagger2markup.config.builder.OpenAPI2MarkupConfigBuilder;
import java.util.ResourceBundle;
public class OpenAPILabels extends Labels {
public static final String LABEL_CONTENT = "label_content";
public static final String LABEL_DEFAULT = "label_default";
public static final String LABEL_DEPRECATED = "label_deprecated";
public static final String LABEL_EXAMPLE = "label_example";
public static final String LABEL_EXAMPLES = "label_examples";
public static final String LABEL_EXCLUSIVE_MAXIMUM = "label_exclusive_maximum";
public static final String LABEL_EXCLUSIVE_MINIMUM = "label_exclusive_minimum";
public static final String LABEL_EXTERNAL_VALUE = "label_external_value";
public static final String LABEL_FORMAT = "label_format";
public static final String LABEL_MAXIMUM = "label_maximum";
public static final String LABEL_MAX_ITEMS = "label_max_items";
public static final String LABEL_MAX_LENGTH = "label_max_length";
public static final String LABEL_MAX_PROPERTIES = "label_max_properties";
public static final String LABEL_MINIMUM = "label_minimum";
public static final String LABEL_MIN_ITEMS = "label_min_items";
public static final String LABEL_MIN_LENGTH = "label_min_length";
public static final String LABEL_MIN_PROPERTIES = "label_min_properties";
public static final String LABEL_MULTIPLE_OF = "label_multiple_of";
public static final String LABEL_NO_LINKS = "label_no_links";
public static final String LABEL_NULLABLE = "label_nullable";
public static final String LABEL_OPERATION = "label_operation";
public static final String LABEL_OPTIONAL = "label_optional";
public static final String LABEL_PARAMETERS = "label_parameters";
public static final String LABEL_READ_ONLY = "label_read_only";
public static final String LABEL_REQUIRED = "label_required";
public static final String LABEL_SERVER = "label_server";
public static final String LABEL_TERMS_OF_SERVICE = "label_terms_of_service";
public static final String LABEL_TITLE = "label_title";
public static final String LABEL_TYPE = "label_type";
public static final String LABEL_UNIQUE_ITEMS = "label_unique_items";
public static final String LABEL_WRITE_ONLY = "label_write_only";
public static final String SECTION_TITLE_COMPONENTS = "section_title_components";
public static final String SECTION_TITLE_PARAMETERS = "section_title_parameters";
public static final String SECTION_TITLE_PATHS = "section_title_paths";
public static final String SECTION_TITLE_SCHEMAS = "section_title_schemas";
public static final String SECTION_TITLE_SECURITY = "section_title_security";
public static final String SECTION_TITLE_SERVERS = "section_title_servers";
public static final String SECTION_TITLE_OVERVIEW = "section_title_overview";
public static final String SECTION_TITLE_TAGS = "section_title_tags";
public static final String SECTION_TITLE_RESPONSES = "section_title_responses";
public static final String SECTION_TITLE_HEADERS = "section_title_headers";
public static final String SECTION_TITLE_LINKS = "section_title_links";
public static final String TABLE_HEADER_DEFAULT = "table_header_default";
public static final String TABLE_HEADER_DESCRIPTION = "table_header_description";
public static final String TABLE_HEADER_HTTP_CODE = "table_header_http_code";
public static final String TABLE_HEADER_LINKS = "table_header_links";
public static final String TABLE_HEADER_NAME = "table_header_name";
public static final String TABLE_HEADER_POSSIBLE_VALUES = "table_header_possible_values";
public static final String TABLE_HEADER_SCHEMA = "table_header_schema";
public static final String TABLE_HEADER_SCOPES = "table_header_scopes";
public static final String TABLE_HEADER_TYPE = "table_header_type";
public static final String TABLE_HEADER_VARIABLE = "table_header_variable";
public static final String TABLE_TITLE_HEADERS = "table_title_headers";
public static final String TABLE_TITLE_PARAMETERS = "table_title_parameters";
public static final String TABLE_TITLE_PROPERTIES = "table_title_properties";
public static final String TABLE_TITLE_RESPONSES = "table_title_responses";
public static final String TABLE_TITLE_SECURITY = "table_title_security";
public static final String TABLE_TITLE_SERVER_VARIABLES = "table_title_server_variables";
public OpenAPILabels(OpenAPI2MarkupConfigBuilder.OpenSchema2MarkupConfig config) {
super(ResourceBundle.getBundle("io/github/swagger2markup/lang/labels", config.getLanguage().toLocale()));
}
}

View File

@@ -0,0 +1,48 @@
package io.github.swagger2markup.config.builder;
import io.github.swagger2markup.OpenAPI2MarkupProperties;
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.configuration2.ConfigurationConverter;
import org.apache.commons.configuration2.MapConfiguration;
import org.apache.commons.configuration2.PropertiesConfiguration;
import java.util.Map;
import java.util.Properties;
public class OpenAPI2MarkupConfigBuilder extends Schema2MarkupConfigBuilder {
private OpenSchema2MarkupConfig openApi2MarkupConfig;
public OpenAPI2MarkupConfigBuilder() {
this(new PropertiesConfiguration());
}
public OpenAPI2MarkupConfigBuilder(Properties properties) {
this(ConfigurationConverter.getConfiguration(properties));
}
public OpenAPI2MarkupConfigBuilder(Map<String, String> map) {
this(new MapConfiguration(map));
}
private OpenAPI2MarkupConfigBuilder(Configuration configuration) {
super(new OpenAPI2MarkupProperties(getCompositeConfiguration(configuration)), configuration);
}
@Override
public DefaultSchema2MarkupConfig createConfigInstance() {
if(openApi2MarkupConfig == null) {
openApi2MarkupConfig = new OpenSchema2MarkupConfig();
}
return openApi2MarkupConfig;
}
@Override
public OpenSchema2MarkupConfig build() {
buildNaturalOrdering();
return openApi2MarkupConfig;
}
public static class OpenSchema2MarkupConfig extends DefaultSchema2MarkupConfig {
}
}

View File

@@ -0,0 +1,36 @@
/*
* 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.
*/
package io.github.swagger2markup.extension;
import io.github.swagger2markup.OpenAPI2MarkupConverter.OpenAPIContext;
/**
* An abstract OpenAPI extension which must be extended by an other OpenAPI extensions
*/
abstract class AbstractExtension implements Extension {
protected OpenAPIContext globalContext;
/**
* Global context lazy initialization
*
* @param globalContext Global context
*/
public void setGlobalContext(OpenAPIContext globalContext) {
this.globalContext = globalContext;
}
}

View File

@@ -0,0 +1,15 @@
package io.github.swagger2markup.extension;
import org.asciidoctor.ast.Document;
public class ContentContext {
private Document document;
public ContentContext(Document document) {
this.document = document;
}
public Document getDocument() {
return document;
}
}

View File

@@ -0,0 +1,92 @@
/*
* 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.
*/
package io.github.swagger2markup.extension;
import io.swagger.models.Model;
import org.apache.commons.lang3.Validate;
import org.asciidoctor.ast.Document;
import java.util.Optional;
/**
* DefinitionsDocumentExtension extension point can be used to extend the definitions document content.
*/
public abstract class DefinitionsDocumentExtension extends AbstractExtension {
public abstract void apply(Context context);
public enum Position {
DOCUMENT_BEFORE,
DOCUMENT_BEGIN,
DOCUMENT_END,
DOCUMENT_AFTER,
DEFINITION_BEFORE,
DEFINITION_BEGIN,
DEFINITION_END,
DEFINITION_AFTER
}
public static class Context extends ContentContext {
private Position position;
/**
* null if position == DOCUMENT_*
*/
private String definitionName;
/**
* null if position == DOCUMENT_*
*/
private Model model;
/**
* @param position the current position
*/
public Context(Position position, Document document) {
super(document);
Validate.inclusiveBetween(Position.DOCUMENT_BEFORE, Position.DOCUMENT_AFTER, position);
this.position = position;
}
/**
* @param position the current position
* @param definitionName the name of the current definition
* @param model the current Model of the definition
*/
public Context(Position position, Document document, String definitionName, Model model) {
super(document);
Validate.inclusiveBetween(Position.DEFINITION_BEFORE, Position.DEFINITION_AFTER, position);
Validate.notNull(definitionName);
Validate.notNull(model);
this.position = position;
this.definitionName = definitionName;
this.model = model;
}
public Position getPosition() {
return position;
}
public Optional<String> getDefinitionName() {
return Optional.ofNullable(definitionName);
}
public Optional<Model> getModel() {
return Optional.ofNullable(model);
}
}
}

View File

@@ -0,0 +1,33 @@
/*
* 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.
*/
package io.github.swagger2markup.extension;
import static io.github.swagger2markup.OpenAPI2MarkupConverter.OpenAPIContext;
/**
* Extension interface which must be implemented by an OpenAPI extension
*/
interface Extension {
/**
* Global context lazy initialization
*
* @param globalContext Global context
*/
void setGlobalContext(OpenAPIContext globalContext);
}

View File

@@ -0,0 +1,41 @@
/*
* 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.
*/
package io.github.swagger2markup.extension;
import io.github.swagger2markup.config.builder.OpenAPI2MarkupConfigBuilder;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.config.Labels;
import io.swagger.v3.oas.models.OpenAPI;
import io.vavr.Function2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class MarkupComponent<D, T, R> implements Function2<D, T, R> {
protected Logger logger = LoggerFactory.getLogger(getClass());
protected OpenAPI2MarkupConverter.Context<OpenAPI> context;
protected Labels labels;
protected OpenAPI2MarkupConfigBuilder.OpenSchema2MarkupConfig config;
protected OpenAPI2MarkupExtensionRegistry extensionRegistry;
public MarkupComponent(OpenAPI2MarkupConverter.OpenAPIContext context) {
this.context = context;
this.config = context.getConfig();
this.extensionRegistry = context.getExtensionRegistry();
this.labels = context.getLabels();
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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.
*/
package io.github.swagger2markup.extension;
import java.util.List;
/**
* Extension points registry interface.
*/
public interface OpenAPI2MarkupExtensionRegistry extends Schema2MarkupExtensionRegistry {
/**
* OpenAPIModelExtension extension point can be used to preprocess the Swagger model.
*
* @return registered extensions extending OpenAPIModelExtension extension point
*/
List<OpenAPIModelExtension> getSwaggerModelExtensions();
/**
* OverviewDocumentExtension extension point can be used to extend the overview document content.
*
* @return registered extensions extending OverviewDocumentExtension extension point
*/
List<OverviewDocumentExtension> getOverviewDocumentExtensions();
/**
* DefinitionsDocumentExtension extension point can be used to extend the definitions document content.
*
* @return registered extensions extending DefinitionsDocumentExtension extension point
*/
List<DefinitionsDocumentExtension> getDefinitionsDocumentExtensions();
/**
* SecurityContentExtension extension point can be used to extend the security document content.
*
* @return registered extensions extending SecurityContentExtension extension point
*/
List<SecurityDocumentExtension> getSecurityDocumentExtensions();
/**
* PathsDocumentExtension extension point can be used to extend the paths document content.
*
* @return registered extensions extending PathsDocumentExtension extension point
*/
List<PathsDocumentExtension> getPathsDocumentExtensions();
}

View File

@@ -0,0 +1,28 @@
/*
* 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.
*/
package io.github.swagger2markup.extension;
import io.swagger.v3.oas.models.OpenAPI;
/**
* OpenAPIModelExtension extension point can be used to preprocess the Swagger model.
*/
public abstract class OpenAPIModelExtension extends AbstractExtension {
public abstract void apply(OpenAPI openAPI);
}

View File

@@ -0,0 +1,51 @@
/*
* 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.
*/
package io.github.swagger2markup.extension;
import org.asciidoctor.ast.Document;
/**
* OverviewDocumentExtension extension point can be used to extend the overview document content.
*/
public abstract class OverviewDocumentExtension extends AbstractExtension {
public abstract void apply(Context context);
public enum Position {
DOCUMENT_BEFORE,
DOCUMENT_AFTER,
DOCUMENT_BEGIN,
DOCUMENT_END
}
public static class Context extends ContentContext {
private Position position;
/**
* @param position the current position
*/
public Context(Position position, Document document) {
super(document);
this.position = position;
}
public Position getPosition() {
return position;
}
}
}

View File

@@ -0,0 +1,101 @@
/*
* 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.
*/
package io.github.swagger2markup.extension;
import io.github.swagger2markup.model.PathOperation;
import org.apache.commons.lang3.Validate;
import org.asciidoctor.ast.Document;
import java.util.Optional;
/**
* PathsDocumentExtension extension point can be used to extend the paths document content.
*/
public abstract class PathsDocumentExtension extends AbstractExtension {
public abstract void apply(Context context);
public enum Position {
DOCUMENT_BEFORE,
DOCUMENT_BEGIN,
DOCUMENT_END,
DOCUMENT_AFTER,
OPERATION_BEFORE,
OPERATION_BEGIN,
OPERATION_END,
OPERATION_AFTER,
OPERATION_DESCRIPTION_BEFORE,
OPERATION_DESCRIPTION_BEGIN,
OPERATION_DESCRIPTION_END,
OPERATION_DESCRIPTION_AFTER,
OPERATION_PARAMETERS_BEFORE,
OPERATION_PARAMETERS_BEGIN,
OPERATION_PARAMETERS_END,
OPERATION_PARAMETERS_AFTER,
OPERATION_RESPONSES_BEFORE,
OPERATION_RESPONSES_BEGIN,
OPERATION_RESPONSES_END,
OPERATION_RESPONSES_AFTER,
OPERATION_SECURITY_BEFORE,
OPERATION_SECURITY_BEGIN,
OPERATION_SECURITY_END,
OPERATION_SECURITY_AFTER
}
public static class Context extends ContentContext {
private Position position;
/**
* null if position == DOCUMENT_*
*/
private PathOperation operation;
/**
* Context for positions DOCUMENT_*
*
* @param position the current position
* @param document document object
*/
public Context(Position position, Document document) {
super(document);
Validate.inclusiveBetween(Position.DOCUMENT_BEFORE, Position.DOCUMENT_AFTER, position);
this.position = position;
}
/**
* Context for all other positions
*
* @param position the current position
* @param document document object
* @param operation the current path operation
*/
public Context(Position position, Document document, PathOperation operation) {
super(document);
Validate.inclusiveBetween(Position.OPERATION_BEFORE, Position.OPERATION_SECURITY_AFTER, position);
Validate.notNull(operation);
this.position = position;
this.operation = operation;
}
public Position getPosition() {
return position;
}
public Optional<PathOperation> getOperation() {
return Optional.ofNullable(operation);
}
}
}

View File

@@ -0,0 +1,94 @@
/*
* 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.
*/
package io.github.swagger2markup.extension;
import io.swagger.models.auth.SecuritySchemeDefinition;
import org.apache.commons.lang3.Validate;
import org.asciidoctor.ast.Document;
import java.util.Optional;
/**
* SecurityContentExtension extension point can be used to extend the security document content.
*/
public abstract class SecurityDocumentExtension extends AbstractExtension {
public abstract void apply(Context context);
public enum Position {
DOCUMENT_BEFORE,
DOCUMENT_BEGIN,
DOCUMENT_END,
DOCUMENT_AFTER,
SECURITY_SCHEME_BEFORE,
SECURITY_SCHEME_BEGIN,
SECURITY_SCHEME_END,
SECURITY_SCHEME_AFTER
}
public static class Context extends ContentContext {
private Position position;
/**
* null if position == DOCUMENT_*
*/
private String securitySchemeName;
/**
* null if position == DOCUMENT_*
*/
private SecuritySchemeDefinition securityScheme;
/**
* @param position the current position
* @param document the MarkupDocBuilder
*/
public Context(Position position, Document document) {
super(document);
Validate.inclusiveBetween(Position.DOCUMENT_BEFORE, Position.DOCUMENT_AFTER, position);
this.position = position;
}
/**
* @param position the current position
* @param document the MarkupDocBuilder
* @param securitySchemeName the name of the current securityScheme
* @param securityScheme the current security scheme securityScheme
*/
public Context(Position position, Document document, String securitySchemeName, SecuritySchemeDefinition securityScheme) {
super(document);
Validate.inclusiveBetween(Position.SECURITY_SCHEME_BEFORE, Position.SECURITY_SCHEME_AFTER, position);
Validate.notNull(securitySchemeName);
Validate.notNull(securityScheme);
this.position = position;
this.securitySchemeName = securitySchemeName;
this.securityScheme = securityScheme;
}
public Position getPosition() {
return position;
}
public Optional<String> getSecuritySchemeName() {
return Optional.ofNullable(securitySchemeName);
}
public Optional<SecuritySchemeDefinition> getSecurityScheme() {
return Optional.ofNullable(securityScheme);
}
}
}

View File

@@ -0,0 +1,127 @@
/*
* 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.
*/
package io.github.swagger2markup.extension.builder;
import io.github.swagger2markup.extension.*;
import java.util.List;
import static java.util.ServiceLoader.load;
import static org.apache.commons.collections4.IteratorUtils.toList;
public class OpenAPI2MarkupExtensionRegistryBuilder {
private final Context context;
public OpenAPI2MarkupExtensionRegistryBuilder() {
List<OpenAPIModelExtension> openAPIModelExtensions = toList(load(OpenAPIModelExtension.class).iterator());
List<OverviewDocumentExtension> overviewDocumentExtensions = toList(load(OverviewDocumentExtension.class).iterator());
List<DefinitionsDocumentExtension> definitionsDocumentExtensions = toList(load(DefinitionsDocumentExtension.class).iterator());
List<PathsDocumentExtension> pathsDocumentExtensions = toList(load(PathsDocumentExtension.class).iterator());
List<SecurityDocumentExtension> securityDocumentExtensions = toList(load(SecurityDocumentExtension.class).iterator());
context = new Context(
openAPIModelExtensions,
overviewDocumentExtensions,
definitionsDocumentExtensions,
pathsDocumentExtensions,
securityDocumentExtensions);
}
public OpenAPI2MarkupExtensionRegistry build() {
return new DefaultOpenAPI2MarkupExtensionRegistry(context);
}
public OpenAPI2MarkupExtensionRegistryBuilder withSwaggerModelExtension(OpenAPIModelExtension extension) {
context.openAPIModelExtensions.add(extension);
return this;
}
public OpenAPI2MarkupExtensionRegistryBuilder withOverviewDocumentExtension(OverviewDocumentExtension extension) {
context.overviewDocumentExtensions.add(extension);
return this;
}
public OpenAPI2MarkupExtensionRegistryBuilder withDefinitionsDocumentExtension(DefinitionsDocumentExtension extension) {
context.definitionsDocumentExtensions.add(extension);
return this;
}
public OpenAPI2MarkupExtensionRegistryBuilder withPathsDocumentExtension(PathsDocumentExtension extension) {
context.pathsDocumentExtensions.add(extension);
return this;
}
public OpenAPI2MarkupExtensionRegistryBuilder withSecurityDocumentExtension(SecurityDocumentExtension extension) {
context.securityDocumentExtensions.add(extension);
return this;
}
static class DefaultOpenAPI2MarkupExtensionRegistry implements OpenAPI2MarkupExtensionRegistry {
private Context context;
DefaultOpenAPI2MarkupExtensionRegistry(Context context) {
this.context = context;
}
@Override
public List<OpenAPIModelExtension> getSwaggerModelExtensions() {
return context.openAPIModelExtensions;
}
@Override
public List<OverviewDocumentExtension> getOverviewDocumentExtensions() {
return context.overviewDocumentExtensions;
}
@Override
public List<DefinitionsDocumentExtension> getDefinitionsDocumentExtensions() {
return context.definitionsDocumentExtensions;
}
@Override
public List<SecurityDocumentExtension> getSecurityDocumentExtensions() {
return context.securityDocumentExtensions;
}
@Override
public List<PathsDocumentExtension> getPathsDocumentExtensions() {
return context.pathsDocumentExtensions;
}
}
private static class Context {
final List<OpenAPIModelExtension> openAPIModelExtensions;
final List<OverviewDocumentExtension> overviewDocumentExtensions;
final List<DefinitionsDocumentExtension> definitionsDocumentExtensions;
final List<PathsDocumentExtension> pathsDocumentExtensions;
final List<SecurityDocumentExtension> securityDocumentExtensions;
Context(List<OpenAPIModelExtension> openAPIModelExtensions,
List<OverviewDocumentExtension> overviewDocumentExtensions,
List<DefinitionsDocumentExtension> definitionsDocumentExtensions,
List<PathsDocumentExtension> pathsDocumentExtensions,
List<SecurityDocumentExtension> securityDocumentExtensions) {
this.openAPIModelExtensions = openAPIModelExtensions;
this.overviewDocumentExtensions = overviewDocumentExtensions;
this.definitionsDocumentExtensions = definitionsDocumentExtensions;
this.pathsDocumentExtensions = pathsDocumentExtensions;
this.securityDocumentExtensions = securityDocumentExtensions;
}
}
}

View File

@@ -0,0 +1,101 @@
/*
* 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.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.DescriptionListEntryImpl;
import io.github.swagger2markup.adoc.ast.impl.DescriptionListImpl;
import io.github.swagger2markup.adoc.ast.impl.ListItemImpl;
import io.github.swagger2markup.adoc.ast.impl.ParagraphBlockImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import io.swagger.v3.oas.models.media.Encoding;
import org.apache.commons.lang3.StringUtils;
import org.asciidoctor.ast.StructuralNode;
import java.util.Collections;
import java.util.Map;
import static io.github.swagger2markup.adoc.converter.internal.Delimiters.LINE_SEPARATOR;
import static io.github.swagger2markup.config.OpenAPILabels.LABEL_EXAMPLES;
import static io.github.swagger2markup.internal.helper.OpenApiHelpers.italicUnconstrained;
public class EncodingComponent extends MarkupComponent<StructuralNode, EncodingComponent.Parameters, StructuralNode> {
private final HeadersComponent headersComponent;
public EncodingComponent(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
this.headersComponent = new HeadersComponent(context);
}
public static EncodingComponent.Parameters parameters(Map<String, Encoding> encodings) {
return new EncodingComponent.Parameters(encodings);
}
public StructuralNode apply(StructuralNode node, Map<String, Encoding> encodings) {
return apply(node, parameters(encodings));
}
@Override
public StructuralNode apply(StructuralNode node, EncodingComponent.Parameters parameters) {
Map<String, Encoding> encodings = parameters.encodings;
if (encodings == null || encodings.isEmpty()) return node;
DescriptionListImpl encodingList = new DescriptionListImpl(node);
encodingList.setTitle(labels.getLabel(LABEL_EXAMPLES));
encodings.forEach((name, encoding) -> {
DescriptionListEntryImpl encodingEntry = new DescriptionListEntryImpl(encodingList, Collections.singletonList(new ListItemImpl(encodingList, name)));
ListItemImpl tagDesc = new ListItemImpl(encodingEntry, "");
ParagraphBlockImpl encodingBlock = new ParagraphBlockImpl(tagDesc);
StringBuilder sb = new StringBuilder();
String contentType = encoding.getContentType();
if(StringUtils.isNotBlank(contentType)){
sb.append("Content-Type:").append(contentType).append(LINE_SEPARATOR);
}
if(encoding.getAllowReserved()){
sb.append(italicUnconstrained("Allow Reserved").toLowerCase()).append(LINE_SEPARATOR);
}
if(encoding.getExplode()){
sb.append(italicUnconstrained("Explode").toLowerCase()).append(LINE_SEPARATOR);
}
Encoding.StyleEnum style = encoding.getStyle();
if(style != null){
sb.append("style").append(style).append(LINE_SEPARATOR);
}
encodingBlock.setSource(sb.toString());
tagDesc.append(encodingBlock);
headersComponent.apply(tagDesc, encoding.getHeaders());
encodingEntry.setDescription(tagDesc);
encodingList.addEntry(encodingEntry);
});
node.append(encodingList);
return node;
}
public static class Parameters {
private final Map<String, Encoding> encodings;
public Parameters(Map<String, Encoding> encodings) {
this.encodings = encodings;
}
}
}

View File

@@ -0,0 +1,108 @@
/*
* 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.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.DescriptionListEntryImpl;
import io.github.swagger2markup.adoc.ast.impl.DescriptionListImpl;
import io.github.swagger2markup.adoc.ast.impl.ListItemImpl;
import io.github.swagger2markup.adoc.ast.impl.ParagraphBlockImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import io.swagger.v3.oas.models.examples.Example;
import org.apache.commons.lang3.StringUtils;
import org.asciidoctor.ast.StructuralNode;
import java.util.Collections;
import java.util.Map;
import static io.github.swagger2markup.adoc.converter.internal.Delimiters.LINE_SEPARATOR;
import static io.github.swagger2markup.config.OpenAPILabels.LABEL_EXAMPLES;
import static io.github.swagger2markup.config.OpenAPILabels.LABEL_EXTERNAL_VALUE;
import static io.github.swagger2markup.internal.helper.OpenApiHelpers.appendDescription;
public class ExamplesComponent extends MarkupComponent<StructuralNode, ExamplesComponent.Parameters, StructuralNode> {
private final MediaTypeExampleComponent mediaTypeExampleComponent;
public ExamplesComponent(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
this.mediaTypeExampleComponent = new MediaTypeExampleComponent(context);
}
public static ExamplesComponent.Parameters parameters(Map<String, Example> examples) {
return new ExamplesComponent.Parameters(examples);
}
public StructuralNode apply(StructuralNode node, Map<String, Example> examples) {
return apply(node, parameters(examples));
}
@Override
public StructuralNode apply(StructuralNode node, ExamplesComponent.Parameters parameters) {
Map<String, Example> examples = parameters.examples;
if (examples == null || examples.isEmpty()) return node;
DescriptionListImpl examplesList = new DescriptionListImpl(node);
examplesList.setTitle(labels.getLabel(LABEL_EXAMPLES));
examples.forEach((name, example) -> {
DescriptionListEntryImpl exampleEntry = new DescriptionListEntryImpl(examplesList, Collections.singletonList(new ListItemImpl(examplesList, name)));
ListItemImpl tagDesc = new ListItemImpl(exampleEntry, "");
ParagraphBlockImpl exampleBlock = new ParagraphBlockImpl(tagDesc);
appendDescription(exampleBlock, example.getSummary());
appendDescription(exampleBlock, example.getDescription());
mediaTypeExampleComponent.apply(tagDesc, example.getValue());
ParagraphBlockImpl paragraphBlock = new ParagraphBlockImpl(tagDesc);
String source = "";
generateRefLink(source, example.getExternalValue(), labels.getLabel(LABEL_EXTERNAL_VALUE));
generateRefLink(source, example.get$ref(), "");
if(StringUtils.isNotBlank(source)){
paragraphBlock.setSource(source);
tagDesc.append(paragraphBlock);
}
exampleEntry.setDescription(tagDesc);
examplesList.addEntry(exampleEntry);
});
node.append(examplesList);
return node;
}
private String generateRefLink(String source, String ref, String alt) {
if (StringUtils.isNotBlank(ref)) {
if (StringUtils.isBlank(alt)) {
alt = ref.substring(ref.lastIndexOf('/') + 1);
}
String anchor = ref.replaceFirst("#", "").replaceAll("/", "_");
source += "<<" + anchor + "," + alt + ">>" + LINE_SEPARATOR;
}
return source;
}
public static class Parameters {
private final Map<String, Example> examples;
public Parameters(Map<String, Example> examples) {
this.examples = examples;
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* 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.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.extension.MarkupComponent;
import io.github.swagger2markup.adoc.ast.impl.ParagraphBlockImpl;
import io.swagger.v3.oas.models.ExternalDocumentation;
import org.apache.commons.lang3.StringUtils;
import org.asciidoctor.ast.Block;
import org.asciidoctor.ast.StructuralNode;
public class ExternalDocumentationComponent extends MarkupComponent<StructuralNode, ExternalDocumentationComponent.Parameters, StructuralNode> {
public ExternalDocumentationComponent(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
}
public static Parameters parameters(ExternalDocumentation externalDocs) {
return new Parameters(externalDocs);
}
public StructuralNode apply(StructuralNode node, ExternalDocumentation externalDocs) {
return apply(node, parameters(externalDocs));
}
@Override
public StructuralNode apply(StructuralNode node, Parameters params) {
ExternalDocumentation externalDocs = params.externalDocs;
if (externalDocs == null) return node;
String url = externalDocs.getUrl();
if (StringUtils.isNotBlank(url)) {
Block paragraph = new ParagraphBlockImpl(node);
String desc = externalDocs.getDescription();
paragraph.setSource(url + (StringUtils.isNotBlank(desc) ? "[" + desc + "]" : ""));
node.append(paragraph);
}
return node;
}
public static class Parameters {
private final ExternalDocumentation externalDocs;
public Parameters(ExternalDocumentation externalDocs) {
this.externalDocs = externalDocs;
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* 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.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.TableImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import io.swagger.v3.oas.models.headers.Header;
import org.asciidoctor.ast.StructuralNode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import static io.github.swagger2markup.config.OpenAPILabels.*;
import static io.github.swagger2markup.internal.helper.OpenApiHelpers.generateInnerDoc;
import static io.github.swagger2markup.internal.helper.OpenApiHelpers.getSchemaTypeAsString;
public class HeadersComponent extends MarkupComponent<StructuralNode, HeadersComponent.Parameters, StructuralNode> {
private final SchemaComponent schemaComponent;
public HeadersComponent(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
this.schemaComponent = new SchemaComponent(context);
}
public static HeadersComponent.Parameters parameters(Map<String, Header> headers) {
return new HeadersComponent.Parameters(headers);
}
public StructuralNode apply(StructuralNode node, Map<String, Header> headers) {
return apply(node, parameters(headers));
}
@Override
public StructuralNode apply(StructuralNode node, HeadersComponent.Parameters parameters) {
Map<String, Header> headers = parameters.headers;
if (null == headers || headers.isEmpty()) return node;
TableImpl responseHeadersTable = new TableImpl(node, new HashMap<>(), new ArrayList<>());
responseHeadersTable.setOption("header");
responseHeadersTable.setAttribute("caption", "", true);
responseHeadersTable.setAttribute("cols", ".^2a,.^14a,.^4a", true);
responseHeadersTable.setTitle(labels.getLabel(TABLE_TITLE_HEADERS));
responseHeadersTable.setHeaderRow(labels.getLabel(TABLE_HEADER_NAME), labels.getLabel(TABLE_HEADER_DESCRIPTION), labels.getLabel(TABLE_HEADER_SCHEMA));
headers.forEach((name, header) ->
responseHeadersTable.addRow(
generateInnerDoc(responseHeadersTable, name),
generateInnerDoc(responseHeadersTable, Optional.ofNullable(header.getDescription()).orElse("")),
generateInnerDoc(responseHeadersTable, getSchemaTypeAsString(header.getSchema()))
));
node.append(responseHeadersTable);
return node;
}
public static class Parameters {
private final Map<String, Header> headers;
public Parameters(Map<String, Header> headers) {
this.headers = headers;
}
}
}

View File

@@ -0,0 +1,82 @@
/*
* 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.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.DocumentImpl;
import io.github.swagger2markup.adoc.ast.impl.ParagraphBlockImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import io.swagger.v3.oas.models.links.Link;
import org.asciidoctor.ast.Document;
import org.asciidoctor.ast.StructuralNode;
import java.util.Map;
import static io.github.swagger2markup.adoc.converter.internal.Delimiters.LINE_SEPARATOR;
import static io.github.swagger2markup.config.OpenAPILabels.*;
import static io.github.swagger2markup.internal.helper.OpenApiHelpers.italicUnconstrained;
public class LinkComponent extends MarkupComponent<StructuralNode, LinkComponent.Parameters, StructuralNode> {
public LinkComponent(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
}
public static LinkComponent.Parameters parameters(Map<String, Link> links) {
return new LinkComponent.Parameters(links);
}
public Document apply(StructuralNode parent, Map<String, Link> links) {
return apply(parent, parameters(links));
}
@Override
public Document apply(StructuralNode parent, LinkComponent.Parameters parameters) {
DocumentImpl linksDocument = new DocumentImpl(parent);
ParagraphBlockImpl linkParagraph = new ParagraphBlockImpl(linksDocument);
Map<String, Link> links = parameters.links;
if (null == links || links.isEmpty()) {
linkParagraph.setSource(labels.getLabel(LABEL_NO_LINKS));
} else {
StringBuilder sb = new StringBuilder();
links.forEach((name, link) -> {
sb.append(name).append(" +").append(LINE_SEPARATOR);
sb.append(italicUnconstrained(labels.getLabel(LABEL_OPERATION))).append(' ')
.append(italicUnconstrained(link.getOperationId())).append(" +").append(LINE_SEPARATOR);
Map<String, String> linkParameters = link.getParameters();
if (null != linkParameters && !linkParameters.isEmpty()) {
sb.append(italicUnconstrained(labels.getLabel(LABEL_PARAMETERS))).append(" {").append(" +").append(LINE_SEPARATOR);
linkParameters.forEach((param, value) ->
sb.append('"').append(param).append("\": \"").append(value).append('"').append(" +").append(LINE_SEPARATOR)
);
sb.append('}').append(" +").append(LINE_SEPARATOR);
}
});
linkParagraph.setSource(sb.toString());
}
linksDocument.append(linkParagraph);
return linksDocument;
}
public static class Parameters {
private final Map<String, Link> links;
public Parameters(Map<String, Link> links) {
this.links = links;
}
}
}

View File

@@ -0,0 +1,87 @@
/*
* 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.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.DescriptionListEntryImpl;
import io.github.swagger2markup.adoc.ast.impl.DescriptionListImpl;
import io.github.swagger2markup.adoc.ast.impl.ListItemImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import io.swagger.v3.oas.models.media.Content;
import org.asciidoctor.ast.Document;
import org.asciidoctor.ast.StructuralNode;
import java.util.Collections;
import static io.github.swagger2markup.config.OpenAPILabels.LABEL_CONTENT;
public class MediaContentComponent extends MarkupComponent<StructuralNode, MediaContentComponent.Parameters, StructuralNode> {
private final MediaTypeExampleComponent mediaTypeExampleComponent;
private final ExamplesComponent examplesComponent;
private final SchemaComponent schemaComponent;
private final EncodingComponent encodingComponent;
public MediaContentComponent(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
this.mediaTypeExampleComponent = new MediaTypeExampleComponent(context);
this.examplesComponent = new ExamplesComponent(context);
this.schemaComponent = new SchemaComponent(context);
this.encodingComponent = new EncodingComponent(context);
}
public static MediaContentComponent.Parameters parameters(Content content) {
return new MediaContentComponent.Parameters(content);
}
public StructuralNode apply(StructuralNode node, Content content) {
return apply(node, parameters(content));
}
@Override
public StructuralNode apply(StructuralNode node, MediaContentComponent.Parameters parameters) {
Content content = parameters.content;
if (content == null || content.isEmpty()) return node;
DescriptionListImpl mediaContentList = new DescriptionListImpl(node);
mediaContentList.setTitle(labels.getLabel(LABEL_CONTENT));
content.forEach((type, mediaType) -> {
DescriptionListEntryImpl tagEntry = new DescriptionListEntryImpl(mediaContentList, Collections.singletonList(new ListItemImpl(mediaContentList, type)));
ListItemImpl tagDesc = new ListItemImpl(tagEntry, "");
Document tagDescDocument = schemaComponent.apply(mediaContentList, mediaType.getSchema());
mediaTypeExampleComponent.apply(tagDescDocument, mediaType.getExample());
examplesComponent.apply(tagDescDocument, mediaType.getExamples());
encodingComponent.apply(tagDescDocument, mediaType.getEncoding());
tagDesc.append(tagDescDocument);
tagEntry.setDescription(tagDesc);
mediaContentList.addEntry(tagEntry);
});
node.append(mediaContentList);
return node;
}
public static class Parameters {
private final Content content;
public Parameters(Content content) {
this.content = content;
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* 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.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.ParagraphBlockImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import org.apache.commons.lang3.StringUtils;
import org.asciidoctor.ast.StructuralNode;
import static io.github.swagger2markup.adoc.converter.internal.Delimiters.DELIMITER_BLOCK;
import static io.github.swagger2markup.adoc.converter.internal.Delimiters.LINE_SEPARATOR;
import static io.github.swagger2markup.config.OpenAPILabels.LABEL_EXAMPLE;
public class MediaTypeExampleComponent extends MarkupComponent<StructuralNode, MediaTypeExampleComponent.Parameters, StructuralNode> {
public MediaTypeExampleComponent(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
}
public static MediaTypeExampleComponent.Parameters parameters(Object example) {
return new MediaTypeExampleComponent.Parameters(example);
}
public StructuralNode apply(StructuralNode node, Object example) {
return apply(node, parameters(example));
}
@Override
public StructuralNode apply(StructuralNode node, MediaTypeExampleComponent.Parameters parameters) {
Object example = parameters.example;
if (example == null || StringUtils.isBlank(example.toString())) return node;
ParagraphBlockImpl sourceBlock = new ParagraphBlockImpl(node);
sourceBlock.setTitle(labels.getLabel(LABEL_EXAMPLE));
sourceBlock.setAttribute("style", "source", true);
sourceBlock.setSource(DELIMITER_BLOCK + LINE_SEPARATOR + example + LINE_SEPARATOR + DELIMITER_BLOCK);
node.append(sourceBlock);
return node;
}
public static class Parameters {
private final Object example;
public Parameters(Object example) {
this.example = example;
}
}
}

View File

@@ -0,0 +1,103 @@
/*
* 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.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.TableImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import io.swagger.v3.oas.models.parameters.Parameter;
import org.asciidoctor.ast.Document;
import org.asciidoctor.ast.StructuralNode;
import org.asciidoctor.ast.Table;
import java.util.*;
import java.util.stream.Collectors;
import static io.github.swagger2markup.adoc.converter.internal.Delimiters.LINE_SEPARATOR;
import static io.github.swagger2markup.config.OpenAPILabels.*;
import static io.github.swagger2markup.internal.helper.OpenApiHelpers.*;
public class ParametersComponent extends MarkupComponent<StructuralNode, ParametersComponent.Parameters, StructuralNode> {
private final SchemaComponent schemaComponent;
public ParametersComponent(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
this.schemaComponent = new SchemaComponent(context);
}
public static ParametersComponent.Parameters parameters(Map<String, Parameter> parameters) {
return new ParametersComponent.Parameters(parameters);
}
public static ParametersComponent.Parameters parameters(List<Parameter> parameters) {
if(null == parameters) {
return new ParametersComponent.Parameters(new HashMap<>());
}
return new ParametersComponent.Parameters(parameters.stream().collect(Collectors.toMap(Parameter::getName, parameter -> parameter)));
}
public StructuralNode apply(StructuralNode parent, List<Parameter> params) {
return apply(parent, parameters(params));
}
public StructuralNode apply(StructuralNode parent, Map<String, Parameter> params) {
return apply(parent, parameters(params));
}
@Override
public StructuralNode apply(StructuralNode parent, ParametersComponent.Parameters componentParameters) {
Map<String, Parameter> parameters = componentParameters.parameters;
if (null == parameters || parameters.isEmpty()) return parent;
TableImpl pathParametersTable = new TableImpl(parent, new HashMap<>(), new ArrayList<>());
pathParametersTable.setOption("header");
pathParametersTable.setAttribute("caption", "", true);
pathParametersTable.setAttribute("cols", ".^2a,.^3a,.^10a,.^5a", true);
pathParametersTable.setTitle(labels.getLabel(TABLE_TITLE_PARAMETERS));
pathParametersTable.setHeaderRow(
labels.getLabel(TABLE_HEADER_TYPE),
labels.getLabel(TABLE_HEADER_NAME),
labels.getLabel(TABLE_HEADER_DESCRIPTION),
labels.getLabel(TABLE_HEADER_SCHEMA));
parameters.forEach((alt, parameter) ->
pathParametersTable.addRow(
generateInnerDoc(pathParametersTable, boldUnconstrained(parameter.getIn()), alt),
getParameterNameDocument(pathParametersTable, parameter),
generateInnerDoc(pathParametersTable, Optional.ofNullable(parameter.getDescription()).orElse("")),
generateInnerDoc(pathParametersTable, getSchemaTypeAsString(parameter.getSchema()))
));
parent.append(pathParametersTable);
return parent;
}
private Document getParameterNameDocument(Table table, Parameter parameter) {
String documentContent = boldUnconstrained(parameter.getName()) + " +" + LINE_SEPARATOR + requiredIndicator(parameter.getRequired(),
labels.getLabel(LABEL_REQUIRED), labels.getLabel(LABEL_OPTIONAL));
return generateInnerDoc(table, documentContent);
}
public static class Parameters {
private final Map<String, Parameter> parameters;
public Parameters(Map<String, Parameter> parameters) {
this.parameters = parameters;
}
}
}

View File

@@ -0,0 +1,89 @@
/*
* 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.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.TableImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import io.swagger.v3.oas.models.media.Schema;
import org.asciidoctor.ast.StructuralNode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static io.github.swagger2markup.adoc.converter.internal.Delimiters.LINE_SEPARATOR;
import static io.github.swagger2markup.config.OpenAPILabels.*;
import static io.github.swagger2markup.internal.helper.OpenApiHelpers.*;
public class PropertiesTableComponent extends MarkupComponent<StructuralNode, PropertiesTableComponent.Parameters, StructuralNode> {
private final SchemaComponent schemaComponent;
PropertiesTableComponent(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
this.schemaComponent = new SchemaComponent(context);
}
public static Parameters parameters(@SuppressWarnings("rawtypes") Map<String, Schema> properties, List<String> schemaRequired) {
return new Parameters(properties, schemaRequired);
}
public StructuralNode apply(StructuralNode parent, @SuppressWarnings("rawtypes") Map<String, Schema> properties, List<String> schemaRequired) {
return apply(parent, parameters(properties, schemaRequired));
}
public StructuralNode apply(StructuralNode parent, Parameters params) {
@SuppressWarnings("rawtypes") Map<String, Schema> properties = params.properties;
List<String> schemaRequired = params.schemaRequired;
if (null == properties || properties.isEmpty()) return parent;
List<String> finalSchemaRequired = (null == schemaRequired) ? new ArrayList<>() : schemaRequired;
TableImpl propertiesTable = new TableImpl(parent, new HashMap<>(), new ArrayList<>());
propertiesTable.setOption("header");
propertiesTable.setAttribute("caption", "", true);
propertiesTable.setAttribute("cols", ".^4a,.^16a,.^4a", true);
propertiesTable.setTitle(labels.getLabel(TABLE_TITLE_PROPERTIES));
propertiesTable.setHeaderRow(
labels.getLabel(TABLE_HEADER_NAME),
labels.getLabel(TABLE_HEADER_DESCRIPTION),
labels.getLabel(TABLE_HEADER_SCHEMA));
properties.forEach((name, schema) -> propertiesTable.addRow(
generateInnerDoc(propertiesTable, name + LINE_SEPARATOR + requiredIndicator(finalSchemaRequired.contains(name),
labels.getLabel(LABEL_REQUIRED), labels.getLabel(LABEL_OPTIONAL))),
schemaComponent.apply(propertiesTable, schema),
generateInnerDoc(propertiesTable, getSchemaTypeAsString(schema))
));
parent.append(propertiesTable);
return parent;
}
@SuppressWarnings("rawtypes")
public static class Parameters {
private final Map<String, Schema> properties;
private final List<String> schemaRequired;
public Parameters(Map<String, Schema> properties, List<String> schemaRequired) {
this.properties = properties;
this.schemaRequired = schemaRequired;
}
}
}

View File

@@ -0,0 +1,96 @@
/*
* 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.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.TableImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import io.swagger.v3.oas.models.responses.ApiResponse;
import org.asciidoctor.ast.Document;
import org.asciidoctor.ast.StructuralNode;
import org.asciidoctor.ast.Table;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import static io.github.swagger2markup.config.OpenAPILabels.*;
import static io.github.swagger2markup.internal.helper.OpenApiHelpers.generateInnerDoc;
public class ResponseComponent extends MarkupComponent<StructuralNode, ResponseComponent.Parameters, StructuralNode> {
private final HeadersComponent headersComponent;
private final LinkComponent linkComponent;
private final MediaContentComponent mediaContentComponent;
public ResponseComponent(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
this.headersComponent = new HeadersComponent(context);
this.linkComponent = new LinkComponent(context);
this.mediaContentComponent = new MediaContentComponent(context);
}
public static Parameters parameters(Map<String, ApiResponse> apiResponses) {
return new Parameters(apiResponses);
}
public StructuralNode apply(StructuralNode serverSection, Map<String, ApiResponse> apiResponses) {
return apply(serverSection, parameters(apiResponses));
}
@Override
public StructuralNode apply(StructuralNode serverSection, Parameters params) {
Map<String, ApiResponse> apiResponses = params.apiResponses;
if (null == apiResponses || apiResponses.isEmpty()) return serverSection;
TableImpl pathResponsesTable = new TableImpl(serverSection, new HashMap<>(), new ArrayList<>());
pathResponsesTable.setOption("header");
pathResponsesTable.setAttribute("caption", "", true);
pathResponsesTable.setAttribute("cols", ".^2a,.^14a,.^4a", true);
pathResponsesTable.setTitle(labels.getLabel(TABLE_TITLE_RESPONSES));
pathResponsesTable.setHeaderRow(
labels.getLabel(TABLE_HEADER_HTTP_CODE),
labels.getLabel(TABLE_HEADER_DESCRIPTION),
labels.getLabel(TABLE_HEADER_LINKS));
apiResponses.forEach((httpCode, apiResponse) ->
pathResponsesTable.addRow(
generateInnerDoc(pathResponsesTable, httpCode),
getResponseDescriptionColumnDocument(pathResponsesTable, apiResponse),
linkComponent.apply(pathResponsesTable, apiResponse.getLinks())
));
serverSection.append(pathResponsesTable);
return serverSection;
}
private Document getResponseDescriptionColumnDocument(Table table, ApiResponse apiResponse) {
Document document = generateInnerDoc(table, Optional.ofNullable(apiResponse.getDescription()).orElse(""));
headersComponent.apply(document, apiResponse.getHeaders());
mediaContentComponent.apply(document, apiResponse.getContent());
return document;
}
public static class Parameters {
private final Map<String, ApiResponse> apiResponses;
public Parameters(Map<String, ApiResponse> apiResponses) {
this.apiResponses = apiResponses;
}
}
}

View File

@@ -0,0 +1,118 @@
/*
* 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.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.DocumentImpl;
import io.github.swagger2markup.adoc.ast.impl.ParagraphBlockImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import io.github.swagger2markup.internal.helper.OpenApiHelpers;
import io.swagger.v3.oas.models.media.Schema;
import org.apache.commons.lang3.StringUtils;
import org.asciidoctor.ast.Document;
import org.asciidoctor.ast.StructuralNode;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static io.github.swagger2markup.adoc.converter.internal.Delimiters.LINE_SEPARATOR;
import static io.github.swagger2markup.config.OpenAPILabels.*;
import static io.github.swagger2markup.internal.helper.OpenApiHelpers.boldUnconstrained;
public class SchemaComponent extends MarkupComponent<StructuralNode, SchemaComponent.Parameters, StructuralNode> {
private final OpenAPI2MarkupConverter.OpenAPIContext context;
public SchemaComponent(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
this.context = context;
}
public static SchemaComponent.Parameters parameters(@SuppressWarnings("rawtypes") Schema schema) {
return new SchemaComponent.Parameters(schema);
}
public Document apply(StructuralNode parent, @SuppressWarnings("rawtypes") Schema schema) {
return apply(parent, parameters(schema));
}
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
public Document apply(StructuralNode parent, SchemaComponent.Parameters parameters) {
Document schemaDocument = new DocumentImpl(parent);
Schema schema = parameters.schema;
if (null == schema) return schemaDocument;
OpenApiHelpers.appendDescription(schemaDocument, schema.getDescription());
Map<String, Boolean> schemasBooleanProperties = new HashMap<String, Boolean>() {{
put(labels.getLabel(LABEL_DEPRECATED), schema.getDeprecated());
put(labels.getLabel(LABEL_NULLABLE), schema.getNullable());
put(labels.getLabel(LABEL_READ_ONLY), schema.getReadOnly());
put(labels.getLabel(LABEL_WRITE_ONLY), schema.getWriteOnly());
put(labels.getLabel(LABEL_UNIQUE_ITEMS), schema.getUniqueItems());
put(labels.getLabel(LABEL_EXCLUSIVE_MAXIMUM), schema.getExclusiveMaximum());
put(labels.getLabel(LABEL_EXCLUSIVE_MINIMUM), schema.getExclusiveMinimum());
}};
Map<String, Object> schemasValueProperties = new HashMap<String, Object>() {{
put(labels.getLabel(LABEL_TITLE), schema.getTitle());
put(labels.getLabel(LABEL_DEFAULT), schema.getDefault());
put(labels.getLabel(LABEL_MAXIMUM), schema.getMaximum());
put(labels.getLabel(LABEL_MINIMUM), schema.getMinimum());
put(labels.getLabel(LABEL_MAX_LENGTH), schema.getMaxLength());
put(labels.getLabel(LABEL_MIN_LENGTH), schema.getMinLength());
put(labels.getLabel(LABEL_MAX_ITEMS), schema.getMaxItems());
put(labels.getLabel(LABEL_MIN_ITEMS), schema.getMinItems());
put(labels.getLabel(LABEL_MAX_PROPERTIES), schema.getMaxProperties());
put(labels.getLabel(LABEL_MIN_PROPERTIES), schema.getMinProperties());
put(labels.getLabel(LABEL_MULTIPLE_OF), schema.getMultipleOf());
}};
Stream<String> schemaBooleanStream = schemasBooleanProperties.entrySet().stream()
.filter(e -> null != e.getValue() && e.getValue())
.map(e -> OpenApiHelpers.italicUnconstrained(e.getKey().toLowerCase()));
Stream<String> schemaValueStream = schemasValueProperties.entrySet().stream()
.filter(e -> null != e.getValue() && StringUtils.isNotBlank(e.getValue().toString()))
.map(e -> boldUnconstrained(e.getKey()) + ": " + e.getValue());
ParagraphBlockImpl paragraphBlock = new ParagraphBlockImpl(schemaDocument);
String source = Stream.concat(schemaBooleanStream, schemaValueStream).collect(Collectors.joining(" +" + LINE_SEPARATOR));
paragraphBlock.setSource(source);
schemaDocument.append(paragraphBlock);
Map<String, Schema> properties = schema.getProperties();
if (null != properties && !properties.isEmpty()) {
PropertiesTableComponent propertiesTableComponent = new PropertiesTableComponent(context);
propertiesTableComponent.apply(schemaDocument, properties, schema.getRequired());
}
return schemaDocument;
}
@SuppressWarnings("rawtypes")
public static class Parameters {
private final Schema schema;
public Parameters(Schema schema) {
this.schema = schema;
}
}
}

View File

@@ -0,0 +1,86 @@
/*
* 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.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.TableImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import org.asciidoctor.ast.StructuralNode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import static io.github.swagger2markup.config.OpenAPILabels.*;
import static io.github.swagger2markup.internal.helper.OpenApiHelpers.*;
public class SecurityRequirementTableComponent extends MarkupComponent<StructuralNode, SecurityRequirementTableComponent.Parameters, StructuralNode> {
public SecurityRequirementTableComponent(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
}
public static SecurityRequirementTableComponent.Parameters parameters(List<SecurityRequirement> securityRequirements, boolean addTitle) {
return new SecurityRequirementTableComponent.Parameters(securityRequirements, addTitle);
}
public StructuralNode apply(StructuralNode document, List<SecurityRequirement> securityRequirements, boolean addTitle) {
return apply(document, parameters(securityRequirements, addTitle));
}
@Override
public StructuralNode apply(StructuralNode node, SecurityRequirementTableComponent.Parameters parameters) {
List<SecurityRequirement> securityRequirements = parameters.securityRequirements;
if (securityRequirements == null || securityRequirements.isEmpty()) return node;
TableImpl securityRequirementsTable = new TableImpl(node, new HashMap<>(), new ArrayList<>());
securityRequirementsTable.setOption("header");
securityRequirementsTable.setAttribute("caption", "", true);
securityRequirementsTable.setAttribute("cols", ".^3a,.^4a,.^13a", true);
if (parameters.addTitle) {
securityRequirementsTable.setTitle(labels.getLabel(TABLE_TITLE_SECURITY));
}
securityRequirementsTable.setHeaderRow(
labels.getLabel(TABLE_HEADER_TYPE),
labels.getLabel(TABLE_HEADER_NAME),
labels.getLabel(TABLE_HEADER_SCOPES));
securityRequirements.forEach(securityRequirement ->
securityRequirement.forEach((name, scopes) ->
securityRequirementsTable.addRow(
generateInnerDoc(securityRequirementsTable, boldUnconstrained(scopes.isEmpty() ? "apiKey" : "oauth2")),
generateInnerDoc(securityRequirementsTable, name),
generateInnerDoc(securityRequirementsTable, String.join(", ", scopes))
)
)
);
node.append(securityRequirementsTable);
return node;
}
public static class Parameters {
private final List<SecurityRequirement> securityRequirements;
private final boolean addTitle;
public Parameters(List<SecurityRequirement> securityRequirements, boolean addTitle) {
this.securityRequirements = securityRequirements;
this.addTitle = addTitle;
}
}
}

View File

@@ -0,0 +1,86 @@
/*
* 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.
*/
package io.github.swagger2markup.internal.component;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.DescriptionListEntryImpl;
import io.github.swagger2markup.adoc.ast.impl.DescriptionListImpl;
import io.github.swagger2markup.adoc.ast.impl.ListItemImpl;
import io.github.swagger2markup.adoc.ast.impl.SectionImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import io.swagger.v3.oas.models.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.asciidoctor.ast.Document;
import org.asciidoctor.ast.Section;
import java.util.Collections;
import java.util.List;
import static io.github.swagger2markup.config.OpenAPILabels.SECTION_TITLE_TAGS;
public class TagsComponent extends MarkupComponent<Document, TagsComponent.Parameters, Document> {
private final ExternalDocumentationComponent externalDocumentationComponent;
public TagsComponent(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
this.externalDocumentationComponent = new ExternalDocumentationComponent(context);
}
public static TagsComponent.Parameters parameters(List<Tag> tags) {
return new TagsComponent.Parameters(tags);
}
public Document apply(Document document, List<Tag> tags) {
return apply(document, parameters(tags));
}
@Override
public Document apply(Document document, TagsComponent.Parameters parameters) {
List<Tag> openAPITags = parameters.tags;
if (null == openAPITags || openAPITags.isEmpty()) return document;
Section tagsSection = new SectionImpl(document);
tagsSection.setTitle(labels.getLabel(SECTION_TITLE_TAGS));
DescriptionListImpl tagsList = new DescriptionListImpl(tagsSection);
openAPITags.forEach(tag -> {
DescriptionListEntryImpl tagEntry = new DescriptionListEntryImpl(tagsList, Collections.singletonList(new ListItemImpl(tagsList, tag.getName())));
String description = tag.getDescription();
if(StringUtils.isNotBlank(description)){
ListItemImpl tagDesc = new ListItemImpl(tagEntry, "");
tagDesc.setSource(description);
externalDocumentationComponent.apply(tagDesc, tag.getExternalDocs());
tagEntry.setDescription(tagDesc);
}
tagsList.addEntry(tagEntry);
});
tagsSection.append(tagsList);
document.append(tagsSection);
return document;
}
public static class Parameters {
private final List<Tag> tags;
public Parameters(List<Tag> tags) {
this.tags = tags;
}
}
}

View File

@@ -0,0 +1,122 @@
package io.github.swagger2markup.internal.document;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.SectionImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import io.github.swagger2markup.internal.component.*;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.headers.Header;
import io.swagger.v3.oas.models.links.Link;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.responses.ApiResponse;
import org.apache.commons.lang3.Validate;
import org.asciidoctor.ast.Document;
import org.asciidoctor.ast.Section;
import org.asciidoctor.ast.StructuralNode;
import java.util.Map;
import static io.github.swagger2markup.config.OpenAPILabels.*;
public class ComponentsDocument extends MarkupComponent<Document, ComponentsDocument.Parameters, Document> {
private final ParametersComponent parametersComponent;
private final ResponseComponent responseComponent;
private final HeadersComponent headersComponent;
private final SchemaComponent schemaComponent;
private final LinkComponent linkComponent;
public ComponentsDocument(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
this.parametersComponent = new ParametersComponent(context);
this.responseComponent = new ResponseComponent(context);
this.headersComponent = new HeadersComponent(context);
this.schemaComponent = new SchemaComponent(context);
this.linkComponent = new LinkComponent(context);
}
public static Parameters parameters(Components components) {
return new Parameters(components);
}
@Override
public Document apply(Document document, ComponentsDocument.Parameters parameters) {
appendComponentsSection(document, parameters.components);
return document;
}
public static class Parameters {
private final Components components;
public Parameters(Components components) {
this.components = Validate.notNull(components, "Schema must not be null");
}
}
private void appendComponentsSection(Document document, Components components) {
if (null == components) return;
Section componentsSection = new SectionImpl(document);
componentsSection.setTitle(labels.getLabel(SECTION_TITLE_COMPONENTS));
String componentSectionId = "_components";
componentsSection.setId(componentSectionId);
appendComponentsSchemasSection(componentsSection, componentSectionId, components.getSchemas());
Map<String, Parameter> parameters = components.getParameters();
if (null != parameters && !parameters.isEmpty()) {
appendSubSection(componentsSection, componentSectionId, parametersComponent, SECTION_TITLE_PARAMETERS,
new ParametersComponent.Parameters(parameters));
}
Map<String, ApiResponse> responses = components.getResponses();
if (null != responses && !responses.isEmpty()) {
appendSubSection(componentsSection, componentSectionId, responseComponent, SECTION_TITLE_RESPONSES,
new ResponseComponent.Parameters(responses));
}
Map<String, Header> headers = components.getHeaders();
if (null != headers && !headers.isEmpty()) {
appendSubSection(componentsSection, componentSectionId, headersComponent, SECTION_TITLE_HEADERS,
new HeadersComponent.Parameters(headers));
}
Map<String, Link> links = components.getLinks();
if (null != links && !links.isEmpty()) {
appendSubSection(componentsSection, componentSectionId, linkComponent, SECTION_TITLE_LINKS,
new LinkComponent.Parameters(links));
}
document.append(componentsSection);
}
private void appendComponentsSchemasSection(
Section componentsSection, String componentSectionId,
@SuppressWarnings("rawtypes") Map<String, Schema> schemas) {
if (null == schemas || schemas.isEmpty()) return;
SectionImpl schemasSection = new SectionImpl(componentsSection);
String schemasSectionId = componentSectionId + "_schemas";
schemasSection.setTitle(labels.getLabel(SECTION_TITLE_SCHEMAS));
schemasSection.setId(schemasSectionId);
schemas.forEach((name, schema) -> {
String schemaDocumentId = schemasSectionId + "_" + name;
Document schemaDocument = schemaComponent.apply(schemasSection, schema);
schemaDocument.setTitle(name);
schemaDocument.setId(schemaDocumentId);
schemasSection.append(schemaDocument);
});
componentsSection.append(schemasSection);
}
private <T> void appendSubSection(Section componentsSection, String componentSectionId,
MarkupComponent<StructuralNode, T, StructuralNode> markupComponent,
String sectionLabel, T parameters) {
SectionImpl parametersSection = new SectionImpl(componentsSection);
String parametersSectionId = componentSectionId + "_parameters";
parametersSection.setTitle(labels.getLabel(sectionLabel));
parametersSection.setId(parametersSectionId);
markupComponent.apply(parametersSection, parameters);
componentsSection.append(parametersSection);
}
}

View File

@@ -0,0 +1,138 @@
package io.github.swagger2markup.internal.document;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.BlockImpl;
import io.github.swagger2markup.adoc.ast.impl.DocumentImpl;
import io.github.swagger2markup.adoc.ast.impl.ParagraphBlockImpl;
import io.github.swagger2markup.adoc.ast.impl.SectionImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import io.github.swagger2markup.extension.OverviewDocumentExtension;
import io.github.swagger2markup.internal.component.ExternalDocumentationComponent;
import io.github.swagger2markup.internal.component.TagsComponent;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.asciidoctor.ast.Block;
import org.asciidoctor.ast.Document;
import org.asciidoctor.ast.Section;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Optional;
import static io.github.swagger2markup.config.OpenAPILabels.LABEL_TERMS_OF_SERVICE;
import static io.github.swagger2markup.config.OpenAPILabels.SECTION_TITLE_OVERVIEW;
import static io.github.swagger2markup.extension.OverviewDocumentExtension.Context;
import static io.github.swagger2markup.internal.helper.OpenApiHelpers.appendDescription;
public class OverviewDocument extends MarkupComponent<Document, OverviewDocument.Parameters, Document> {
private final TagsComponent tagsComponent;
private final ExternalDocumentationComponent externalDocumentationComponent;
public OverviewDocument(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
tagsComponent = new TagsComponent(context);
this.externalDocumentationComponent = new ExternalDocumentationComponent(context);
}
public static OverviewDocument.Parameters parameters(OpenAPI schema) {
return new OverviewDocument.Parameters(schema);
}
@Override
public Document apply(Document document, Parameters parameters) {
Info apiInfo = parameters.openAPI.getInfo();
document.setAttribute("openapi", parameters.openAPI.getOpenapi(), true);
addDocumentTitle(document, apiInfo);
addAuthorInfo(document, apiInfo);
addVersionInfo(document, apiInfo);
applyOverviewDocumentExtension(new Context(OverviewDocumentExtension.Position.DOCUMENT_BEFORE, document));
Document subDocument = new DocumentImpl(document);
Section overviewDoc = new SectionImpl(subDocument, "section", new HashMap<>(), new ArrayList<>(),
null, new ArrayList<>(), 1, "", new ArrayList<>(),
null, null, "", "", false, false);
applyOverviewDocumentExtension(new Context(OverviewDocumentExtension.Position.DOCUMENT_BEGIN, subDocument));
overviewDoc.setTitle(labels.getLabel(SECTION_TITLE_OVERVIEW));
appendDescription(overviewDoc, apiInfo.getDescription());
appendTermsOfServiceInfo(overviewDoc, apiInfo);
appendLicenseInfo(overviewDoc, apiInfo);
subDocument.append(overviewDoc);
applyOverviewDocumentExtension(new Context(OverviewDocumentExtension.Position.DOCUMENT_END, subDocument));
document.append(subDocument);
externalDocumentationComponent.apply(document, parameters.openAPI.getExternalDocs());
tagsComponent.apply(document, parameters.openAPI.getTags());
applyOverviewDocumentExtension(new Context(OverviewDocumentExtension.Position.DOCUMENT_AFTER, document));
return document;
}
private void applyOverviewDocumentExtension(Context context) {
extensionRegistry.getOverviewDocumentExtensions().forEach(extension -> extension.apply(context));
}
private void addDocumentTitle(Document rootDocument, Info apiInfo) {
String title = apiInfo.getTitle();
if (StringUtils.isNotBlank(title)) {
rootDocument.setTitle(title);
}
}
private void addVersionInfo(Document rootDocument, Info info) {
String version = info.getVersion();
if (StringUtils.isNotBlank(version)) {
rootDocument.setAttribute("revnumber", version, true);
}
}
private void addAuthorInfo(Document rootDocument, Info info) {
Contact contact = info.getContact();
if (null != contact) {
String author = Optional.ofNullable(contact.getName()).orElse("");
String email = contact.getEmail();
if (StringUtils.isNotBlank(email)) {
rootDocument.setAttribute("email", email, true);
}
rootDocument.setAttribute("author", author, true);
rootDocument.setAttribute("authorcount", 1L, true);
}
}
private void appendLicenseInfo(Section overviewDoc, Info info) {
License license = info.getLicense();
if (null != license) {
StringBuilder sb = new StringBuilder();
if (StringUtils.isNotBlank(license.getUrl())) {
sb.append(license.getUrl()).append("[");
}
sb.append(license.getName());
if (StringUtils.isNotBlank(license.getUrl())) {
sb.append("]");
}
BlockImpl paragraph = new ParagraphBlockImpl(overviewDoc);
paragraph.setSource(sb.toString());
overviewDoc.append(paragraph);
}
}
private void appendTermsOfServiceInfo(Section overviewDoc, Info info) {
String termsOfService = info.getTermsOfService();
if (StringUtils.isNotBlank(termsOfService)) {
Block paragraph = new ParagraphBlockImpl(overviewDoc);
paragraph.setSource(termsOfService + "[" + labels.getLabel(LABEL_TERMS_OF_SERVICE) + "]");
overviewDoc.append(paragraph);
}
}
public static class Parameters {
private final OpenAPI openAPI;
public Parameters(OpenAPI openAPI) {
this.openAPI = Validate.notNull(openAPI, "Schema must not be null");
}
}
}

View File

@@ -0,0 +1,116 @@
package io.github.swagger2markup.internal.document;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.SectionImpl;
import io.github.swagger2markup.adoc.ast.impl.TableImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import io.github.swagger2markup.internal.component.ExternalDocumentationComponent;
import io.github.swagger2markup.internal.component.ParametersComponent;
import io.github.swagger2markup.internal.component.ResponseComponent;
import io.github.swagger2markup.internal.component.SecurityRequirementTableComponent;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.servers.Server;
import io.swagger.v3.oas.models.servers.ServerVariables;
import org.apache.commons.lang3.Validate;
import org.asciidoctor.ast.Document;
import org.asciidoctor.ast.Section;
import org.asciidoctor.ast.StructuralNode;
import java.util.*;
import static io.github.swagger2markup.config.OpenAPILabels.*;
import static io.github.swagger2markup.internal.helper.OpenApiHelpers.*;
public class PathsDocument extends MarkupComponent<Document, PathsDocument.Parameters, Document> {
private final ParametersComponent parametersComponent;
private final ExternalDocumentationComponent externalDocumentationComponent;
private final ResponseComponent responseComponent;
private final SecurityRequirementTableComponent securityRequirementTableComponent;
public PathsDocument(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
this.parametersComponent = new ParametersComponent(context);
this.externalDocumentationComponent = new ExternalDocumentationComponent(context);
this.responseComponent = new ResponseComponent(context);
this.securityRequirementTableComponent = new SecurityRequirementTableComponent(context);
}
public static Parameters parameters(OpenAPI schema) {
return new Parameters(schema);
}
@Override
public Document apply(Document document, Parameters parameters) {
Paths apiPaths = parameters.schema.getPaths();
if (null == apiPaths || apiPaths.isEmpty()) return document;
SectionImpl allPathsSection = new SectionImpl(document);
allPathsSection.setTitle(labels.getLabel(SECTION_TITLE_PATHS));
apiPaths.forEach((name, pathItem) ->
pathItem.readOperationsMap().forEach(((httpMethod, operation) -> {
SectionImpl operationSection = new SectionImpl(allPathsSection);
String summary = Optional.ofNullable(operation.getSummary()).orElse("");
operationSection.setTitle((italicUnconstrained(httpMethod.name().toUpperCase()) + " " + monospaced(name) + " " + summary).trim());
appendDescription(operationSection, operation.getDescription());
externalDocumentationComponent.apply(operationSection, operation.getExternalDocs());
parametersComponent.apply(operationSection, operation.getParameters());
responseComponent.apply(operationSection, operation.getResponses());
appendServersSection(operationSection, operation.getServers());
securityRequirementTableComponent.apply(operationSection, operation.getSecurity(), false);
allPathsSection.append(operationSection);
})));
document.append(allPathsSection);
return document;
}
private void appendServersSection(StructuralNode node, List<Server> servers) {
if (null == servers || servers.isEmpty()) return;
Section serversSection = new SectionImpl(node);
serversSection.setTitle(labels.getLabel(SECTION_TITLE_SERVERS));
servers.forEach(server -> {
Section serverSection = new SectionImpl(serversSection);
serverSection.setTitle(italicUnconstrained(labels.getLabel(LABEL_SERVER)) + ": " + server.getUrl());
appendDescription(serverSection, server.getDescription());
ServerVariables variables = server.getVariables();
appendVariables(serverSection, variables);
serversSection.append(serverSection);
});
node.append(serversSection);
}
private void appendVariables(Section serverSection, ServerVariables variables) {
if (null == variables || variables.isEmpty()) return;
TableImpl serverVariables = new TableImpl(serverSection, new HashMap<String, Object>() {{
put("header-option", "");
put("cols", ".^2a,.^9a,.^3a,.^4a");
}}, new ArrayList<>());
serverVariables.setTitle(labels.getLabel(TABLE_TITLE_SERVER_VARIABLES));
serverVariables.setHeaderRow(labels.getLabel(TABLE_HEADER_VARIABLE), labels.getLabel(TABLE_HEADER_DESCRIPTION),
labels.getLabel(TABLE_HEADER_POSSIBLE_VALUES), labels.getLabel(TABLE_HEADER_DEFAULT)
);
variables.forEach((name, variable) -> {
String possibleValues = String.join(", ", Optional.ofNullable(variable.getEnum()).orElse(Collections.singletonList("Any")));
serverVariables.addRow(name, Optional.ofNullable(variable.getDescription()).orElse(""), possibleValues, variable.getDefault());
});
serverSection.append(serverVariables);
}
public static class Parameters {
private final OpenAPI schema;
public Parameters(OpenAPI schema) {
this.schema = Validate.notNull(schema, "Schema must not be null");
}
}
}

View File

@@ -0,0 +1,49 @@
package io.github.swagger2markup.internal.document;
import io.github.swagger2markup.OpenAPI2MarkupConverter;
import io.github.swagger2markup.adoc.ast.impl.SectionImpl;
import io.github.swagger2markup.extension.MarkupComponent;
import io.github.swagger2markup.internal.component.SecurityRequirementTableComponent;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import org.apache.commons.lang3.Validate;
import org.asciidoctor.ast.Document;
import org.asciidoctor.ast.Section;
import java.util.List;
import static io.github.swagger2markup.config.OpenAPILabels.SECTION_TITLE_SECURITY;
public class SecurityDocument extends MarkupComponent<Document, SecurityDocument.Parameters, Document> {
private final SecurityRequirementTableComponent securityRequirementTableComponent;
public SecurityDocument(OpenAPI2MarkupConverter.OpenAPIContext context) {
super(context);
this.securityRequirementTableComponent = new SecurityRequirementTableComponent(context);
}
public static Parameters parameters(OpenAPI schema) {
return new Parameters(schema);
}
@Override
public Document apply(Document document, SecurityDocument.Parameters parameters) {
List<SecurityRequirement> securityRequirements = parameters.schema.getSecurity();
if (null == securityRequirements || securityRequirements.isEmpty()) return document;
Section securityRequirementsSection = new SectionImpl(document);
securityRequirementsSection.setTitle(labels.getLabel(SECTION_TITLE_SECURITY));
securityRequirementTableComponent.apply(securityRequirementsSection, securityRequirements, false);
document.append(securityRequirementsSection);
return document;
}
public static class Parameters {
private final OpenAPI schema;
public Parameters(OpenAPI schema) {
this.schema = Validate.notNull(schema, "Schema must not be null");
}
}
}

View File

@@ -0,0 +1,115 @@
package io.github.swagger2markup.internal.helper;
import io.github.swagger2markup.adoc.ast.impl.DocumentImpl;
import io.github.swagger2markup.adoc.ast.impl.ParagraphBlockImpl;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.Schema;
import org.apache.commons.lang3.StringUtils;
import org.asciidoctor.ast.Block;
import org.asciidoctor.ast.Document;
import org.asciidoctor.ast.StructuralNode;
import org.asciidoctor.ast.Table;
import java.util.List;
import static io.github.swagger2markup.adoc.converter.internal.Delimiters.LINE_SEPARATOR;
public class OpenApiHelpers {
public static void appendDescription(StructuralNode node, String description) {
if (StringUtils.isNotBlank(description)) {
Block paragraph = new ParagraphBlockImpl(node);
paragraph.setSource(description);
node.append(paragraph);
}
}
public static Document generateInnerDoc(Table table, String documentContent) {
return generateInnerDoc(table, documentContent, "");
}
public static Document generateInnerDoc(Table table, String documentContent, String id) {
Document innerDoc = new DocumentImpl(table);
if (StringUtils.isNotBlank(id)) {
innerDoc.setId(id);
}
Block paragraph = new ParagraphBlockImpl(innerDoc);
paragraph.setSource(documentContent);
innerDoc.append(paragraph);
return innerDoc;
}
public static String requiredIndicator(boolean isRequired, String labelRequired, String labelOptional) {
return italicUnconstrained(isRequired ? labelRequired : labelOptional).toLowerCase();
}
public static String superScript(String str) {
return "^" + str + "^";
}
public static String subScript(String str) {
return "~" + str + "~";
}
public static String italicUnconstrained(String str) {
return "__" + str + "__";
}
public static String boldUnconstrained(String str) {
return "**" + str + "**";
}
public static String monospaced(String str) {
return "`" + str + "`";
}
public static String getSchemaTypeAsString(Schema schema) {
StringBuilder stringBuilder = new StringBuilder();
if (schema instanceof ArraySchema) {
stringBuilder.append("< ");
Schema<?> items = ((ArraySchema) schema).getItems();
stringBuilder.append(getSchemaType(items));
stringBuilder.append(" > ");
stringBuilder.append(schema.getType());
} else {
List enumList = schema.getEnum();
if (enumList != null) {
stringBuilder.append("enum (");
for (Object value : enumList) {
stringBuilder.append(value.toString());
stringBuilder.append(",");
}
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
stringBuilder.append(')');
} else {
stringBuilder.append(getSchemaType(schema));
String format = schema.getFormat();
if (format != null) {
stringBuilder.append(' ');
stringBuilder.append('(');
stringBuilder.append(format);
stringBuilder.append(')');
}
}
}
return stringBuilder.toString();
}
private static String getSchemaType(Schema<?> schema) {
String type = schema.getType();
if (StringUtils.isNotEmpty(type)) {
return type;
} else {
return generateRefLink(schema.get$ref());
}
}
private static String generateRefLink(String ref) {
if (StringUtils.isNotBlank(ref)) {
String anchor = ref.toLowerCase().replaceFirst("#", "").replaceAll("/", "_");
return "<<" + anchor + ">>" + LINE_SEPARATOR;
}
return "";
}
}

View File

@@ -0,0 +1,30 @@
swagger2markup.markupLanguage=ASCIIDOC
swagger2markup.swaggerMarkupLanguage=ASCIIDOC
swagger2markup.generatedExamplesEnabled=false
swagger2markup.hostnameEnabled=false
swagger2markup.basePathPrefixEnabled=false
swagger2markup.operationExtensionsEnabled=false
swagger2markup.definitionExtensionsEnabled=false
swagger2markup.separatedDefinitionsEnabled=false
swagger2markup.separatedOperationsEnabled=false
swagger2markup.pathsGroupedBy=AS_IS
swagger2markup.outputLanguage=EN
swagger2markup.inlineSchemaEnabled=true
swagger2markup.interDocumentCrossReferencesEnabled=false
swagger2markup.flatBodyEnabled=false
swagger2markup.pathSecuritySectionEnabled=true
swagger2markup.overviewDocument=overview
swagger2markup.pathsDocument=paths
swagger2markup.definitionsDocument=definitions
swagger2markup.securityDocument=security
swagger2markup.separatedOperationsFolder=operations
swagger2markup.separatedDefinitionsFolder=definitions
swagger2markup.tagOrderBy=NATURAL
swagger2markup.operationOrderBy=NATURAL
swagger2markup.definitionOrderBy=NATURAL
swagger2markup.parameterOrderBy=NATURAL
swagger2markup.propertyOrderBy=NATURAL
swagger2markup.responseOrderBy=NATURAL
swagger2markup.listDelimiterEnabled=false
swagger2markup.listDelimiter=,
swagger2markup.asciidoc.pegdown.timeoutMillis=2000

View File

@@ -0,0 +1,58 @@
label_content=Content
label_default=Default
label_deprecated=Deprecated
label_example=Example
label_examples=Examples
label_exclusive_maximum=Exclusive Maximum
label_exclusive_minimum=Exclusive Minimum
label_external_value=External Value
label_format=Format
label_maximum=Maximum
label_max_items=Maximum Items
label_max_length=Maximum Length
label_max_properties=Maximum Properties
label_minimum=Minimum
label_min_items=Minimum Items
label_min_length=Minimum Length
label_min_properties=Minimum Properties
label_multiple_of=Multiple Of
label_no_links=No Links
label_nullable=Nullable
label_operation=Operation
label_optional=Optional
label_parameters=Parameters
label_read_only=Read Only
label_required=Required
label_server=Server
label_terms_of_service=Terms Of Service
label_title=Title
label_type=Type
label_unique_items=Unique Items
label_write_only=Write Only
section_title_components=Components
section_title_parameters=Parameters
section_title_paths=Paths
section_title_schemas=Schemas
section_title_security=Security
section_title_servers=Servers
section_title_overview=Overview
section_title_tags=Tags
section_title_responses=Responses
section_title_headers=Headers
section_title_links=Links
table_header_default=Default
table_header_description=Description
table_header_http_code=Code
table_header_links=Links
table_header_name=Name
table_header_possible_values=Possible Values
table_header_schema=Schema
table_header_scopes=Scopes
table_header_type=Type
table_header_variable=Variable
table_title_headers=Headers
table_title_parameters=Parameters
table_title_properties=Properties
table_title_responses=Responses
table_title_security=Security
table_title_server_variables=Server Variables

View File

@@ -0,0 +1,74 @@
/*
* 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.
*/
package io.github.swagger2markup;
import io.github.swagger2markup.assertions.DiffUtils;
import org.apache.commons.io.FileUtils;
import org.assertj.core.api.Assertions;
import org.junit.Before;
import org.junit.Test;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
public class AsciidocConverterTest {
private static final String[] EXPECTED_FILES = new String[]{"definitions.adoc", "overview.adoc", "paths.adoc", "security.adoc"};
private List<String> expectedFiles;
@Before
public void setUp() {
expectedFiles = new ArrayList<>(asList(EXPECTED_FILES));
}
@Test
public void testToString() throws URISyntaxException {
//Given
Path file = Paths.get(AsciidocConverterTest.class.getResource("/yaml/swagger_petstore.yaml").toURI());
//When
String asciiDocAsString = OpenAPI2MarkupConverter.from(file).build()
.toString();
//Then
Assertions.assertThat(asciiDocAsString).isNotEmpty();
System.out.println(asciiDocAsString);
}
@Test
public void testToFolder() throws URISyntaxException {
//Given
Path file = Paths.get(AsciidocConverterTest.class.getResource("/yaml/swagger_petstore.yaml").toURI());
Path outputDirectory = Paths.get("build/test/asciidoc/to_folder");
FileUtils.deleteQuietly(outputDirectory.toFile());
//When
OpenAPI2MarkupConverter.from(file).build()
.toFolder(outputDirectory);
//Then
String[] files = outputDirectory.toFile().list();
assertThat(files).hasSize(4).containsAll(expectedFiles);
Path expectedFilesDirectory = Paths.get(AsciidocConverterTest.class.getResource("/expected/asciidoc/to_folder").toURI());
DiffUtils.assertThatAllFilesAreEqual(expectedFilesDirectory, outputDirectory, "testToFolder.html");
}
}

View File

@@ -0,0 +1,49 @@
package io.github.swagger2markup;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.parser.OpenAPIV3Parser;
import io.swagger.v3.parser.core.models.ParseOptions;
import io.swagger.v3.parser.core.models.SwaggerParseResult;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.Arrays;
import static org.junit.Assert.assertNotNull;
@RunWith(Parameterized.class)
public class OpenApi2AsciiDocTest {
final private String openApiFile;
final private String expectedAsciiDoc;
public OpenApi2AsciiDocTest(String openApiFile, String expectedAsciiDoc) throws IOException {
this.openApiFile = "./src/test/resources/open_api/" + openApiFile;
this.expectedAsciiDoc = IOUtils.toString(getClass().getResourceAsStream("/asciidoc/" + expectedAsciiDoc), StandardCharsets.UTF_8);
}
@Parameterized.Parameters(name = "Run {index}: open api={0}, asciidoc={1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][]{
{"simple.yaml", "simple.adoc"},
{"petstore.yaml", "petstore.adoc"}
});
}
@Test
public void converts_open_api_v3_to_asciidoc() {
ParseOptions options = new ParseOptions();
options.setResolve(true);
SwaggerParseResult result = new OpenAPIV3Parser().readLocation(openApiFile, null, options);
OpenAPI swagger = result.getOpenAPI();
assertNotNull(swagger);
OpenAPI2MarkupConverter converter = OpenAPI2MarkupConverter.from(swagger).build();
converter.toFolder(Paths.get("build/test/asciidoc"));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,276 @@
= Simple Inventory API
<you@your-company.com>
v1.0.0
:revnumber: 1.0.0
:openapi: 3.0.0
:authorcount: 1
:email: you@your-company.com
== Overview
This is a simple API
http://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0]
== Tags
admins::
Secured Admin-only calls
developers::
Operations available to regular developers
== Servers
=== __Server__: /
== Paths
=== __GET__ `/inventory` searches inventory
By passing in the appropriate options, you can search for
available inventory in the system
.Parameters
[%header,caption=,cols=".^2a,.^3a,.^10a,.^5a"]
|===
<.<|Type
<.<|Name
<.<|Description
<.<|Schema
<.<|**query**
<.<|**searchString** +
__optional__
<.<|pass an optional search string for looking up inventory
<.<|type: string
<.<|**query**
<.<|**limit** +
__optional__
<.<|maximum number of records to return
<.<|minimum: 0 +
type: integer +
maximum: 50 +
format: int32
<.<|**query**
<.<|**skip** +
__optional__
<.<|number of records to skip for pagination
<.<|minimum: 0 +
type: integer +
format: int32
|===
.Responses
[%header,caption=,cols=".^2a,.^14a,.^4a"]
|===
<.<|Code
<.<|Description
<.<|Links
<.<|200
<.<|search results matching criteria
.Content
application/json::
+
type: array
<.<|No Links
<.<|400
<.<|bad input parameter
<.<|No Links
|===
=== __POST__ `/inventory` adds an inventory item
Adds an item to the system
.Responses
[%header,caption=,cols=".^2a,.^14a,.^4a"]
|===
<.<|Code
<.<|Description
<.<|Links
<.<|201
<.<|item created
<.<|No Links
<.<|400
<.<|invalid input, object invalid
<.<|No Links
<.<|409
<.<|an existing item already exists
<.<|No Links
|===
[[_components]]
== Components
[[_components_schemas]]
=== Schemas
[[_components_schemas_inventoryitem]]
==== InventoryItem
type: object
.Properties
[%header,caption=,cols=".^4a,.^16a"]
|===
<.<|Name
<.<|Schema
<.<|id
__required__
<.<|type: string +
format: uuid
<.<|name
__required__
<.<|type: string
<.<|releaseDate
__required__
<.<|type: string +
format: date-time
<.<|manufacturer
__required__
<.<|<<_components_schemas_Manufacturer,Manufacturer>>
|===
[[_components_schemas_manufacturer]]
==== Manufacturer
type: object
.Properties
[%header,caption=,cols=".^4a,.^16a"]
|===
<.<|Name
<.<|Schema
<.<|name
__required__
<.<|type: string
<.<|homePage
__optional__
<.<|type: string +
format: url
<.<|phone
__optional__
<.<|type: string
|===

View File

@@ -0,0 +1,351 @@
[[_components]]
== Components
[[_components_schemas]]
=== Schemas
[[_components_schemas_user]]
==== User
.Properties
[%header,caption=,cols=".^4a,.^16a,.^4a"]
|===
<.<|Name
<.<|Description
<.<|Schema
<.<|id
__optional__
<.<|
<.<|integer (int64)
<.<|username
__optional__
<.<|
<.<|string
<.<|firstName
__optional__
<.<|
<.<|string
<.<|lastName
__optional__
<.<|
<.<|string
<.<|email
__optional__
<.<|
<.<|string
<.<|password
__optional__
<.<|
<.<|string
<.<|phone
__optional__
<.<|
<.<|string
<.<|userStatus
__optional__
<.<|User Status
<.<|integer (int32)
|===
[[_components_schemas_category]]
==== Category
.Properties
[%header,caption=,cols=".^4a,.^16a,.^4a"]
|===
<.<|Name
<.<|Description
<.<|Schema
<.<|id
__optional__
<.<|
<.<|integer (int64)
<.<|name
__optional__
<.<|The name of the category
**Maximum Length**: 255 +
**Minimum Length**: 0 +
**Default**: DefaultCategory
<.<|string
|===
[[_components_schemas_pet]]
==== Pet
.Properties
[%header,caption=,cols=".^4a,.^16a,.^4a"]
|===
<.<|Name
<.<|Description
<.<|Schema
<.<|id
__optional__
<.<|
<.<|integer (int64)
<.<|category
__optional__
<.<|
<.<|<<_components_schemas_category>>
<.<|name
__required__
<.<|
<.<|string
<.<|photoUrls
__required__
<.<|
<.<|< string > array
<.<|tags
__optional__
<.<|
<.<|< <<_components_schemas_tag>>
> array
<.<|status
__optional__
<.<|pet status in the store,
<.<|enum (Dead,Alive)
|===
[[_components_schemas_tag]]
==== Tag
.Properties
[%header,caption=,cols=".^4a,.^16a,.^4a"]
|===
<.<|Name
<.<|Description
<.<|Schema
<.<|id
__optional__
<.<|
<.<|integer (int64)
<.<|name
__optional__
<.<|
<.<|string
|===
[[_components_schemas_order]]
==== Order
.Properties
[%header,caption=,cols=".^4a,.^16a,.^4a"]
|===
<.<|Name
<.<|Description
<.<|Schema
<.<|id
__optional__
<.<|
<.<|integer (int64)
<.<|petId
__optional__
<.<|
<.<|integer (int64)
<.<|quantity
__optional__
<.<|**Maximum**: 10000 +
**Minimum**: 0 +
**Default**: 0
<.<|integer (int32)
<.<|shipDate
__optional__
<.<|
<.<|string (date-time)
<.<|status
__optional__
<.<|Order Status
<.<|enum (Ordered,Cancelled)
<.<|complete
__optional__
<.<|
<.<|boolean
|===
[[_components_parameters]]
=== Responses
.Responses
[%header,caption=,cols=".^2a,.^14a,.^4a"]
|===
<.<|Code
<.<|Description
<.<|Links
<.<|InvalidId
<.<|Invalid ID supplied
<.<|No Links
|===

View File

@@ -0,0 +1,30 @@
= Swagger Petstore
apiteam@swagger.io
v1.0.0
:revnumber: 1.0.0
:openapi: 3.0.0
:author: apiteam@swagger.io
:authorcount: 1
== Overview
This is a sample server Petstore server.
[Learn about Swagger](http://swagger.io) 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
http://helloreverb.com/terms/[Terms Of Service]
http://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0]
http://swagger.io[Find out more about Swagger]
== Tags
pet::
Pet resource
store::
Store resource
user::
User resource

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="io.github.swagger2markup" level="DEBUG"/>
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
</configuration>

View File

@@ -0,0 +1,732 @@
openapi: 3.0.0
servers:
- url: 'http://localhost:8000/v2/api'
info:
description: >-
This is a sample server Petstore server. You can find out more about
Swagger at http://swagger.io or on
irc.freenode.net, #swagger. For this sample, you can use the api key
"special-key" to test the authorization filters
version: 1.0.0
title: Swagger Petstore
termsOfService: 'http://swagger.io/terms/'
contact:
name: apiteam@swagger.io
license:
name: Apache 2.0
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
externalDocs:
description: Find more info here
url: 'https://swagger.io'
tags:
- name: pet
description: Pet Operations
externalDocs:
url: 'http://swagger.io'
- name: user
description: All about the Users
paths:
/pet/add:
post:
tags:
- pet
summary: Add a new pet to the store
description: ''
operationId: createPet
responses:
'200':
description: This is a sample
content:
text/plain:
schema:
type: string
example: 'whoa!'
'405':
description: Invalid input
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
description: Pet object that needs to be added to the store
/pet:
post:
tags:
- pet
summary: Add a new pet to the store
description: ''
operationId: addPet
responses:
'405':
description: Invalid input
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
description: Pet object that needs to be added to the store
put:
tags:
- pet
summary: Update an existing pet
description: ''
operationId: updatePet
responses:
'400':
description: Invalid ID supplied
'404':
description: Pet not found
'405':
description: Validation exception
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
requestBody:
$ref: '#/components/requestBodies/Pet'
/pet/findByStatus:
get:
tags:
- pet
summary: Finds Pets by status
description: Multiple status values can be provided with comma seperated strings
operationId: findPetsByStatus
parameters:
- name: status
in: query
description: Status values that need to be considered for filter
required: false
style: pipeDelimited
schema:
type: array
items:
type: string
default: available
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/PetArray'
application/xml:
schema:
$ref: '#/components/schemas/PetArray'
'400':
description: Invalid status value
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
/pet/findByTags:
get:
tags:
- pet
summary: Finds Pets by tags
description: >-
Muliple tags can be provided with comma seperated strings. Use tag1,
tag2, tag3 for testing.
operationId: findPetsByTags
parameters:
- name: tags
in: query
description: Tags to filter by
required: false
explode: true
schema:
type: array
items:
type: string
responses:
'200':
description: successful operation
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid tag value
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
'/pet/{petId}':
get:
tags:
- pet
summary: Find pet by ID
description: >-
Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API
error conditions
operationId: getPetById
parameters:
- name: petId
in: path
description: ID of pet that needs to be fetched
required: true
schema:
type: integer
format: int64
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
'400':
description: Invalid ID supplied
'404':
description: Pet not found
security:
- api_key: []
- petstore_auth:
- 'write:pets'
- 'read:pets'
post:
tags:
- pet
summary: Updates a pet in the store with form data
description: ''
operationId: updatePetWithForm
parameters:
- name: petId
in: path
description: ID of pet that needs to be updated
required: true
schema:
type: string
responses:
'405':
description: Invalid input
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
name:
description: Updated name of the pet
type: string
status:
description: Updated status of the pet
type: string
delete:
tags:
- pet
summary: Deletes a pet
description: ''
operationId: deletePet
parameters:
- name: api_key
in: header
description: ''
required: false
schema:
type: string
- name: petId
in: path
description: Pet id to delete
required: true
schema:
type: integer
format: int64
responses:
'400':
description: Invalid pet value
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
description: Pet extra params that needs to be deleted
'/pet/{petId}/uploadImage':
post:
tags:
- pet
summary: uploads an image
description: ''
operationId: uploadFile
parameters:
- name: petId
in: path
description: ID of pet to update
required: true
schema:
type: integer
format: int64
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: "#/components/schemas/ApiResponse"
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
additionalMetadata:
description: Additional data to pass to server
type: string
file:
description: file to upload
type: string
format: binary
/store/inventory:
get:
tags:
- store
summary: Returns pet inventories by status
description: Returns a map of status codes to quantities
operationId: get inventory+1
responses:
'200':
description: successful operation
content:
application/json:
schema:
type: object
additionalProperties:
type: integer
format: int32
application/xml:
schema:
type: object
additionalProperties:
type: integer
format: int32
security:
- api_key: []
/store/order:
post:
tags:
- store
summary: Place an order for a pet
description: ''
operationId: placeOrder
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
application/xml:
schema:
$ref: '#/components/schemas/Order'
'400':
description: Invalid Order
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
description: order placed for purchasing the pet
'/store/order/{orderId}':
get:
tags:
- store
summary: Find purchase order by ID
description: >-
For valid response try integer IDs with value <= 5 or > 10. Other values
will generated exceptions
operationId: getOrderById
parameters:
- name: orderId
in: path
description: ID of pet that needs to be fetched
required: true
schema:
type: string
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
application/xml:
schema:
$ref: '#/components/schemas/Order'
'400':
description: Invalid ID supplied
'404':
description: Order not found
delete:
tags:
- store
summary: Delete purchase order by ID
description: >-
For valid response try integer IDs with value < 1000. Anything above
1000 or nonintegers will generate API errors
operationId: deleteOrder
parameters:
- name: orderId
in: path
description: ID of the order that needs to be deleted
required: true
schema:
type: string
responses:
'400':
description: Invalid ID supplied
'404':
description: Order not found
/user:
post:
tags:
- user
summary: Create user
description: This can only be done by the logged in user.
operationId: createUser
responses:
200:
content:
'application/json':
schema:
type: object
properties:
id:
# default is text/plain
type: string
format: text
examples:
foo:
value: {"foo": "bar"}
bar:
summary: A bar example
value: {"bar": "baz"}
default:
description: successful operation
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/User'
description: Created user object
/user/createWithArray:
post:
tags:
- user
summary: Creates list of users with given input array
description: ''
operationId: createUsersWithArrayInput
responses:
default:
description: successful operation
requestBody:
$ref: '#/components/requestBodies/UserArray'
/user/createWithList:
post:
tags:
- user
summary: Creates list of users with given input array
description: ''
operationId: createUsersWithListInput
responses:
default:
description: successful operation
requestBody:
$ref: '#/components/requestBodies/UserArray'
/user/login:
get:
tags:
- user
security:
- https
summary: Logs user into the system
description: ''
operationId: loginUser
parameters:
- name: username
in: query
description: The user name for login
required: false
schema:
type: string
- name: password
in: query
description: The password for login in clear text
required: false
schema:
type: string
responses:
'200':
description: successful operation
content:
application/json:
schema:
type: string
application/xml:
schema:
type: string
'400':
description: Invalid username/password supplied
/user/logout:
get:
tags:
- user
security:
- https
summary: Logs out current logged in user session
description: ''
operationId: logoutUser
responses:
default:
description: successful operation
'/user/{username}':
get:
tags:
- user
summary: Get user by user name
description: ''
operationId: getUserByName
parameters:
- name: username
in: path
description: 'The name that needs to be fetched. Use user1 for testing.'
required: true
schema:
type: string
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
'400':
description: Invalid username supplied
'404':
description: User not found
put:
tags:
- user
summary: Updated user
description: This can only be done by the logged in user.
operationId: updateUser
parameters:
- name: username
in: path
description: name that need to be deleted
required: true
schema:
type: string
responses:
'400':
description: Invalid user supplied
'404':
description: User not found
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/User'
description: Updated user object
delete:
tags:
- user
summary: Delete user
description: This can only be done by the logged in user.
operationId: deleteUser
parameters:
- name: username
in: path
description: The name that needs to be deleted
required: true
schema:
type: string
responses:
'400':
description: Invalid username supplied
'404':
description: User not found
security:
- foo:
- bar
- baz
a:
- b
- c
components:
parameters:
sharedSkip:
name: skip
in: query
description: Results to skip
required: false
schema:
type: integer
format: int32
responses:
veryBad:
description: failed
requestBodies:
UserArray:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
description: List of user object
Pet:
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
application/xml:
schema:
$ref: '#/components/schemas/Pet'
description: Pet object that needs to be added to the store
securitySchemes:
api_key:
type: apiKey
name: api_key
in: header
petstore_auth:
type: oauth2
flows:
implicit:
authorizationUrl: 'http://petstore.swagger.io/api/oauth/dialog'
scopes:
'write:pets': modify pets in your account
'read:pets': read your pets
schemas:
User:
properties:
id:
type: integer
format: int64
username:
type: string
firstName:
type: string
lastName:
type: string
email:
type: string
password:
type: string
phone:
type: string
userStatus:
type: integer
format: int32
description: User Status
xml:
name: User
Category:
properties:
id:
type: integer
format: int64
name:
type: string
xml:
name: Category
Pet:
required:
- name
- photoUrls
properties:
id:
type: integer
format: int64
category:
$ref: '#/components/schemas/Category'
name:
type: string
example: doggie
photoUrls:
type: array
xml:
name: photoUrl
wrapped: true
items:
type: string
tags:
type: array
xml:
name: tag
wrapped: true
items:
$ref: '#/components/schemas/Tag'
status:
type: string
description: pet status in the store
xml:
name: Pet
Tag:
properties:
id:
type: integer
format: int64
name:
type: string
xml:
name: Tag
Order:
properties:
id:
type: integer
format: int64
petId:
type: integer
format: int64
quantity:
type: integer
format: int32
shipDate:
type: string
format: date-time
status:
type: string
description: Order Status
complete:
type: boolean
xml:
name: Order
PetArray:
type: array
items:
$ref: '#/components/schemas/Pet'

View File

@@ -0,0 +1,115 @@
openapi: 3.0.0
info:
description: This is a simple API
version: "1.0.0"
title: Simple Inventory API
contact:
email: you@your-company.com
license:
name: Apache 2.0
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
tags:
- name: admins
description: Secured Admin-only calls
- name: developers
description: Operations available to regular developers
paths:
/inventory:
get:
tags:
- developers
summary: searches inventory
operationId: searchInventory
description: |
By passing in the appropriate options, you can search for
available inventory in the system
parameters:
- in: query
name: searchString
description: pass an optional search string for looking up inventory
required: false
schema:
type: string
- in: query
name: skip
description: number of records to skip for pagination
schema:
type: integer
format: int32
minimum: 0
- in: query
name: limit
description: maximum number of records to return
schema:
type: integer
format: int32
minimum: 0
maximum: 50
responses:
'200':
description: search results matching criteria
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/InventoryItem'
'400':
description: bad input parameter
post:
tags:
- admins
summary: adds an inventory item
operationId: addInventory
description: Adds an item to the system
responses:
'201':
description: item created
'400':
description: 'invalid input, object invalid'
'409':
description: an existing item already exists
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/InventoryItem'
description: Inventory item to add
components:
schemas:
InventoryItem:
type: object
required:
- id
- name
- manufacturer
- releaseDate
properties:
id:
type: string
format: uuid
example: d290f1ee-6c54-4b01-90e6-d701748f0851
name:
type: string
example: Widget Adapter
releaseDate:
type: string
format: date-time
example: '2016-08-29T09:12:33.001Z'
manufacturer:
$ref: '#/components/schemas/Manufacturer'
Manufacturer:
required:
- name
properties:
name:
type: string
example: ACME Corporation
homePage:
type: string
format: url
example: 'https://www.acme-corp.com'
phone:
type: string
example: 408-867-5309
type: object

View File

@@ -0,0 +1,693 @@
openapi: 3.0.0
info:
description: >
This is a sample server Petstore server.
[Learn about Swagger](http://swagger.io) 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: 1.0.0
title: Swagger Petstore
termsOfService: http://helloreverb.com/terms/
contact:
name: apiteam@swagger.io
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
tags:
- name: pet
description: Pet resource
- name: store
description: Store resource
- name: user
description: User resource
paths:
/pets:
post:
tags:
- pet
summary: Add a new pet to the store
description: ""
operationId: addPet
requestBody:
$ref: "#/components/requestBodies/Pet"
responses:
"405":
description: Invalid input
security:
- petstore_auth:
- write_pets
- read_pets
put:
tags:
- pet
summary: Update an existing pet
description: ""
operationId: updatePet
requestBody:
$ref: "#/components/requestBodies/Pet"
responses:
"400":
$ref: "#/components/responses/InvalidId"
"404":
description: Pet not found
"405":
description: Validation exception
security:
- petstore_auth:
- write_pets
- read_pets
/pets/findByStatus:
get:
tags:
- pet
summary: Finds Pets by status
description: Multiple status values can be provided with comma seperated strings
operationId: findPetsByStatus
parameters:
- in: query
name: status
description: Status values that need to be considered for filter
required: false
explode: true
schema:
type: array
items:
type: string
responses:
"200":
description: successful operation
headers:
X-Rate-Limit-Limit:
description: The number of allowed requests in the current period
schema:
type: integer
X-Rate-Limit-Remaining:
description: The number of remaining requests in the current period
schema:
type: integer
X-Rate-Limit-Reset:
description: The number of seconds left in the current period
schema:
type: integer
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Pet"
application/xml:
schema:
type: array
items:
$ref: "#/components/schemas/Pet"
"400":
description: Invalid status value
security:
- petstore_auth:
- write_pets
- read_pets
/pets/findByTags:
get:
tags:
- pet
summary: Finds Pets by tags
description: Muliple tags can be provided with comma seperated strings. Use tag1,
tag2, tag3 for testing.
operationId: findPetsByTags
parameters:
- in: query
name: tags
description: Tags to filter by
required: false
example: adorable
explode: true
schema:
type: array
items:
type: string
responses:
"200":
description: successful operation
headers:
X-Rate-Limit-Limit:
description: The number of allowed requests in the current period
schema:
type: integer
X-Rate-Limit-Remaining:
description: The number of remaining requests in the current period
schema:
type: integer
X-Rate-Limit-Reset:
description: The number of seconds left in the current period
schema:
type: integer
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Pet"
application/xml:
schema:
type: array
items:
$ref: "#/components/schemas/Pet"
"400":
description: Invalid tag value
security:
- petstore_auth:
- write_pets
- read_pets
"/pets/{petId}":
get:
tags:
- pet
summary: Find pet by ID
description: Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API
error conditions
operationId: getPetById
parameters:
- in: path
name: petId
description: ID of pet that needs to be fetched
required: true
example: 30
schema:
type: integer
format: int64
responses:
"200":
description: successful operation
headers:
X-Rate-Limit-Limit:
description: The number of allowed requests in the current period
schema:
type: integer
X-Rate-Limit-Remaining:
description: The number of remaining requests in the current period
schema:
type: integer
X-Rate-Limit-Reset:
description: The number of seconds left in the current period
schema:
type: integer
content:
application/json:
schema:
$ref: "#/components/schemas/Pet"
application/xml:
schema:
$ref: "#/components/schemas/Pet"
"400":
$ref: "#/components/responses/InvalidId"
"404":
description: Pet not found
security:
- api_key: []
- petstore_auth:
- write_pets
- read_pets
post:
tags:
- pet
summary: Updates a pet in the store with form data
description: ""
operationId: updatePetWithForm
parameters:
- in: path
name: petId
description: ID of pet that needs to be updated
required: true
schema:
type: string
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
name:
description: Updated name of the pet
type: string
status:
description: Updated status of the pet
type: string
required:
- name
- status
responses:
"405":
description: Invalid input
security:
- petstore_auth:
- write_pets
- read_pets
delete:
tags:
- pet
summary: Deletes a pet
description: ""
operationId: deletePet
parameters:
- in: header
name: api_key
description: ""
required: true
schema:
type: string
- in: path
name: petId
description: Pet id to delete
required: true
schema:
type: integer
format: int64
responses:
"400":
description: Invalid pet value
security:
- petstore_auth:
- write_pets
- read_pets
/stores/order:
post:
tags:
- store
summary: Place an order for a pet
description: ""
operationId: placeOrder
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/Order"
description: order placed for purchasing the pet
responses:
"200":
description: successful operation
headers:
X-Rate-Limit-Limit:
description: The number of allowed requests in the current period
schema:
type: integer
X-Rate-Limit-Remaining:
description: The number of remaining requests in the current period
schema:
type: integer
X-Rate-Limit-Reset:
description: The number of seconds left in the current period
schema:
type: integer
content:
application/json:
schema:
$ref: "#/components/schemas/Order"
application/xml:
schema:
$ref: "#/components/schemas/Order"
"400":
description: Invalid Order
"/stores/order/{orderId}":
get:
tags:
- store
summary: Find purchase order by ID
description: For valid response try integer IDs with value <= 5 or > 10. Other values
will generated exceptions
operationId: getOrderById
parameters:
- in: path
name: orderId
description: ID of pet that needs to be fetched
required: true
schema:
type: string
responses:
"200":
description: successful operation
headers:
X-Rate-Limit-Limit:
description: The number of allowed requests in the current period
schema:
type: integer
X-Rate-Limit-Remaining:
description: The number of remaining requests in the current period
schema:
type: integer
X-Rate-Limit-Reset:
description: The number of seconds left in the current period
schema:
type: integer
content:
application/json:
schema:
$ref: "#/components/schemas/Order"
application/xml:
schema:
$ref: "#/components/schemas/Order"
"400":
$ref: "#/components/responses/InvalidId"
"404":
description: Order not found
delete:
tags:
- store
summary: Delete purchase order by ID
description: For valid response try integer IDs with value < 1000. Anything above
1000 or nonintegers will generate API errors
operationId: deleteOrder
parameters:
- in: path
name: orderId
description: ID of the order that needs to be deleted
required: true
schema:
type: string
responses:
"400":
$ref: "#/components/responses/InvalidId"
"404":
description: Order not found
/users:
post:
tags:
- user
summary: Create user
description: This can only be done by the logged in user.
operationId: createUser
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/User"
description: Created user object
responses:
default:
description: successful operation
/users/createWithArray:
post:
tags:
- user
summary: Creates list of users with given input array
description: ""
operationId: createUsersWithArrayInput
requestBody:
$ref: "#/components/requestBodies/UserArray"
responses:
default:
description: successful operation
/users/createWithList:
post:
tags:
- user
summary: Creates list of users with given input array
description: ""
operationId: createUsersWithListInput
requestBody:
$ref: "#/components/requestBodies/UserArray"
responses:
default:
description: successful operation
/users/login:
get:
tags:
- user
summary: Logs user into the system
description: ""
operationId: loginUser
parameters:
- in: query
name: username
description: The user name for login
required: false
schema:
type: string
- in: query
name: password
description: The password for login in clear text
required: false
schema:
type: string
responses:
"200":
description: successful operation
headers:
X-Rate-Limit-Limit:
description: The number of allowed requests in the current period
schema:
type: integer
X-Rate-Limit-Remaining:
description: The number of remaining requests in the current period
schema:
type: integer
X-Rate-Limit-Reset:
description: The number of seconds left in the current period
schema:
type: integer
content:
application/json:
schema:
type: string
application/xml:
schema:
type: string
"400":
description: Invalid username/password supplied
/users/logout:
get:
tags:
- user
summary: Logs out current logged in user session
description: ""
operationId: logoutUser
responses:
default:
description: successful operation
"/users/{username}":
get:
tags:
- user
summary: Get user by user name
description: ""
operationId: getUserByName
parameters:
- in: path
name: username
description: The name that needs to be fetched. Use user1 for testing.
required: true
schema:
type: string
responses:
"200":
description: successful operation
headers:
X-Rate-Limit-Limit:
description: The number of allowed requests in the current period
schema:
type: integer
X-Rate-Limit-Remaining:
description: The number of remaining requests in the current period
schema:
type: integer
X-Rate-Limit-Reset:
description: The number of seconds left in the current period
schema:
type: integer
content:
application/json:
schema:
$ref: "#/components/schemas/User"
application/xml:
schema:
$ref: "#/components/schemas/User"
"400":
description: Invalid username supplied
"404":
description: User not found
put:
tags:
- user
summary: Updated user
description: This can only be done by the logged in user.
operationId: updateUser
parameters:
- in: path
name: username
description: name that need to be deleted
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/User"
description: Updated user object
responses:
"400":
description: Invalid user supplied
"404":
description: User not found
delete:
tags:
- user
summary: Delete user
description: This can only be done by the logged in user.
operationId: deleteUser
parameters:
- in: path
name: username
description: The name that needs to be deleted
required: true
schema:
type: string
responses:
"400":
description: Invalid username supplied
"404":
description: User not found
externalDocs:
description: Find out more about Swagger
url: http://swagger.io
servers:
- url: http://petstore.swagger.io/v2
components:
responses:
InvalidId:
description: Invalid ID supplied
requestBodies:
UserArray:
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/User"
description: List of user object
Pet:
content:
application/json:
schema:
$ref: "#/components/schemas/Pet"
application/xml:
schema:
$ref: "#/components/schemas/Pet"
description: Pet object that needs to be added to the store
securitySchemes:
api_key:
type: apiKey
name: api_key
in: header
description: This is another description
petstore_auth:
type: oauth2
description: This is a standard oauth flow
flows:
implicit:
authorizationUrl: http://petstore.swagger.io/api/oauth/dialog
scopes:
write_pets: modify pets in your account
read_pets: read your pets
schemas:
User:
type: object
properties:
id:
type: integer
format: int64
username:
type: string
firstName:
type: string
lastName:
type: string
email:
type: string
password:
type: string
phone:
type: string
userStatus:
type: integer
format: int32
description: User Status
Category:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
description: The name of the category
minLength: 0
maxLength: 255
pattern: "[A-Za-zäöüÄÖÜß]{0,255}"
default: DefaultCategory
example: FoobarCategory
Pet:
type: object
required:
- name
- photoUrls
properties:
id:
type: integer
format: int64
category:
$ref: "#/components/schemas/Category"
name:
type: string
example: doggie
photoUrls:
type: array
items:
type: string
tags:
type: array
items:
$ref: "#/components/schemas/Tag"
status:
type: string
description: pet status in the store,
enum:
- Dead
- Alive
Tag:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
Order:
type: object
properties:
id:
type: integer
format: int64
petId:
type: integer
format: int64
quantity:
type: integer
format: int32
minimum: 0
maximum: 10000
default: 0
example: 10
shipDate:
type: string
format: date-time
status:
type: string
description: Order Status
enum:
- Ordered
- Cancelled
complete:
type: boolean

View File

@@ -1,6 +1,10 @@
rootProject.name = 'swagger2markup'
include 'swagger2markup-asciidoc'
include 'swagger2markup-bom'
include 'swagger2markup-builder'
include 'swagger2markup-core'
include 'swagger2markup-documentation'
include 'swagger2markup'
include 'swagger2markup-core'
include 'openapi2markup'

View File

@@ -0,0 +1,25 @@
ext.moduleName="io.github.swagger2markup.asciidoc"
dependencies {
configurations.all {
// resolutionStrategy.force dependencyOverrides.commonsCodec
// resolutionStrategy.force dependencyOverrides.commonsIO
// resolutionStrategy.force dependencyOverrides.commonsLang3
resolutionStrategy.force dependencyOverrides.jnrConstants
resolutionStrategy.force dependencyOverrides.jnrEnxio
resolutionStrategy.force dependencyOverrides.jnrPosix
// resolutionStrategy.force dependencyOverrides.jodaTime
resolutionStrategy.force dependencyOverrides.slf4j
// resolutionStrategy.force dependencyOverrides.jacksonDatabind
// resolutionStrategy.force dependencyOverrides.guava
// resolutionStrategy.force dependencyOverrides.findBugs
// resolutionStrategy.force dependencyOverrides.jaksonCore
}
implementation implLibraries.asciiDocJApi
implementation implLibraries.commonsText
implementation implLibraries.slf4j
testImplementation implLibraries.commonsIO
testImplementation testLibraries.asciiDocJ
testImplementation testLibraries.junit
testImplementation testLibraries.logback
}

View File

@@ -0,0 +1,887 @@
package io.github.swagger2markup.adoc;
import io.github.swagger2markup.adoc.converter.internal.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.asciidoctor.ast.List;
import org.asciidoctor.ast.*;
import org.asciidoctor.converter.ConverterFor;
import org.asciidoctor.converter.StringConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import static io.github.swagger2markup.adoc.converter.internal.Delimiters.*;
@ConverterFor(AsciidocConverter.NAME)
public class AsciidocConverter extends StringConverter {
private Logger logger = LoggerFactory.getLogger(getClass());
public static final String NAME = "adoc";
private final Pattern emptyLineOrStartWith = Pattern.compile("(?m)^\\s*(?:\\r?\\n)|(?m)^\\s+");
private final Pattern coListItemIdPattern = Pattern.compile(".*-(\\d+)");
private final Pattern tableColumnsStylePattern = Pattern.compile("((\\d+)\\*)?([<^>])?(\\.[<^>])?(\\d+)?([adehlmsv])?");
private static final java.util.List<String> attributeToExclude = Arrays.asList(
"localtime",
"filetype",
"asciidoctor-version",
"doctime",
"localyear",
"docdate",
"localdate",
"localdatetime",
"docdatetime",
"backend",
"basebackend",
"doctitle",
"docyear"
);
private static final String[] supportedUrlSchemes = new String[]{
"http",
"https",
"ftp",
"irc",
"mailto"
};
public AsciidocConverter(String backend, Map<String, Object> opts) {
super(backend, opts);
}
/**
* Converts an {@link ContentNode} using the specified transform along
* with additional options. If a transform is not specified, implementations
* typically derive one from the {@link ContentNode#getNodeName()} property.
*
* <p>Implementations are free to decide how to carry out the conversion. In
* the case of the built-in converters, the tranform value is used to
* dispatch to a handler method. The TemplateConverter uses the value of
* the transform to select a template to render.
*
* @param node The concrete instance of FlowNode to convert
* @param transform An optional String transform that hints at which transformation
* should be applied to this node. If a transform is not specified,
* the transform is typically derived from the value of the
* node's node_name property. (optional, default: null)
* @param opts An optional map of options that provide additional hints about
* how to convert the node. (optional, default: empty map)
* @return the converted result
*/
@Override
public String convert(ContentNode node, String transform, Map<Object, Object> opts) {
if (null == transform) {
transform = node.getNodeName();
}
switch (transform) {
case "inline_quoted":
return convertInlineQuoted((PhraseNode) node);
case "paragraph":
return convertParagraph((StructuralNode) node);
case "inline_anchor":
return convertInlineAnchor((PhraseNode) node);
case "section":
return convertSection((Section) node);
case "listing":
return convertListing((Block) node);
case "literal":
return convertLiteral((StructuralNode) node);
case "ulist":
return convertUList((List) node);
case "olist":
return convertOList((List) node);
case "dlist":
return convertDescriptionList((DescriptionList) node);
case "admonition":
return convertAdmonition((Block) node);
case "colist":
return convertCoList((List) node);
case "embedded":
case "document":
return convertEmbedded((Document) node);
case "example":
return convertExample((Block) node);
case "floating_title":
return convertFloatingTitle((StructuralNode) node);
case "image":
return convertImage((StructuralNode) node);
case "inline_break":
return convertInlineBreak(node);
case "inline_button":
return convertInlineButton(node);
case "inline_callout":
return convertInlineCallout(node);
case "inline_footnote":
return convertInlineFootnote(node);
case "inline_image":
return convertInlineImage((PhraseNode) node);
case "inline_indexterm":
return convertInlineIndexTerm(node);
case "inline_kbd":
return convertInlineKbd(node);
case "inline_menu":
return convertInlineMenu(node);
case "open":
return convertOpen((StructuralNode) node);
case "page_break":
return convertPageBreak(node);
case "preamble":
return convertPreamble((StructuralNode) node);
case "quote":
return convertQuote((StructuralNode) node);
case "sidebar":
return convertSidebar((StructuralNode) node);
case "stem":
return convertStem(node);
case "table":
return convertTable((Table) node);
case "thematic_break":
return convertThematicBreak(node);
case "verse":
return convertVerse((StructuralNode) node);
case "video":
return convertVideo(node);
case "toc":
return convertToc(node);
case "pass":
return convertPass(node);
case "audio":
return convertAudio(node);
// didn't exist on html converter
case "list":
return convertList((List) node);
case "list_item":
return convertListItem((ListItem) node);
default:
logger.debug("Don't know how to convert transform: [" + transform + "] Node: " + node);
return null;
}
}
String convertEmbedded(Document node) {
logger.debug("convertEmbedded");
StringBuilder sb = new StringBuilder();
appendId(node, sb);
if (StringUtils.isNotBlank(node.getDoctitle())) {
sb.append(repeat(node.getLevel() + 1,DOCUMENT_TITLE)).append(' ').append(StringEscapeUtils.unescapeHtml4(node.getDoctitle())).append(LINE_SEPARATOR);
}
Map<String, Object> attributes = node.getAttributes();
appendAuthors(sb, attributes);
appendRevisionDetails(sb, attributes);
appendDocumentAttributes(sb, attributes);
appendTrailingNewLine(sb);
appendChildBlocks(node, sb);
return sb.toString();
}
private void appendAuthors(StringBuilder sb, Map<String, Object> attributes) {
Long authorCount = (Long) attributes.getOrDefault("authorcount", 0L);
if (authorCount == 1) {
String author = getAuthorDetail(attributes, "author", "email");
if (StringUtils.isNotBlank(author)) {
sb.append(author).append(LINE_SEPARATOR);
}
} else if (authorCount > 1) {
String authors = LongStream.rangeClosed(1, authorCount)
.mapToObj(i -> getAuthorDetail(attributes, "author_" + i, "email_" + i))
.collect(Collectors.joining("; "));
if (StringUtils.isNotBlank(authors)) {
sb.append(authors).append(LINE_SEPARATOR);
}
}
}
private void appendDocumentAttributes(StringBuilder sb, Map<String, Object> attributes) {
attributes.forEach((k, v) -> {
if (!attributeToExclude.contains(k) && v != null && !v.toString().isEmpty())
sb.append(COLON).append(k).append(COLON).append(" ").append(v).append(LINE_SEPARATOR);
});
}
private void appendRevisionDetails(StringBuilder sb, Map<String, Object> attributes) {
String revDetails = Stream.of(attributes.get("revnumber"), attributes.get("revdate")).filter(Objects::nonNull)
.filter(o -> !o.toString().isEmpty()).map(Object::toString)
.collect(Collectors.joining(", "));
if (!revDetails.isEmpty()) {
sb.append("v").append(revDetails).append(LINE_SEPARATOR);
}
}
private String getAuthorDetail(Map<String, Object> attributes, String authorKey, String emailKey) {
String author = attributes.getOrDefault(authorKey, "").toString();
String email = attributes.getOrDefault(emailKey, "").toString();
if (StringUtils.isNotBlank(email)) {
email = " <" + email + ">";
}
return (author + email).trim();
}
private String convertInlineAnchor(PhraseNode node) {
logger.debug("convertInlineAnchor");
String type = node.getType();
switch (type) {
case "xref": {
String attrs;
String text;
String path = Optional.ofNullable(node.getAttributes().get("path")).orElse("").toString();
if (StringUtils.isNotBlank(path)) {
ArrayList<String> list = new ArrayList<>();
if (StringUtils.isNotBlank(node.getRole())) {
list.add(" class=\"#{node.role}\"");
}
append_link_constraint_attrs(node, list);
attrs = String.join(" ", list);
text = StringUtils.isNotBlank(node.getText()) ? node.getText() : path;
} else {
attrs = StringUtils.isNotBlank(node.getRole()) ? " class=\"" + node.getRole() + "\"" : "";
text = node.getText();
if (StringUtils.isNotBlank(text)) {
text = node.getAttributes().get("refid").toString();
}
}
return node.getTarget() + ATTRIBUTES_BEGIN + text + (StringUtils.isNotBlank(attrs) ? "," + attrs : "") + ATTRIBUTES_END;
}
case "ref":
return node.getId();
case "link": {
ArrayList<String> attrs = new ArrayList<>();
String target = node.getTarget();
String includePrefix = !StringUtils.startsWithAny(target, supportedUrlSchemes) ? "include::" : "";
String text = node.getText();
if (!target.equals(text)) {
attrs.add(text);
}
if (StringUtils.isNotBlank(node.getId())) {
attrs.add("id=\"" + node.getId() + "\"");
}
String role = node.getRole();
if (StringUtils.isNotBlank(role) && !role.equals("bare")) {
attrs.add("role=\"" + role + "\"");
}
String title = node.getAttribute("title", "").toString();
if (StringUtils.isNotBlank(title)) {
attrs.add("title=\"" + title + "\"");
}
return includePrefix + target + ATTRIBUTES_BEGIN + String.join(",", attrs) + ATTRIBUTES_END;
}
case "bibref":
return node.getId() + ATTRIBUTES_BEGIN + (StringUtils.isNotBlank(node.getReftext()) ? node.getReftext() : node.getId()) + ATTRIBUTES_END;
default:
logger.warn("unknown anchor type: " + node.getType());
return null;
}
}
private String convertAdmonition(Block node) {
logger.debug("convertAdmonition");
StringBuilder sb = new StringBuilder();
java.util.List<StructuralNode> blocks = node.getBlocks();
if (blocks.isEmpty()) {
sb.append(node.getStyle()).append(": ").append(node.getSource());
} else {
appendTitle(node, sb);
sb.append(ATTRIBUTES_BEGIN).append(node.getStyle()).append(ATTRIBUTES_END)
.append(LINE_SEPARATOR).append(DELIMITER_EXAMPLE).append(LINE_SEPARATOR);
appendChildBlocks(node, sb);
sb.append(DELIMITER_EXAMPLE).append(LINE_SEPARATOR);
}
return sb.toString();
}
private String convertInlineQuoted(PhraseNode node) {
logger.debug("convertInlineQuoted");
StringBuilder sb = new StringBuilder();
String marker = "";
switch (node.getType()) {
case "monospaced":
marker = "`";
break;
case "emphasis":
marker = "_";
break;
case "strong":
marker = "*";
break;
case "superscript":
marker = "^";
break;
case "subscript":
marker = "~";
break;
case "double":
case "single":
case "mark":
case "asciimath":
case "latexmath":
marker = "";
break;
}
sb.append(marker).append(node.getText()).append(marker);
return sb.toString();
}
private String convertFloatingTitle(StructuralNode node) {
logger.debug("convertFloatingTitle");
return ATTRIBUTES_BEGIN + "discrete" + ATTRIBUTES_END + LINE_SEPARATOR +
repeat(node.getLevel() + 1, TITLE) + ' ' + node.getTitle() + LINE_SEPARATOR;
}
private String convertExample(Block node) {
logger.debug("convertExample");
StringBuilder sb = new StringBuilder();
appendTitle(node, sb);
sb.append(DELIMITER_EXAMPLE).append(LINE_SEPARATOR);
appendChildBlocks(node, sb);
sb.append(DELIMITER_EXAMPLE).append(LINE_SEPARATOR);
return sb.toString();
}
private String convertInlineButton(ContentNode node) {
logger.debug("convertInlineButton: name" + node.getNodeName());
return "convertInlineButton";
}
private String convertInlineCallout(ContentNode node) {
logger.debug("convertInlineCallout: name" + node.getNodeName());
return "convertInlineCallout";
}
private String convertInlineBreak(ContentNode node) {
logger.debug("convertInlineBreak: name" + node.getNodeName());
return "convertInlineBreak";
}
private String convertInlineFootnote(ContentNode node) {
logger.debug("convertInlineFootnote: name" + node.getNodeName());
return "convertInlineFootnote";
}
private String convertInlineImage(PhraseNode node) {
logger.debug("convertInlineImage");
if (node.getType().equals("icon")) {
return (new IconNode(node)).toAsciiDocContent();
} else {
return (new BlockImageNode(node)).toAsciiDocContent();
}
}
private String convertInlineIndexTerm(ContentNode node) {
logger.debug("convertInlineIndexTerm: name" + node.getNodeName());
return "convertInlineIndexTerm";
}
private String convertInlineKbd(ContentNode node) {
logger.debug("convertInlineKbd: name" + node.getNodeName());
return "convertInlineKbd";
}
private String convertInlineMenu(ContentNode node) {
logger.debug("convertInlineMenu: name" + node.getNodeName());
return "convertInlineMenu";
}
private String convertOpen(StructuralNode node) {
logger.debug("convertOpen");
StringBuilder sb = new StringBuilder();
switch (node.getStyle()) {
case "abstract":
sb.append(ATTRIBUTES_BEGIN).append("abstract").append(ATTRIBUTES_END).append(LINE_SEPARATOR);
break;
case "open":
sb.append(DELIMITER_OPEN_BLOCK).append(LINE_SEPARATOR);
}
sb.append(Optional.ofNullable(((Block) node).getSource()).orElse(""));
appendChildBlocks(node, sb);
if ("open".equals(node.getStyle())) {
sb.append(DELIMITER_OPEN_BLOCK).append(LINE_SEPARATOR);
}
return sb.toString();
}
private String convertPageBreak(ContentNode node) {
logger.debug("convertPageBreak: name" + node.getNodeName());
return DELIMITER_PAGE_BREAK + LINE_SEPARATOR;
}
private String convertQuote(StructuralNode node) {
logger.debug("convertQuote");
StringBuilder sb = new StringBuilder();
appendTitle(node, sb);
sb.append(ATTRIBUTES_BEGIN);
java.util.List<String> attrs = new ArrayList<>();
if (StringUtils.isNotBlank(node.getStyle())) {
attrs.add("quote");
}
appendAttributeTo(node, attrs, "attribution");
appendAttributeTo(node, attrs, "citetitle");
sb.append(String.join(",", attrs)).append(ATTRIBUTES_END).append(LINE_SEPARATOR);
java.util.List<StructuralNode> blocks = node.getBlocks();
if (!blocks.isEmpty()) {
sb.append("____").append(LINE_SEPARATOR);
appendChildBlocks(node, sb);
sb.append("____").append(LINE_SEPARATOR);
} else {
sb.append(((Block) node).getSource());
}
return sb.toString();
}
private String convertSidebar(StructuralNode node) {
logger.debug("convertSidebar");
StringBuilder sb = new StringBuilder();
appendTitle(node, sb);
appendChildBlocks(node, sb);
return sb.toString();
}
private String convertStem(ContentNode node) {
logger.debug("convertStem: name" + node.getNodeName());
return "convertStem";
}
private String convertThematicBreak(ContentNode node) {
logger.debug("convertThematicBreak: name" + node.getNodeName());
return DELIMITER_THEMATIC_BREAK + LINE_SEPARATOR;
}
private String convertVerse(StructuralNode node) {
logger.debug("convertVerse");
StringBuilder sb = new StringBuilder();
appendTitle(node, sb);
sb.append(ATTRIBUTES_BEGIN);
java.util.List<String> attrs = new ArrayList<>();
if (StringUtils.isNotBlank(node.getStyle())) {
attrs.add("verse");
}
appendAttributeTo(node, attrs, "attribution");
appendAttributeTo(node, attrs, "citetitle");
sb.append(String.join(",", attrs)).append(ATTRIBUTES_END).append(LINE_SEPARATOR);
String source = ((Block) node).getSource();
boolean matches = emptyLineOrStartWith.matcher(source).find();
if (matches) {
sb.append(DELIMITER_VERSE).append(LINE_SEPARATOR);
}
sb.append(source);
if (matches) {
sb.append(LINE_SEPARATOR).append(DELIMITER_VERSE);
}
appendTrailingNewLine(sb);
return sb.toString();
}
private String convertVideo(ContentNode node) {
logger.debug("convertVideo: name" + node.getNodeName());
return "convertVideo";
}
private String convertToc(ContentNode node) {
logger.debug("convertToc: name" + node.getNodeName());
return "convertToc";
}
private String convertPass(ContentNode node) {
logger.debug("convertPass: name" + node.getNodeName());
return "convertPass";
}
private String convertAudio(ContentNode node) {
logger.debug("convertAudio: name" + node.getNodeName());
return "convertAudio";
}
private String convertCell(Cell node) {
logger.debug("convertCell");
StringBuilder sb = new StringBuilder();
String source = node.getSource();
if (StringUtils.isNotBlank(source)) {
sb.append(source);
}
Document innerDocument = node.getInnerDocument();
if (null != innerDocument) {
appendChildBlocks(innerDocument, sb, false);
}
return sb.toString().replaceAll(LINE_SEPARATOR + LINE_SEPARATOR + "+", LINE_SEPARATOR + LINE_SEPARATOR);
}
private String convertRow(Row node, java.util.List<TableCellStyle> columnStyles, String delimiterTableCell) {
logger.debug("convertRow");
StringBuilder sb = new StringBuilder();
node.getCells().forEach(cell -> {
boolean addNewLine = false;
int colspan = cell.getColspan();
if (colspan != 0) {
addNewLine = true;
sb.append(colspan).append('+');
}
int rowspan = cell.getRowspan();
if (rowspan != 0) {
addNewLine = true;
sb.append('.').append(rowspan).append('+');
}
int index = cell.getColumn().getColumnNumber() - 1;
TableCellStyle tableCellStyle = (columnStyles.size() > index) ? columnStyles.get(index) : null;
boolean hAlignmentAdded = false;
TableCellHorizontalAlignment hAlignment = TableCellHorizontalAlignment.fromName(cell.getHorizontalAlignment().name());
if ((null != hAlignment) && (null == tableCellStyle || hAlignment != tableCellStyle.horizontalAlignment)) {
hAlignmentAdded = true;
addNewLine = true;
sb.append(hAlignment.getDelimiter());
}
TableCellVerticalAlignment vAlignment = TableCellVerticalAlignment.fromName(cell.getVerticalAlignment().name());
if ((null != vAlignment) && (null == tableCellStyle || hAlignmentAdded || vAlignment != tableCellStyle.verticalAlignment)) {
addNewLine = true;
sb.append(vAlignment.getDelimiter());
}
Style style = Style.fromName(cell.getAttribute("style", "").toString());
if (null != style && (null == tableCellStyle || style != tableCellStyle.style)) {
addNewLine = true;
sb.append(style.getShortHand());
}
sb.append(delimiterTableCell).append(convertCell(cell));
if (addNewLine) {
sb.append(LINE_SEPARATOR);
} else {
sb.append(' ');
}
});
return sb.toString();
}
private String convertTable(Table node) {
logger.debug("convertTable");
java.util.List<TableCellStyle> columnStyles = new ArrayList<>();
for (String col : node.getAttribute("cols", "").toString().split(",")) {
Matcher matcher = tableColumnsStylePattern.matcher(col);
if (matcher.find()) {
int multiplier = 1;
String multiplierGroup = matcher.group(2);
if (null != multiplierGroup) {
try {
multiplier = Integer.parseInt(multiplierGroup);
} catch (NumberFormatException ignored) {
}
}
int width = 0;
try {
width = Integer.parseInt(matcher.group(5));
} catch (NumberFormatException ignored) {
}
TableCellStyle tableCellStyle = new TableCellStyle(
TableCellHorizontalAlignment.fromString(matcher.group(3)),
TableCellVerticalAlignment.fromString(matcher.group(4)),
Style.fromString(matcher.group(6)),
width
);
for (int i = 0; i < multiplier; i++) {
columnStyles.add(tableCellStyle);
}
}
}
StringBuilder sb = new StringBuilder();
appendTitle(node, sb);
sb.append(new TableNode(node).toAsciiDocContent());
boolean innerTable = isInnerTable(node);
String tableDelimiter = innerTable ? DELIMITER_INNER_TABLE : DELIMITER_TABLE;
String cellDelimiter = innerTable ? DELIMITER_INNER_TABLE_CELL : DELIMITER_TABLE_CELL;
sb.append(tableDelimiter).append(LINE_SEPARATOR);
appendRows(node.getHeader(), sb, columnStyles, cellDelimiter);
appendRows(node.getBody(), sb, columnStyles, cellDelimiter);
appendRows(node.getFooter(), sb, columnStyles, cellDelimiter);
sb.append(tableDelimiter).append(LINE_SEPARATOR);
return sb.toString();
}
private boolean isInnerTable(ContentNode node) {
if(null != node) {
ContentNode parent = node.getParent();
if (null != parent) {
return parent instanceof Table || isInnerTable(parent);
}
}
return false;
}
private void appendRows(java.util.List<Row> rows, StringBuilder sb, java.util.List<TableCellStyle> columnStyles, String delimiterTableCell) {
rows.forEach(row -> sb.append(convertRow(row, columnStyles, delimiterTableCell)).append(LINE_SEPARATOR));
}
private String convertDescriptionList(DescriptionList node) {
logger.debug("convertDescriptionList");
StringBuilder sb = new StringBuilder();
appendTitle(node, sb);
String style = Optional.ofNullable(node.getStyle()).orElse("");
switch (style) {
case STYLE_HORIZONTAL:
sb.append(ATTRIBUTES_BEGIN).append(STYLE_HORIZONTAL).append(ATTRIBUTES_END).append(LINE_SEPARATOR);
node.getItems().forEach(item -> sb.append(convertDescriptionListEntry(item, node.getLevel(), false)));
break;
case STYLE_Q_AND_A:
sb.append(ATTRIBUTES_BEGIN).append(STYLE_Q_AND_A).append(ATTRIBUTES_END).append(LINE_SEPARATOR);
default:
node.getItems().forEach(item -> sb.append(convertDescriptionListEntry(item, node.getLevel(), true)));
break;
}
appendTrailingNewLine(sb);
return sb.toString();
}
private String convertDescriptionListEntry(DescriptionListEntry node, int level, Boolean descriptionOnNewLine) {
logger.debug("convertDescriptionListEntry");
StringBuilder sb = new StringBuilder();
String delimiter = repeat(level + 1, MARKER_D_LIST_ITEM);
String entryTerms = node.getTerms().stream()
.map(term -> Optional.ofNullable(term.getSource()).orElse(""))
.collect(Collectors.joining(delimiter + LINE_SEPARATOR, "", delimiter));
sb.append(entryTerms);
ListItem description = node.getDescription();
if (null != description) {
if (descriptionOnNewLine) {
sb.append(LINE_SEPARATOR);
}
String desc = Optional.ofNullable(description.getSource()).orElse("");
if (StringUtils.isNotBlank(desc)) {
sb.append(desc).append(LINE_SEPARATOR);
}
appendChildBlocks(description, sb);
}
return sb.toString();
}
private String convertListing(Block node) {
logger.debug("convertListing");
StringBuilder sb = new StringBuilder();
appendTitle(node, sb);
if (STYLE_SOURCE.equals(node.getStyle())) {
sb.append(new SourceNode(node).toAsciiDocContent());
} else {
sb.append(new BlockListingNode(node).toAsciiDocContent());
}
return sb.toString();
}
private String convertUList(List node) {
logger.debug("convertUList");
StringBuilder sb = new StringBuilder();
appendStyle(node, sb);
appendTitle(node, sb);
appendChildBlocks(node, sb);
appendTrailingNewLine(sb);
return sb.toString();
}
private String convertOList(List node) {
logger.debug("convertOList");
StringBuilder sb = new StringBuilder();
java.util.List<String> attrs = new ArrayList<>();
String start = node.getAttribute("start", "").toString();
if (StringUtils.isNotBlank(start)) {
attrs.add("start=" + start);
}
if (node.isOption("reversed")) {
attrs.add("%reversed");
}
if (!attrs.isEmpty()) {
sb.append(ATTRIBUTES_BEGIN).append(String.join(",", attrs)).append(ATTRIBUTES_END).append(LINE_SEPARATOR);
}
appendTitle(node, sb);
appendChildBlocks(node, sb);
appendTrailingNewLine(sb);
return sb.toString();
}
private String convertCoList(List node) {
logger.debug("convertCoList");
StringBuilder result = new StringBuilder();
appendChildBlocks(node, result);
return result.toString();
}
private String convertListItem(ListItem node) {
logger.debug("convertListItem");
StringBuilder sb = new StringBuilder();
String marker = Optional.ofNullable(node.getMarker()).orElse(repeat(node.getLevel(), MARKER_LIST_ITEM));
String coids = node.getAttribute("coids", "").toString();
Matcher matcher = coListItemIdPattern.matcher(coids);
if (matcher.find()) {
marker = marker.replaceAll("\\d+", matcher.group(1));
}
sb.append(marker).append(" ");
if (node.hasAttribute("checkbox")) {
sb.append('[');
if (node.hasAttribute("checked")) {
sb.append('x');
} else {
sb.append(' ');
}
sb.append(']').append(' ');
}
sb.append(Optional.ofNullable(node.getSource()).orElse(""));
appendTrailingNewLine(sb);
appendChildBlocks(node, sb);
return sb.toString();
}
private String convertList(List node) {
logger.debug("convertList");
return node.getContent().toString();
}
private String convertPreamble(StructuralNode node) {
logger.debug("convertPreamble");
return node.getContent().toString();
}
private String convertImage(StructuralNode node) {
logger.debug("convertImage");
StringBuilder sb = new StringBuilder();
appendTitle(node, sb);
appendRoles(node, sb);
sb.append(new BlockImageNode(node).toAsciiDocContent());
return sb.toString();
}
private String convertLiteral(StructuralNode node) {
logger.debug("convertLiteral");
return ATTRIBUTES_BEGIN + node.getContext() + ATTRIBUTES_END + LINE_SEPARATOR +
StringEscapeUtils.unescapeHtml4(node.getContent().toString()) + LINE_SEPARATOR;
}
private String convertParagraph(StructuralNode node) {
logger.debug("convertParagraph");
StringBuilder sb = new StringBuilder();
appendTitle(node, sb);
sb.append(new ParagraphAttributes(node).toAsciiDocContent());
appendSource((Block) node, sb);
appendTrailingNewLine(sb);
return sb.toString();
}
private String convertSection(Section node) {
logger.debug("convertSection");
StringBuilder sb = new StringBuilder();
appendId(node, sb);
sb.append(new DelimitedBlockNode(node).toAsciiDocContent()).append(StringUtils.repeat(TITLE, node.getLevel() + 1))
.append(" ").append(StringEscapeUtils.unescapeHtml4(node.getTitle())).append(LINE_SEPARATOR);
appendChildBlocks(node, sb);
appendTrailingNewLine(sb);
return sb.toString();
}
private void append_link_constraint_attrs(ContentNode node, java.util.List<String> attrs) {
String rel = node.getAttribute("nofollow-option").toString();
String window = node.getAttributes().get("window").toString();
if (StringUtils.isNotBlank(window)) {
attrs.add("target = \"#{window}\"");
if (window.equals("_blank") || (node.getAttributes().containsKey("option-noopener"))) {
if (StringUtils.isNotBlank(rel)) {
attrs.add("rel = \"" + rel + "noopener\"");
} else {
attrs.add(" rel=\"noopener\"");
}
}
} else if (StringUtils.isNotBlank(rel)) {
attrs.add("rel = " + rel + "\"");
}
}
private String repeat(int count, String with) {
return new String(new char[count]).replace("\0", with);
}
private void appendChildBlocks(StructuralNode parentNode, StringBuilder sb) {
appendChildBlocks(parentNode, sb, true);
}
private void appendChildBlocks(StructuralNode parentNode, StringBuilder sb, boolean addTrailingLineSeparator) {
final boolean isParentAListItem = parentNode instanceof ListItem || parentNode instanceof DescriptionListEntry;
parentNode.getBlocks().forEach(childNode -> {
String childNodeValue = childNode.convert();
if (StringUtils.isNotBlank(childNodeValue)) {
if (isParentAListItem && (sb.toString().contains("+" + LINE_SEPARATOR) || !(childNode instanceof List || childNode instanceof DescriptionList))) {
sb.append('+').append(LINE_SEPARATOR);
}
sb.append(childNodeValue);
if (addTrailingLineSeparator && !StringUtils.endsWith(childNodeValue, LINE_SEPARATOR)) {
sb.append(LINE_SEPARATOR);
}
}
});
}
private void appendTrailingNewLine(StringBuilder sb) {
if (!sb.toString().endsWith(LINE_SEPARATOR + LINE_SEPARATOR)) {
sb.append(LINE_SEPARATOR);
}
}
private void appendId(StructuralNode node, StringBuilder sb) {
String id = node.getId();
if (StringUtils.isNotBlank(id)) {
sb.append("[[").append(id).append("]]").append(LINE_SEPARATOR);
}
}
private void appendSource(Block node, StringBuilder sb) {
String source = node.getSource();
if (StringUtils.isNotBlank(source)) {
sb.append(source).append(LINE_SEPARATOR);
}
}
private void appendTitle(StructuralNode node, StringBuilder sb) {
String title = node.getTitle();
if (StringUtils.isNotBlank(title)) {
sb.append(".").append(StringEscapeUtils.unescapeHtml4(title)).append(LINE_SEPARATOR);
}
}
private void appendStyle(StructuralNode node, StringBuilder sb) {
String style = node.getStyle();
if (StringUtils.isNotBlank(style)) {
sb.append(ATTRIBUTES_BEGIN).append(style).append(ATTRIBUTES_END).append(LINE_SEPARATOR);
}
}
private void appendRoles(StructuralNode node, StringBuilder sb) {
java.util.List<String> roles = node.getRoles();
if (!roles.isEmpty()) {
sb.append(ATTRIBUTES_BEGIN).append(".").append(String.join(".", roles))
.append(ATTRIBUTES_END).append(LINE_SEPARATOR);
}
}
private void appendAttributeTo(StructuralNode node, java.util.List<String> attrs, String name) {
String attribution = node.getAttribute(name, "").toString();
if (StringUtils.isNotBlank(attribution)) {
attrs.add(attribution);
}
}
}

View File

@@ -0,0 +1,70 @@
package io.github.swagger2markup.adoc.ast.impl;
import org.asciidoctor.ast.Block;
import org.asciidoctor.ast.StructuralNode;
import java.util.*;
public class BlockImpl extends StructuralNodeImpl implements Block {
private List<String> lines;
public BlockImpl(StructuralNode parent, String context) {
this(parent, context, "");
}
public BlockImpl(StructuralNode parent, String context, Object content) {
this(parent, context, new HashMap<>(), content);
}
public BlockImpl(StructuralNode parent, String context, Map<String, Object> attributes) {
this(parent, context, attributes, "");
}
public BlockImpl(StructuralNode parent, String context, Map<String, Object> attributes, Object content) {
this(parent, context, attributes, new ArrayList<>(), content, new ArrayList<>(), "", new ArrayList<>());
}
public BlockImpl(StructuralNode parent, String context, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, String contentModel, List<String> subs) {
this(parent, context, attributes, roles, content, blocks, calculateLevel(parent), contentModel, subs);
}
public BlockImpl(StructuralNode parent, String context, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, Integer level, String contentModel, List<String> subs) {
super(parent, context, attributes, roles, content, blocks, level, contentModel, subs);
this.lines = new ArrayList<>();
}
@Override
@Deprecated
public List<String> lines() {
return getLines();
}
@Override
public List<String> getLines() {
return lines;
}
@Override
public void setLines(List<String> lines) {
this.lines = lines;
}
@Override
@Deprecated
public String source() {
return getSource();
}
@Override
public String getSource() {
return String.join("\n", lines);
}
@Override
public void setSource(String source) {
setLines(Arrays.asList(source.split("\n")));
}
}

View File

@@ -0,0 +1,112 @@
package io.github.swagger2markup.adoc.ast.impl;
import org.asciidoctor.ast.Cell;
import org.asciidoctor.ast.Column;
import org.asciidoctor.ast.Document;
import org.asciidoctor.ast.Table;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CellImpl extends ContentNodeImpl implements Cell {
private final int colspan;
private final int rowspan;
private String text;
private String style;
private Document innerDocument;
public CellImpl(Column parent, String text) {
this(parent, "table_cell", new HashMap<>(), new ArrayList<>(), 0, 0);
this.text = text;
}
public CellImpl(Column parent, Document innerDocument) {
this(parent, "table_cell", new HashMap<>(), new ArrayList<>(), 0, 0);
this.innerDocument = innerDocument;
}
public CellImpl(Column parent, String context, Map<String, Object> attributes, List<String> roles, int colspan, int rowspan) {
super(parent, context, attributes, roles);
this.colspan = colspan;
this.rowspan = rowspan;
}
@Override
public Column getColumn() {
return (Column) getParent();
}
@Override
public int getColspan() {
return colspan;
}
@Override
public int getRowspan() {
return rowspan;
}
@Override
public String getText() {
return text;
}
@Override
public String getSource() {
return text;
}
@Override
public void setSource(String source) {
this.text = source;
}
@Override
public Object getContent() {
return text;
}
@Override
public String getStyle() {
return style;
}
@Override
public void setStyle(String style) {
this.style = style;
}
@Override
public Table.HorizontalAlignment getHorizontalAlignment() {
return Table.HorizontalAlignment.valueOf(((String) getAttribute("halign", "left")).toUpperCase());
}
@Override
public void setHorizontalAlignment(Table.HorizontalAlignment halign) {
setAttribute("halign", halign.name().toLowerCase(), true);
}
@Override
public Table.VerticalAlignment getVerticalAlignment() {
return Table.VerticalAlignment.valueOf(((String) getAttribute("valign", "top")).toUpperCase());
}
@Override
public void setVerticalAlignment(Table.VerticalAlignment valign) {
setAttribute("valign", valign.name().toLowerCase(), true);
}
@Override
public Document getInnerDocument() {
return innerDocument;
}
@Override
public void setInnerDocument(Document document) {
this.innerDocument = document;
}
}

View File

@@ -0,0 +1,81 @@
package io.github.swagger2markup.adoc.ast.impl;
import org.asciidoctor.ast.Column;
import org.asciidoctor.ast.Table;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ColumnImpl extends ContentNodeImpl implements Column {
private String style;
private Number columnNumber = -1;
private Number width = 0;
public ColumnImpl(Table parent) {
this(parent, "table_column", new HashMap<>(), new ArrayList<>());
}
public ColumnImpl(Table parent, String context, Map<String, Object> attributes, List<String> roles) {
super(parent, context, attributes, roles);
}
@Override
public String getStyle() {
return style;
}
@Override
public void setStyle(String style) {
this.style = style;
}
@Override
public Table getTable() {
return (Table) getParent();
}
@Override
public int getColumnNumber() {
return columnNumber.intValue();
}
public void setColumnNumber(Integer columnNumber) {
setAttribute("colnumber", columnNumber, true);
this.columnNumber = columnNumber;
}
@Override
public int getWidth() {
return width.intValue();
}
@Override
public void setWidth(int width) {
setAttribute("width", width, true);
this.width = width;
}
@Override
public Table.HorizontalAlignment getHorizontalAlignment() {
return Table.HorizontalAlignment.valueOf(((String) getAttribute("halign", "left")).toUpperCase());
}
@Override
public void setHorizontalAlignment(Table.HorizontalAlignment halign) {
setAttribute("halign", halign.name().toLowerCase(), true);
}
@Override
public Table.VerticalAlignment getVerticalAlignment() {
return Table.VerticalAlignment.valueOf(((String) getAttribute("valign", "top")).toUpperCase());
}
@Override
public void setVerticalAlignment(Table.VerticalAlignment valign) {
setAttribute("valign", valign.name().toLowerCase(), true);
}
}

View File

@@ -0,0 +1,309 @@
package io.github.swagger2markup.adoc.ast.impl;
import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.ast.Document;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SuppressWarnings("SuspiciousMethodCalls")
public abstract class ContentNodeImpl implements ContentNode {
private String id;
private final String context;
private final Map<String, Object> attributes;
private final List<String> roles;
private final ContentNode parent;
public ContentNodeImpl(ContentNode parent, String context) {
this(parent, context, new HashMap<>(), new ArrayList<>());
}
public ContentNodeImpl(ContentNode parent, String context, Map<String, Object> attributes, List<String> roles) {
this.parent = parent;
this.context = context;
this.attributes = attributes;
this.roles = roles;
}
@Override
@Deprecated
public String id() {
return getId();
}
@Override
public String getId() {
return id;
}
@Override
public void setId(String id) {
this.id = id.toLowerCase().replaceAll("\\s+", "_");
}
@Override
@Deprecated
public String context() {
return getContext();
}
@Override
public String getContext() {
return context;
}
@Override
@Deprecated
public ContentNode parent() {
return getParent();
}
@Override
public ContentNode getParent() {
return parent;
}
@Override
@Deprecated
public Document document() {
return getDocument();
}
@Override
public Document getDocument() {
throw new UnsupportedOperationException("Not implemented, yet");
}
@Override
public String getNodeName() {
return getContext();
}
@Override
public boolean isInline() {
return false;
}
@Override
public boolean isBlock() {
return false;
}
@Override
public Map<String, Object> getAttributes() {
return attributes;
}
@Override
@Deprecated
public Object getAttr(Object name, Object defaultValue, boolean inherit) {
return getAttribute(name, defaultValue, inherit);
}
@Override
@Deprecated
public Object getAttr(Object name, Object defaultValue) {
return getAttribute(name, defaultValue);
}
@Override
@Deprecated
public Object getAttr(Object name) {
return getAttribute(name);
}
@Override
public Object getAttribute(Object name, Object defaultValue, boolean inherit) {
return getAttribute(name, defaultValue);
}
@Override
public Object getAttribute(Object name, Object defaultValue) {
return attributes.getOrDefault(name, defaultValue);
}
@Override
public Object getAttribute(Object name) {
return attributes.get(name);
}
@Override
@Deprecated
public boolean isAttr(Object name, Object expected, boolean inherit) {
return isAttribute(name, expected, inherit);
}
@Override
@Deprecated
public boolean isAttr(Object name, Object expected) {
return isAttribute(name, expected);
}
@Override
public boolean isAttribute(Object name, Object expected, boolean inherit) {
return isAttribute(name, expected);
}
@Override
public boolean isAttribute(Object name, Object expected) {
try {
if (attributes.containsKey(name)) {
return attributes.get(name).equals(expected);
} else return false;
} catch (Exception e) {
return false;
}
}
@Override
@Deprecated
public boolean hasAttr(Object name) {
return hasAttribute(name);
}
@Override
@Deprecated
public boolean hasAttr(Object name, boolean inherited) {
return hasAttribute(name, inherited);
}
@Override
public boolean hasAttribute(Object name) {
return attributes.containsKey(name);
}
@Override
public boolean hasAttribute(Object name, boolean inherited) {
return hasAttribute(name);
}
@Override
@Deprecated
public boolean setAttr(Object name, Object value, boolean overwrite) {
return setAttribute(name, value, overwrite);
}
@Override
public boolean setAttribute(Object name, Object value, boolean overwrite) {
return setAttribute((String)name, value, overwrite);
}
public boolean setAttribute(String name, Object value, boolean overwrite) {
try {
if (overwrite) {
attributes.put(name, value);
} else {
attributes.putIfAbsent(name, value);
}
return true;
} catch (Exception e) {
return false;
}
}
public Object removeAttribute(String name){
return attributes.remove(name);
}
public boolean removeAttribute(String name, Object value){
return attributes.remove(name, value);
}
@Override
public boolean isOption(Object name) {
try {
Object o = attributes.get(name + "-option");
return null != o && o.toString().equals("");
}catch (Exception ignored){
return false;
}
}
public boolean setOption(String name){
return setAttribute(name + "-option", "", true);
}
public Object removeOption(String name){
return removeAttribute(name + "-option");
}
@Override
public boolean isRole() {
return false;
}
@Override
public String getRole() {
return String.join(",", roles);
}
@Override
@Deprecated
public String role() {
return getRole();
}
@Override
public List<String> getRoles() {
return roles;
}
@Override
public boolean hasRole(String role) {
return roles.contains(role);
}
@Override
public void addRole(String role) {
roles.add(role);
}
@Override
public void removeRole(String role) {
roles.remove(role);
}
@Override
public boolean isReftext() {
throw new UnsupportedOperationException("Not implemented, yet");
}
@Override
public String getReftext() {
throw new UnsupportedOperationException("Not implemented, yet");
}
@Override
public String iconUri(String name) {
throw new UnsupportedOperationException("Not implemented, yet");
}
@Override
public String mediaUri(String target) {
throw new UnsupportedOperationException("Not implemented, yet");
}
@Override
public String imageUri(String targetImage) {
throw new UnsupportedOperationException("Not implemented, yet");
}
@Override
public String imageUri(String targetImage, String assetDirKey) {
throw new UnsupportedOperationException("Not implemented, yet");
}
@Override
public String readAsset(String path, Map<Object, Object> opts) {
throw new UnsupportedOperationException("Not implemented, yet");
}
@Override
public String normalizeWebPath(String path, String start, boolean preserveUriTarget) {
throw new UnsupportedOperationException("Not implemented, yet");
}
}

View File

@@ -0,0 +1,36 @@
package io.github.swagger2markup.adoc.ast.impl;
import org.asciidoctor.ast.Cursor;
public class CursorImpl implements Cursor {
private int lineno;
public CursorImpl() {
}
@Override
public int getLineNumber() {
return lineno;
}
@Override
public String getPath() {
throw new UnsupportedOperationException("Not implemented, yet");
}
@Override
public String getDir() {
throw new UnsupportedOperationException("Not implemented, yet");
}
@Override
public String getFile() {
throw new UnsupportedOperationException("Not implemented, yet");
}
@Override
public String toString() {
throw new UnsupportedOperationException("Not implemented, yet");
}
}

View File

@@ -0,0 +1,66 @@
package io.github.swagger2markup.adoc.ast.impl;
import org.asciidoctor.ast.DescriptionListEntry;
import org.asciidoctor.ast.ListItem;
import org.asciidoctor.ast.StructuralNode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DescriptionListEntryImpl extends StructuralNodeImpl implements DescriptionListEntry {
private final List<ListItem> terms;
private ListItem description;
public DescriptionListEntryImpl(StructuralNode parent) {
this(parent, new ArrayList<>());
}
public DescriptionListEntryImpl(StructuralNode parent, List<ListItem> terms) {
this(parent, terms, null);
}
public DescriptionListEntryImpl(StructuralNode parent, List<ListItem> terms, ListItem description) {
this(parent, null, terms, description);
}
public DescriptionListEntryImpl(StructuralNode parent, Object content, List<ListItem> terms, ListItem description) {
this(parent, new HashMap<>(), new ArrayList<>(), content, new ArrayList<>(), "", new ArrayList<>(), terms, description);
}
public DescriptionListEntryImpl(StructuralNode parent, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, String contentModel, List<String> subs,
List<ListItem> terms, ListItem description) {
this(parent, attributes, roles, content, blocks, null != parent ? parent.getLevel() : 1, contentModel, subs, terms, description);
}
public DescriptionListEntryImpl(StructuralNode parent, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, Integer level, String contentModel,
List<String> subs, List<ListItem> terms, ListItem description) {
super(parent, "dlist_item", attributes, roles, content, blocks, level, contentModel, subs);
this.terms = terms;
this.description = description;
}
@Override
public List<ListItem> getTerms() {
return terms;
}
public boolean addTerm(ListItem term) {
return terms.add(term);
}
@Override
public ListItem getDescription() {
return description;
}
public void setDescription(final ListItem description) {
this.description = description;
}
}

View File

@@ -0,0 +1,72 @@
package io.github.swagger2markup.adoc.ast.impl;
import org.asciidoctor.ast.DescriptionList;
import org.asciidoctor.ast.DescriptionListEntry;
import org.asciidoctor.ast.StructuralNode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DescriptionListImpl extends StructuralNodeImpl implements DescriptionList {
public static final String CONTEXT = "dlist";
private List<DescriptionListEntry> items;
public DescriptionListImpl(StructuralNode parent) {
this(parent, new ArrayList<>());
}
public DescriptionListImpl(StructuralNode parent, List<DescriptionListEntry> items) {
this(parent, null, items);
}
public DescriptionListImpl(StructuralNode parent, Object content, List<DescriptionListEntry> items) {
this(parent, new HashMap<>(), new ArrayList<>(), content, new ArrayList<>(), "", new ArrayList<>(), items);
}
public DescriptionListImpl(StructuralNode parent, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, String contentModel,
List<String> subs, List<DescriptionListEntry> items) {
this(parent, attributes, roles, content, blocks, calculateLevel(parent), contentModel, subs, items);
}
public DescriptionListImpl(StructuralNode parent, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, Integer level,
String contentModel, List<String> subs, List<DescriptionListEntry> items) {
super(parent, CONTEXT, attributes, roles, content, blocks, level, contentModel, subs);
this.items = items;
}
@Override
public List<DescriptionListEntry> getItems() {
return items;
}
public void setItems(List<DescriptionListEntry> items) {
this.items = items;
}
public void addEntry(DescriptionListEntry entry) {
this.items.add(entry);
}
@Override
public boolean hasItems() {
return !items.isEmpty();
}
@Override
@Deprecated
public String render() {
return convert();
}
protected static Integer calculateLevel(StructuralNode parent) {
int level = 1;
if (parent instanceof DescriptionList)
level = parent.getLevel() + 1;
return level;
}
}

View File

@@ -0,0 +1,89 @@
package io.github.swagger2markup.adoc.ast.impl;
import org.asciidoctor.ast.Document;
import org.asciidoctor.ast.StructuralNode;
import org.asciidoctor.ast.Title;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DocumentImpl extends StructuralNodeImpl implements Document {
public DocumentImpl() {
this(null);
}
public DocumentImpl(StructuralNode parent) {
this(parent, "document", "");
}
public DocumentImpl(StructuralNode parent, String context, Object content) {
this(parent, context, new HashMap<>(), new ArrayList<>(), content, new ArrayList<>(), "", new ArrayList<>());
}
public DocumentImpl(StructuralNode parent, String context, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, String contentModel,
List<String> subs) {
this(parent, context, attributes, roles, content, blocks, null != parent ? parent.getLevel() + 1 : 0, contentModel, subs);
}
public DocumentImpl(StructuralNode parent, String context, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, Integer level, String contentModel,
List<String> subs) {
super(parent, context, attributes, roles, content, blocks, level, contentModel, subs);
}
@Override
public boolean isBasebackend(String backend) {
return isAttribute("basebackend", backend);
}
@Override
@Deprecated
public boolean basebackend(String backend) {
return isBasebackend(backend);
}
@Override
public Map<Object, Object> getOptions() {
return null;
}
@Override
public Title getStructuredDoctitle() {
return (Title) getOptions().get("doctitle");
}
@Override
public String getDoctitle() {
return getTitle();
}
@Override
@Deprecated
public String doctitle() {
return getDoctitle();
}
@Override
public int getAndIncrementCounter(String name) {
throw new UnsupportedOperationException("Not implemented, yet");
}
@Override
public int getAndIncrementCounter(String name, int initialValue) {
throw new UnsupportedOperationException("Not implemented, yet");
}
@Override
public boolean isSourcemap() {
throw new UnsupportedOperationException("Not implemented, yet");
}
@Override
public void setSourcemap(boolean state) {
throw new UnsupportedOperationException("Not implemented, yet");
}
}

View File

@@ -0,0 +1,56 @@
package io.github.swagger2markup.adoc.ast.impl;
import org.asciidoctor.ast.List;
import org.asciidoctor.ast.StructuralNode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class ListImpl extends StructuralNodeImpl implements List {
private final java.util.List<StructuralNode> items;
public ListImpl(StructuralNode parent, String context) {
this(parent, context, new ArrayList<>());
}
public ListImpl(StructuralNode parent, String context, java.util.List<StructuralNode> items) {
this(parent, context, null, items);
}
public ListImpl(StructuralNode parent, String context, Object content, java.util.List<StructuralNode> items) {
this(parent, context, new HashMap<>(), new ArrayList<>(), content, new ArrayList<>(), "", new ArrayList<>(), items);
}
public ListImpl(StructuralNode parent, String context, Map<String, Object> attributes, java.util.List<String> roles,
Object content, java.util.List<StructuralNode> blocks,
String contentModel, java.util.List<String> subs, java.util.List<StructuralNode> items) {
this(parent, context, attributes, roles, content, blocks, null != parent ? parent.getLevel() + 1 : 0, contentModel, subs, items);
}
public ListImpl(StructuralNode parent, String context, Map<String, Object> attributes, java.util.List<String> roles,
Object content, java.util.List<StructuralNode> blocks,
Integer level, String contentModel, java.util.List<String> subs, java.util.List<StructuralNode> items) {
super(parent, context, attributes, roles, content, blocks, level, contentModel, subs);
this.items = items;
}
@Override
public java.util.List<StructuralNode> getItems() {
return items;
}
@Override
public boolean hasItems() {
return !items.isEmpty();
}
@Override
@Deprecated
public String render() {
return convert();
}
}

View File

@@ -0,0 +1,63 @@
package io.github.swagger2markup.adoc.ast.impl;
import org.apache.commons.lang3.StringUtils;
import org.asciidoctor.ast.ListItem;
import org.asciidoctor.ast.StructuralNode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ListItemImpl extends StructuralNodeImpl implements ListItem {
private final String marker;
private String text;
public ListItemImpl(StructuralNode parent, String text) {
this(parent, "list_item", null, "*", text);
}
public ListItemImpl(StructuralNode parent, String context, Object content, String marker, String text) {
this(parent, context, new HashMap<>(), new ArrayList<>(), content, new ArrayList<>(), "", new ArrayList<>(), marker, text);
}
public ListItemImpl(StructuralNode parent, String context, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, String contentModel,
List<String> subs, String marker, String text) {
this(parent, context, attributes, roles, content, blocks, null != parent ? parent.getLevel() : 1, contentModel, subs, marker, text);
}
public ListItemImpl(StructuralNode parent, String context, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, Integer level,
String contentModel, List<String> subs, String marker, String text) {
super(parent, context, attributes, roles, content, blocks, level, contentModel, subs);
this.marker = marker;
this.text = text;
}
@Override
public String getMarker() {
return marker;
}
@Override
public String getText() {
return text;
}
@Override
public String getSource() {
return text;
}
@Override
public void setSource(String source) {
this.text = source;
}
@Override
public boolean hasText() {
return StringUtils.isNotBlank(text);
}
}

View File

@@ -0,0 +1,38 @@
package io.github.swagger2markup.adoc.ast.impl;
import org.asciidoctor.ast.StructuralNode;
import java.util.List;
import java.util.Map;
public class ParagraphBlockImpl extends BlockImpl {
public static final String CONTEXT = "paragraph";
public ParagraphBlockImpl(StructuralNode parent) {
super(parent, CONTEXT);
}
public ParagraphBlockImpl(StructuralNode parent, Object content) {
super(parent, CONTEXT, content);
}
public ParagraphBlockImpl(StructuralNode parent, Map<String, Object> attributes) {
super(parent, CONTEXT, attributes);
}
public ParagraphBlockImpl(StructuralNode parent, Map<String, Object> attributes, Object content) {
super(parent, CONTEXT, attributes, content);
}
public ParagraphBlockImpl(StructuralNode parent, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, String contentModel, List<String> subs) {
super(parent, CONTEXT, attributes, roles, content, blocks, contentModel, subs);
}
public ParagraphBlockImpl(StructuralNode parent, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, Integer level, String contentModel,
List<String> subs) {
super(parent, CONTEXT, attributes, roles, content, blocks, level, contentModel, subs);
}
}

View File

@@ -0,0 +1,50 @@
package io.github.swagger2markup.adoc.ast.impl;
import io.github.swagger2markup.adoc.AsciidocConverter;
import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.ast.PhraseNode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PhraseNodeImpl extends ContentNodeImpl implements PhraseNode {
private final String type;
private final String text;
private final String target;
private final AsciidocConverter converter = new AsciidocConverter(AsciidocConverter.NAME, new HashMap<>());
public PhraseNodeImpl(ContentNode parent, String context, Map<String, Object> attributes, List<String> roles, String type, String text, String target) {
super(parent, context, attributes, roles);
this.type = type;
this.text = text;
this.target = target;
}
@Override
@Deprecated
public String render() {
return convert();
}
@Override
public String convert() {
return converter.convert(this, null, new HashMap<>());
}
@Override
public String getType() {
return type;
}
@Override
public String getText() {
return text;
}
@Override
public String getTarget() {
return target;
}
}

View File

@@ -0,0 +1,21 @@
package io.github.swagger2markup.adoc.ast.impl;
import org.asciidoctor.ast.Cell;
import org.asciidoctor.ast.Row;
import java.util.List;
public class RowImpl implements Row {
private final List<Cell> cells;
public RowImpl(List<Cell> cells) {
this.cells = cells;
}
@Override
public List<Cell> getCells() {
return cells;
}
}

View File

@@ -0,0 +1,118 @@
package io.github.swagger2markup.adoc.ast.impl;
import org.asciidoctor.ast.Section;
import org.asciidoctor.ast.StructuralNode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SectionImpl extends StructuralNodeImpl implements Section {
private final Integer index;
private final Integer number;
private final String numeral;
private final String sectionName;
private final boolean special;
private final boolean numbered;
public SectionImpl(StructuralNode parent) {
this(parent, new HashMap<>());
}
public SectionImpl(StructuralNode parent, Map<String, Object> attributes) {
this(parent, "section", null, "");
}
public SectionImpl(StructuralNode parent, String context, Object content, String sectionName) {
this(parent, context, content, null, null, "", sectionName, false, false);
}
public SectionImpl(StructuralNode parent, String context, Object content, Integer index, Integer number, String numeral,
String sectionName, boolean special, boolean numbered) {
this(parent, context, new HashMap<>(), new ArrayList<>(), content, new ArrayList<>(),
"", new ArrayList<>(), index, number, numeral, sectionName, special, numbered);
}
public SectionImpl(StructuralNode parent, String context, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, String contentModel, List<String> subs,
Integer index, Integer number, String numeral, String sectionName, boolean special, boolean numbered) {
this(parent, context, attributes, roles, content, blocks, calculateLevel(parent), contentModel, subs, index, number, numeral, sectionName, special, numbered);
}
public SectionImpl(StructuralNode parent, String context, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, Integer level, String contentModel, List<String> subs,
Integer index, Integer number, String numeral, String sectionName, boolean special, boolean numbered) {
super(parent, context, attributes, roles, content, blocks, level, contentModel, subs);
this.index = index;
this.number = number;
this.numeral = numeral;
this.sectionName = sectionName;
this.special = special;
this.numbered = numbered;
}
@Override
@Deprecated
public int index() {
return getIndex();
}
@Override
public int getIndex() {
return index;
}
@Override
@Deprecated
public int number() {
return getNumber();
}
@Override
@Deprecated
public int getNumber() {
return number;
}
@Override
public String getNumeral() {
return numeral;
}
@Override
@Deprecated
public String sectname() {
return getSectionName();
}
@Override
public String getSectionName() {
return sectionName;
}
@Override
@Deprecated
public boolean special() {
return isSpecial();
}
@Override
public boolean isSpecial() {
return special;
}
@Override
@Deprecated
public boolean numbered() {
return isNumbered();
}
@Override
public boolean isNumbered() {
return numbered;
}
}

View File

@@ -0,0 +1,179 @@
package io.github.swagger2markup.adoc.ast.impl;
import io.github.swagger2markup.adoc.AsciidocConverter;
import org.asciidoctor.ast.Cursor;
import org.asciidoctor.ast.StructuralNode;
import java.util.*;
public class StructuralNodeImpl extends ContentNodeImpl implements StructuralNode {
private String title;
private String caption;
private String style;
private final Object content;
private final List<StructuralNode> blocks;
private Integer level;
private final String contentModel;
private List<String> subs;
private final AsciidocConverter converter = new AsciidocConverter(AsciidocConverter.NAME, new HashMap<>());
public StructuralNodeImpl(StructuralNode parent, String context) {
this(parent, context, new HashMap<>());
}
public StructuralNodeImpl(StructuralNode parent, String context, Map<String, Object> attributes) {
this(parent, context, attributes, null);
}
public StructuralNodeImpl(StructuralNode parent, String context, Object content) {
this(parent, context, new HashMap<>(), content);
}
public StructuralNodeImpl(StructuralNode parent, String context, Map<String, Object> attributes, Object content) {
this(parent, context, attributes, new ArrayList<>(), content, new ArrayList<>(), "", new ArrayList<>());
}
public StructuralNodeImpl(StructuralNode parent, String context, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, String contentModel, List<String> subs) {
this(parent, context, attributes, roles, content, blocks, calculateLevel(parent), contentModel, subs);
}
public StructuralNodeImpl(StructuralNode parent, String context, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, Integer level, String contentModel, List<String> subs) {
super(parent, context, attributes, roles);
this.content = content;
this.blocks = blocks;
this.level = level;
this.contentModel = contentModel;
this.subs = subs;
}
@Override
@Deprecated
public String title() {
return getTitle();
}
@Override
public String getTitle() {
return title;
}
@Override
public void setTitle(String title) {
this.title = title;
}
@Override
public String getCaption() {
return caption;
}
@Override
public void setCaption(String caption) {
this.caption = caption;
}
@Override
@Deprecated
public String style() {
return getStyle();
}
@Override
public String getStyle() {
return style;
}
@Override
public void setStyle(String style) {
this.style = style;
}
@Override
@Deprecated
public List<StructuralNode> blocks() {
return getBlocks();
}
@Override
public List<StructuralNode> getBlocks() {
return blocks;
}
@Override
public void append(StructuralNode block) {
blocks.add(block);
}
@Override
@Deprecated
public Object content() {
return getContent();
}
@Override
public Object getContent() {
return content;
}
@Override
public String convert() {
return converter.convert(this, null, new HashMap<>());
}
@Override
public int getLevel() {
return level;
}
@Override
public Cursor getSourceLocation() {
return new CursorImpl();
}
@Override
public String getContentModel() {
return contentModel;
}
@Override
public List<String> getSubstitutions() {
return subs;
}
@Override
public boolean isSubstitutionEnabled(String substitution) {
return subs.contains(substitution);
}
@Override
public void removeSubstitution(String substitution) {
subs.remove(substitution);
}
@Override
public void addSubstitution(String substitution) {
subs.add(substitution);
}
@Override
public void prependSubstitution(String substitution) {
}
@Override
public void setSubstitutions(String... substitutions) {
subs = Arrays.asList(substitutions);
}
@Override
public List<StructuralNode> findBy(Map<Object, Object> selector) {
throw new UnsupportedOperationException("Not implemented, yet");
}
protected static Integer calculateLevel(StructuralNode parent) {
return null != parent ? parent.getLevel() + 1 : 0;
}
}

View File

@@ -0,0 +1,306 @@
package io.github.swagger2markup.adoc.ast.impl;
import org.asciidoctor.ast.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.*;
public class TableImpl extends StructuralNodeImpl implements Table {
public static final String OPTION_UNBREAKABLE = "unbreakable";
public static final String OPTION_BREAKABLE = "breakable";
private Logger logger = LoggerFactory.getLogger(getClass());
public static final String CONTEXT = "table";
private static final String FRAME_ATTR = "frame";
private static final String GRID_ATTR = "grid";
private RowList headerRows;
private RowList bodyRows;
private RowList footerRows;
private List<Column> columns = new ArrayList<>();
public TableImpl(StructuralNode parent) {
this(parent, new HashMap<>(), new ArrayList<>());
}
public TableImpl(StructuralNode parent, Map<String, Object> attributes, List<String> roles) {
this(parent, attributes, roles, calculateLevel(parent));
}
public TableImpl(StructuralNode parent, Map<String, Object> attributes, List<String> roles, Integer level) {
this(parent, attributes, roles, null, new ArrayList<>(), level, "", new ArrayList<>());
}
public TableImpl(StructuralNode parent, Map<String, Object> attributes, List<String> roles,
Object content, List<StructuralNode> blocks, Integer level, String contentModel, List<String> subs) {
super(parent, CONTEXT, attributes, roles, content, blocks, level, contentModel, subs);
this.headerRows = new RowList(new ArrayList<>());
this.bodyRows = new RowList(new ArrayList<>());
this.footerRows = new RowList(new ArrayList<>());
}
@Override
public boolean hasHeaderOption() {
return isOption("header");
}
@Override
public String getFrame() {
return (String) getAttribute(FRAME_ATTR, "all");
}
@Override
public void setFrame(String frame) {
setAttribute(FRAME_ATTR, frame, true);
}
@Override
public String getGrid() {
return (String) getAttribute(GRID_ATTR, "all");
}
@Override
public void setGrid(String grid) {
setAttribute(GRID_ATTR, grid, true);
}
@Override
public List<Column> getColumns() {
return columns;
}
@Override
public List<Row> getHeader() {
return headerRows;
}
public void setHeaderRow(Row row) {
headerRows.clear();
headerRows.add(row);
scanRowForColumns(row);
}
public void setHeaderRow(List<Cell> cells) {
setHeaderRow(new RowImpl(cells));
}
public void setHeaderRow(String... documentContents) {
headerRows.clear();
headerRows.add(generateRow(documentContents));
}
public RowImpl generateRow(Document... innerDocs) {
List<Cell> cells = new ArrayList<>();
for (int i = 0; i < innerDocs.length; i++) {
Column column = null;
try {
column = columns.get(i);
} catch (Exception ignored) {
}
if (null == column) {
ColumnImpl newColumn = new ColumnImpl(this);
newColumn.setColumnNumber(i + 1);
column = newColumn;
addColumnAt(column, i);
}
cells.add(new CellImpl(column, innerDocs[i]));
}
return new RowImpl(cells);
}
public RowImpl generateRow(String... documentContents) {
Document[] documents = Arrays.stream(documentContents).map(documentContent -> {
Document innerDoc = new DocumentImpl();
Block paragraph = new ParagraphBlockImpl(innerDoc);
paragraph.setSource(documentContent);
innerDoc.append(paragraph);
return innerDoc;
}).toArray(Document[]::new);
return generateRow(documents);
}
@Override
public List<Row> getBody() {
return bodyRows;
}
public void setBodyRows(List<Row> rows) {
bodyRows.clear();
bodyRows.addAll(rows);
bodyRows.forEach(this::scanRowForColumns);
}
public void addRow(Row row) {
bodyRows.add(row);
scanRowForColumns(row);
}
public void addRow(List<Cell> cells) {
bodyRows.add(new RowImpl(cells));
}
public RowImpl addRow(Document... documentContents) {
RowImpl row = generateRow(documentContents);
bodyRows.add(row);
return row;
}
public RowImpl addRow(String... documentContents) {
RowImpl row = generateRow(documentContents);
bodyRows.add(row);
return row;
}
@Override
public List<Row> getFooter() {
return footerRows;
}
public void setFooterRow(Row row) {
footerRows.clear();
footerRows.add(row);
scanRowForColumns(row);
}
public void setFooterRow(String... documentContents) {
footerRows.clear();
footerRows.add(generateRow(documentContents));
}
private void scanRowForColumns(Row row) {
row.getCells().forEach(cell -> {
Column column = cell.getColumn();
int i = column.getColumnNumber() - 1;
addColumnAt(column, i);
});
}
private void addColumnAt(Column column, int i) {
if (columns.size() >= i) {
columns.add(i, column);
} else {
while (columns.size() < i) {
columns.add(columns.size(), null);
}
columns.add(column);
}
}
public void setFooterRow(List<Cell> cells) {
setFooterRow(new RowImpl(cells));
}
class RowList extends AbstractList<Row> {
private final List<Row> rubyArray;
private RowList(List<Row> rubyArray) {
this.rubyArray = rubyArray;
}
@Override
public int size() {
return rubyArray.size();
}
@Override
public boolean isEmpty() {
return rubyArray.isEmpty();
}
@Override
public boolean contains(Object o) {
return rubyArray.contains(o);
}
@Override
public boolean add(Row row) {
boolean changed = false;
try {
changed = rubyArray.add(row);
setAttribute("rowcount", size(), true);
} catch (Exception e) {
logger.debug("Couldn't add row", e);
}
return changed;
}
@Override
public boolean remove(Object o) {
if (!(o instanceof RowImpl)) {
return false;
}
try {
boolean changed = rubyArray.remove(o);
setAttribute("rowcount", size(), true);
return changed;
} catch (Exception e) {
logger.debug("Couldn't add row", e);
return false;
}
}
@Override
public boolean retainAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
rubyArray.clear();
setAttribute("rowcount", size(), true);
}
@Override
public Row get(int index) {
return rubyArray.get(index);
}
@Override
public Row set(int index, Row element) {
Row oldRow = get(index);
rubyArray.set(index, element);
return oldRow;
}
@Override
public void add(int index, Row element) {
rubyArray.add(index, element);
setAttribute("rowcount", size(), true);
}
@Override
public Row remove(int index) {
Row removed = rubyArray.remove(index);
setAttribute("rowcount", size(), true);
return removed;
}
@Override
public int indexOf(Object o) {
if (!(o instanceof RowImpl)) {
return -1;
}
return rubyArray.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
if (!(o instanceof RowImpl)) {
return -1;
}
return rubyArray.lastIndexOf(o);
}
}
protected static Integer calculateLevel(StructuralNode parent) {
int level = 1;
if (parent instanceof Table)
level = parent.getLevel() + 1;
return level;
}
}

View File

@@ -0,0 +1,34 @@
package io.github.swagger2markup.adoc.ast.impl;
import org.asciidoctor.ast.Title;
public class TitleImpl implements Title {
private final String main;
private final String subtitle;
public TitleImpl(String main, String subtitle) {
this.main = main;
this.subtitle = subtitle;
}
@Override
public String getMain() {
return main;
}
@Override
public String getSubtitle() {
return subtitle;
}
@Override
public String getCombined() {
return main + ": " + subtitle;
}
@Override
public boolean isSanitized() {
return false;
}
}

View File

@@ -0,0 +1,50 @@
package io.github.swagger2markup.adoc.converter.internal;
import org.apache.commons.lang3.StringUtils;
import org.asciidoctor.ast.ContentNode;
public class BlockImageNode extends NodeAttributes {
final private String target;
public BlockImageNode(ContentNode node) {
super(node.getAttributes());
target = pop("target").replaceAll("\\s", "{sp}");
}
public String getTarget() {
return target;
}
@Override
public void processPositionalAttributes() {
String attr1 = pop("1", "alt");
if (StringUtils.isNotBlank(attr1)) {
attrs.add(attr1);
}
String attr2 = pop("2", "width");
if (StringUtils.isNotBlank(attr2)) {
attrs.add(attr2);
}
String attr3 = pop("3", "height");
if (StringUtils.isNotBlank(attr3)) {
attrs.add(attr3);
}
}
@Override
void processAttributes() {
attributes.forEach((k, v) -> {
if (!k.equals("role") && null != v) {
attrs.add(k + "=" + v);
}
});
}
@Override
public String processAsciiDocContent() {
return "image::" + target + '[' + String.join(",", attrs) + ']';
}
}

View File

@@ -0,0 +1,31 @@
package io.github.swagger2markup.adoc.converter.internal;
import org.asciidoctor.ast.Block;
import java.util.List;
import static io.github.swagger2markup.adoc.converter.internal.Delimiters.*;
public class BlockListingNode extends ParagraphAttributes {
final private Block node;
public BlockListingNode(Block node) {
super(node);
this.node = node;
}
@Override
public String processAsciiDocContent() {
StringBuilder sb = new StringBuilder();
attrsToString(sb, attrs);
sb.append(LINE_SEPARATOR).append(DELIMITER_BLOCK).append(LINE_SEPARATOR).append(node.getSource()).append(LINE_SEPARATOR).append(DELIMITER_BLOCK).append(LINE_SEPARATOR);
return sb.toString();
}
void attrsToString(StringBuilder sb, List<String> list) {
if (!list.isEmpty()) {
sb.append(ATTRIBUTES_BEGIN).append(String.join(",", list)).append(ATTRIBUTES_END).append(LINE_SEPARATOR);
}
}
}

View File

@@ -0,0 +1,45 @@
package io.github.swagger2markup.adoc.converter.internal;
import org.apache.commons.lang3.StringUtils;
import org.asciidoctor.ast.StructuralNode;
import java.util.ArrayList;
import java.util.List;
import static io.github.swagger2markup.adoc.converter.internal.Delimiters.*;
public class DelimitedBlockNode extends ParagraphAttributes {
public DelimitedBlockNode(StructuralNode node) {
super(node);
}
@Override
public void processPositionalAttributes() {
String source = pop("1", "style");
StringBuilder options = new StringBuilder();
List<String> toRemove = new ArrayList<>();
attributes.forEach((k, v) -> {
if (k.endsWith(OPTION_SUFFIX)) {
toRemove.add(k);
options.append('%').append(k.replace(OPTION_SUFFIX, ""));
}
});
toRemove.forEach(attributes::remove);
source += options.toString();
if (StringUtils.isNotBlank(source)) {
attrs.add(source);
}
super.processPositionalAttributes();
}
@Override
public String processAsciiDocContent() {
StringBuilder sb = new StringBuilder();
if (!attrs.isEmpty()) {
sb.append(ATTRIBUTES_BEGIN).append(String.join(",", attrs)).append(ATTRIBUTES_END).append(LINE_SEPARATOR);
}
return sb.toString();
}
}

View File

@@ -0,0 +1,26 @@
package io.github.swagger2markup.adoc.converter.internal;
public class Delimiters {
public static final String ATTRIBUTES_BEGIN = "[";
public static final String ATTRIBUTES_END = "]";
public static final String COLON = ":";
public static final String DELIMITER_BLOCK = "----";
public static final String DELIMITER_EXAMPLE = "====";
public static final String DELIMITER_INNER_TABLE_CELL = "!";
public static final String DELIMITER_INNER_TABLE = "!===";
public static final String DELIMITER_PAGE_BREAK = "<<<";
public static final String DELIMITER_OPEN_BLOCK = "--";
public static final String DELIMITER_SIDEBAR = "****";
public static final String DELIMITER_TABLE = "|===";
public static final String DELIMITER_TABLE_CELL = "|";
public static final String DELIMITER_THEMATIC_BREAK = "'''";
public static final String DELIMITER_VERSE = "____";
public static final String DOCUMENT_TITLE = "=";
public static final String LINE_SEPARATOR = "\n";
public static final String MARKER_LIST_ITEM = "*";
public static final String MARKER_D_LIST_ITEM = ":";
public static final String STYLE_HORIZONTAL = "horizontal";
public static final String STYLE_Q_AND_A = "qanda";
public static final String STYLE_SOURCE = "source";
public static final String TITLE = "=";
}

View File

@@ -0,0 +1,38 @@
package io.github.swagger2markup.adoc.converter.internal;
import org.apache.commons.lang3.StringUtils;
import org.asciidoctor.ast.ContentNode;
public class IconNode extends NodeAttributes {
final private String alt;
public IconNode(ContentNode node) {
super(node.getAttributes());
alt = pop("alt", "default-alt");
}
public String getAlt() {
return alt;
}
@Override
void processPositionalAttributes() {
String attr1 = pop("1", "size");
if (StringUtils.isNotBlank(attr1)) {
attrs.add(attr1);
}
}
@Override
void processAttributes() {
attributes.forEach((k, v) -> {
attrs.add(k + "=" + v);
});
}
@Override
String processAsciiDocContent() {
return "icon:" + alt + '[' + String.join(",", attrs) + ']';
}
}

View File

@@ -0,0 +1,64 @@
package io.github.swagger2markup.adoc.converter.internal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
import static io.github.swagger2markup.adoc.converter.internal.Delimiters.*;
abstract class NodeAttributes {
public static final String TITLE = "title";
final Map<String, Object> attributes;
List<String> attrs = new ArrayList<>();
NodeAttributes(Map<String, Object> attributes) {
this.attributes = attributes;
}
public String pop(String... keys) {
AtomicReference<String> value = new AtomicReference<>("");
Stream.of(keys).forEach(key -> {
try {
String tmpValue = attributes.remove(key).toString();
if (null != tmpValue && !tmpValue.isEmpty() && value.get().isEmpty()) {
value.set(tmpValue);
}
} catch (NullPointerException ignored) {
}
});
return value.get();
}
String pop(String key) {
try {
String value = attributes.remove(key).toString();
if (null == value) {
value = "";
}
return value;
} catch (NullPointerException ignored) {
return "";
}
}
final public String toAsciiDocContent() {
processPositionalAttributes();
processAttributes();
return processAsciiDocContent();
}
abstract void processPositionalAttributes();
abstract void processAttributes();
String processAsciiDocContent() {
StringBuilder sb = new StringBuilder();
if (!attrs.isEmpty()) {
sb.append(ATTRIBUTES_BEGIN).append(String.join(",", attrs)).append(ATTRIBUTES_END).append(LINE_SEPARATOR);
}
return sb.toString();
}
}

View File

@@ -0,0 +1,63 @@
package io.github.swagger2markup.adoc.converter.internal;
import org.apache.commons.lang3.StringUtils;
import org.asciidoctor.ast.StructuralNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class ParagraphAttributes extends NodeAttributes {
public static final String OPTION_SUFFIX = "-option";
private Logger logger = LoggerFactory.getLogger(getClass());
public ParagraphAttributes(StructuralNode node) {
super(node.getAttributes());
}
@Override
public void processPositionalAttributes() {
String attr1 = pop("1", "style");
if (StringUtils.isNotBlank(attr1)) {
attrs.add(attr1);
}
}
@Override
void processAttributes() {
String id = pop("id");
if (StringUtils.isNotBlank(id)) {
id = "#" + id;
}
String roles = String.join(".", pop("role").split(" "));
if (StringUtils.isNotBlank(roles)) {
roles = "." + roles;
}
StringBuilder options = new StringBuilder();
List<String> namedAttributes = new ArrayList<>();
attributes.forEach((k, v) -> {
if (k.equals(TITLE)) {
logger.debug("Skipping attribute: " + TITLE);
} else if (k.endsWith(OPTION_SUFFIX)) {
options.append('%').append(k.replace(OPTION_SUFFIX, ""));
} else if (null != v) {
if(v.toString().contains(" ") || v.toString().contains(",")) {
namedAttributes.add(k + "=\"" + v +"\"");
} else {
namedAttributes.add(k + "=" + v);
}
} else {
logger.warn("Don't know how to handle key: " + k);
}
});
String nonNamedAttributes = id + roles + options.toString();
if (StringUtils.isNotBlank(nonNamedAttributes)) {
attrs.add(nonNamedAttributes);
}
attrs.addAll(namedAttributes);
}
}

View File

@@ -0,0 +1,53 @@
package io.github.swagger2markup.adoc.converter.internal;
import org.apache.commons.lang3.StringUtils;
import org.asciidoctor.ast.Block;
import java.util.ArrayList;
import java.util.List;
import static io.github.swagger2markup.adoc.converter.internal.Delimiters.*;
public class SourceNode extends BlockListingNode {
private List<String> sourceAttrs = new ArrayList<>();
private final Block node;
public SourceNode(Block node) {
super(node);
this.node = node;
}
@Override
public void processPositionalAttributes() {
String source = pop("1", "style");
String language = pop("2", "language");
StringBuilder options = new StringBuilder();
List<String> toRemove = new ArrayList<>();
attributes.forEach((k, v) -> {
if (k.endsWith(OPTION_SUFFIX)) {
toRemove.add(k);
options.append('%').append(k.replace(OPTION_SUFFIX, ""));
}
});
toRemove.forEach(attributes::remove);
source += options.toString();
if (StringUtils.isNotBlank(source)) {
sourceAttrs.add(source);
}
if (StringUtils.isNotBlank(language)) {
sourceAttrs.add(language);
}
super.processPositionalAttributes();
}
@Override
public String processAsciiDocContent() {
StringBuilder sb = new StringBuilder();
attrsToString(sb, attrs);
attrsToString(sb, sourceAttrs);
sb.append(LINE_SEPARATOR).append(DELIMITER_BLOCK).append(LINE_SEPARATOR).append(node.getSource()).append(LINE_SEPARATOR).append(DELIMITER_BLOCK).append(LINE_SEPARATOR);
return sb.toString();
}
}

View File

@@ -0,0 +1,35 @@
package io.github.swagger2markup.adoc.converter.internal;
import org.apache.commons.lang3.StringUtils;
public enum Style {
ASCIIDOC("a"), EMPHASIS("e"), HEADER("h"), LITERAL("l"), MONOSPACED("m"), NONE("d"), STRONG("s"), VERSE("v");
String shortHand;
Style(String h) {
this.shortHand = h;
}
public static Style fromString(String text) {
if(StringUtils.isNotBlank(text)) {
for (Style s : Style.values()) {
if (s.shortHand.equalsIgnoreCase(text)) {
return s;
}
}
}
return null;
}
public static Style fromName(String text) {
if(StringUtils.isNotBlank(text)) {
return valueOf(text.toUpperCase());
}
return null;
}
public String getShortHand() {
return shortHand;
}
}

View File

@@ -0,0 +1,35 @@
package io.github.swagger2markup.adoc.converter.internal;
import org.apache.commons.lang3.StringUtils;
public enum TableCellHorizontalAlignment {
LEFT("<"), CENTER("^"), RIGHT(">");
String delimiter;
TableCellHorizontalAlignment(String s) {
this.delimiter = s;
}
public static TableCellHorizontalAlignment fromString(String text) {
if(StringUtils.isNotBlank(text)) {
for (TableCellHorizontalAlignment a : TableCellHorizontalAlignment.values()) {
if (a.delimiter.equalsIgnoreCase(text)) {
return a;
}
}
}
return null;
}
public static TableCellHorizontalAlignment fromName(String text) {
if(StringUtils.isNotBlank(text)) {
return valueOf(text.toUpperCase());
}
return null;
}
public String getDelimiter() {
return delimiter;
}
}

View File

@@ -0,0 +1,15 @@
package io.github.swagger2markup.adoc.converter.internal;
public class TableCellStyle {
public final TableCellHorizontalAlignment horizontalAlignment;
public final TableCellVerticalAlignment verticalAlignment;
public final Style style;
public final int width;
public TableCellStyle(TableCellHorizontalAlignment horizontalAlignment, TableCellVerticalAlignment verticalAlignment, Style style, int width) {
this.horizontalAlignment = horizontalAlignment;
this.verticalAlignment = verticalAlignment;
this.style = style;
this.width = width;
}
}

View File

@@ -0,0 +1,35 @@
package io.github.swagger2markup.adoc.converter.internal;
import org.apache.commons.lang3.StringUtils;
public enum TableCellVerticalAlignment {
TOP(".<"), MIDDLE(".^"), BOTTOM(".>");
String delimiter;
TableCellVerticalAlignment(String s) {
this.delimiter = s;
}
public static TableCellVerticalAlignment fromString(String text) {
if(StringUtils.isNotBlank(text)) {
for (TableCellVerticalAlignment a : TableCellVerticalAlignment.values()) {
if (a.delimiter.equalsIgnoreCase(text)) {
return a;
}
}
}
return null;
}
public static TableCellVerticalAlignment fromName(String text) {
if(StringUtils.isNotBlank(text)) {
return valueOf(text.toUpperCase());
}
return null;
}
public String getDelimiter() {
return delimiter;
}
}

View File

@@ -0,0 +1,15 @@
package io.github.swagger2markup.adoc.converter.internal;
import org.asciidoctor.ast.Table;
public class TableNode extends DelimitedBlockNode {
public TableNode(Table table) {
super(table);
}
@Override
void processAttributes() {
pop("colcount", "rowcount", "tablepcwidth");
super.processAttributes();
}
}

View File

@@ -0,0 +1 @@
io.github.swagger2markup.adoc.AsciiDocConverterRegistry

View File

@@ -0,0 +1,50 @@
package io.github.swagger2markup.adoc;
import org.apache.commons.io.IOUtils;
import org.asciidoctor.Asciidoctor;
import org.asciidoctor.OptionsBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import static org.junit.Assert.*;
@RunWith(Parameterized.class)
public class AsciidocConverterTest {
private Asciidoctor asciidoctor = Asciidoctor.Factory.create();
@Parameterized.Parameters(name = "Run {index}: file={0}")
public static Iterable<?> data() {
return Arrays.asList(
"simple.adoc",
"arrows-and-boxes-example.ad",
"brokeninclude.asciidoc",
"changeattribute.adoc",
"chronicles-example.adoc",
"document-with-arrays.adoc"
);
}
@Parameterized.Parameter
public String asciidocFile;
@Test
public void converts_asciidoc_to_asciidoc() throws IOException {
//Given
String originalAsciiDoc = IOUtils.toString(getClass().getResourceAsStream("/asciidoc/original/" + asciidocFile), StandardCharsets.UTF_8);
String expectedAsciiDoc = IOUtils.toString(getClass().getResourceAsStream("/asciidoc/expected/" + asciidocFile), StandardCharsets.UTF_8);
//When
asciidoctor.javaConverterRegistry().register(AsciidocConverter.class, AsciidocConverter.NAME);
String result = asciidoctor.convert(originalAsciiDoc, OptionsBuilder.options().backend(AsciidocConverter.NAME).headerFooter(false).asMap());
//Then
assertEquals(expectedAsciiDoc, result);
}
}

View File

@@ -0,0 +1,34 @@
= Document Title
:tip-caption: Tip
:appendix-caption: Appendix
:appendix-refsig: Appendix
:toc-title: Table of Contents
:iconsdir: ./images/icons
:warning-caption: Warning
:figure-caption: Figure
:attribute-missing: skip
:section-refsig: Section
:toc-placement: auto
:important-caption: Important
:note-caption: Note
:stylesdir: .
:untitled-label: Untitled
:max-include-depth: 64
:caution-caption: Caution
:user-home: .
:max-attribute-value-size: 4096
:safe-mode-level: 20
:safe-mode-name: secure
:table-caption: Table
:part-refsig: Part
:authorcount: 0
:example-caption: Example
:version-label: Version
:last-update-label: Last updated
:doctype: article
:chapter-refsig: Chapter
:attribute-undefined: drop-line
[arrowsAndBoxes]
(User) > (Admin)

View File

@@ -0,0 +1,33 @@
= Title
:tip-caption: Tip
:appendix-caption: Appendix
:appendix-refsig: Appendix
:toc-title: Table of Contents
:iconsdir: ./images/icons
:warning-caption: Warning
:figure-caption: Figure
:attribute-missing: skip
:section-refsig: Section
:toc-placement: auto
:important-caption: Important
:note-caption: Note
:stylesdir: .
:untitled-label: Untitled
:max-include-depth: 64
:caution-caption: Caution
:user-home: .
:max-attribute-value-size: 4096
:safe-mode-level: 20
:safe-mode-name: secure
:table-caption: Table
:part-refsig: Part
:authorcount: 0
:example-caption: Example
:version-label: Version
:last-update-label: Last updated
:doctype: article
:chapter-refsig: Chapter
:attribute-undefined: drop-line
link:b.adoc[]

View File

@@ -0,0 +1,33 @@
= Document Title
:tip-caption: Tip
:appendix-caption: Appendix
:appendix-refsig: Appendix
:toc-title: Table of Contents
:iconsdir: ./images/icons
:warning-caption: Warning
:figure-caption: Figure
:attribute-missing: skip
:section-refsig: Section
:toc-placement: auto
:important-caption: Important
:note-caption: Note
:stylesdir: .
:untitled-label: Untitled
:max-include-depth: 64
:caution-caption: Caution
:user-home: .
:max-attribute-value-size: 4096
:safe-mode-level: 20
:safe-mode-name: secure
:table-caption: Table
:part-refsig: Part
:authorcount: 0
:example-caption: Example
:version-label: Version
:last-update-label: Last updated
:doctype: article
:chapter-refsig: Chapter
:attribute-undefined: drop-line
sample {content}

View File

@@ -0,0 +1,535 @@
= The Dangerous & _Thrilling_ Documentation Chronicles: Based on True Events
Kismet Caméléon; Lazarus het Draeke
v1.0, 2014-01-01
:tip-caption: Tip
:appendix-caption: Appendix
:toclevels: 3
:appendix-refsig: Appendix
:author_2: Lazarus het Draeke
:uri-stbernardusabt12: http://www.sintbernardus.be/stbernardusabt12.php?l=en
:authorinitials: KC
:author_1: Kismet Caméléon
:toc-title: Table of Contents
:iconsdir: ./images/icons
:author: Kismet Caméléon
:warning-caption: Warning
:figure-caption: Figure
:lastname: Caméléon
:attribute-missing: skip
:lastname_1: Caméléon
:section-refsig: Section
:uri-devoxx: https://devoxx.be
:lastname_2: het Draeke
:toc-placement: auto
:important-caption: Important
:authors: Kismet Caméléon, Lazarus het Draeke
:note-caption: Note
:firstname: Kismet
:stylesdir: .
:uri-devoxx-top-talks: https://www.youtube.com/watch?v=1OpAgZvYXLQ&amp;list=PLRsbF2sD7JVq7fv1GZGORShSUIae1ZAPy&amp;index=1
:untitled-label: Untitled
:description: This story chronicles the inexplicable hazards and vicious beasts a team must conquer and vanquish on their journey to discovering the true power of Open Source.
:max-include-depth: 64
:caution-caption: Caution
:listing-caption: Listing
:user-home: .
:max-attribute-value-size: 4096
:safe-mode-level: 20
:safe-mode-name: secure
:table-caption: Table
:part-refsig: Part
:firstname_1: Kismet
:authorcount: 2
:revdate: 2014-01-01
:example-caption: Example
:firstname_2: Lazarus
:version-label: Version
:revnumber: 1.0
:last-update-label: Last updated
:doctype: book
:chapter-refsig: Chapter
:uri-wolpertinger: http://en.wikipedia.org/wiki/Wolpertinger
:organization: Company Name
:authorinitials_1: KC
:authorinitials_2: Lh
:attribute-undefined: drop-line
[abstract]
{description}
[[_its_a_city_under_siege]]
== Its a City Under Siege
This journey begins one late Monday afternoon at {uri-devoxx}[((Devoxx))].
Our team needs coffee, _desperately_, but none of us dare open the theater doors...
During the {uri-devoxx-top-talks}[opening university session], a script-happy warlock inadvertently released a legion of Wolpertingers!
To leave now would mean *code dismemberment and certain death*.
Behold -> the horror!
.Wolpertinger, stuffed
[.left.thumb]
image::wolpertinger.jpg[Wolpertinger,link=http://en.wikipedia.org/wiki/Wolpertinger,pdfwidth=50%]
(((Wolpertinger)))
(((Ravenous Beast,Wolpertinger)))
You may not be familiar with these {uri-wolpertinger}[ravenous beasts].
Trust us, they'll eat your shorts and suck loops from your code.
In light of this danger, we've searched high and wide for the security crew's defensive operations manual.
We can't find it and the DefOps{empty}footnote:defops[DefOps is a portmanteau of "`defensive`" and "`operations`".] werewolves haven't returned from their rendezvous at Bier Central.
They've either eaten each other or fallen victim to the Wolpertingers roaming the streets of ((Antwerp)).
Quick, hit kbd:[Ctrl,Alt,Backspace] or select menu:File[Quit] and let's bail out of here!
WARNING: Working with DefOps{empty}footnote:defops[] werewolves leads to howling and trying to train aggressive regular expressions with Pavlovian reinforcement.
_Weak light from the hallway trickled across the theater, chased by a distant scream._
[[_rendezvous_point]]
=== Rendezvous Point
Come on, [[bier-central,Bier Central]]_Bier Central_, of course!
Did you have to ask?
If you beat me there, order me a {uri-stbernardusabt12}[St. Bernardus Abt 12].
Here's some &#x20ac;.
[[ravages]]
[#ravages]
== The Ravages of Writing
Crystalline XML tags relentlessly bombarded the theater.
.XML tags
[source,xml]
----
<author id="1">
<personname>
<firstname>Lazarus</firstname>
<surname>het Draeke</surname>
</personname>
</author>
----
Despite the assault, we continued our pursuit to draft a DefOps{empty}footnote:defops[] plan.
.DefOps Plan
====
Click btn:[Download Zip] to download the defensive operation plan bundle.
OMG!
Somebody please save us now!
I want my mum -- and an extra-large double macchiato, please.
====
Unfortunately, Lazarus and I had both come to the conclusion that we weren't going to get out of this without corrupted hardrives if we didn't locate caffeine within the next few hours.
[[_a_recipe_for_potion_that_will_ensure_you_win_the_hearts_of_developers]]
=== A Recipe for Potion That Will Ensure You Win the Hearts of Developers
This potion for a sample document contains the following ingredients, which are listed in a very random, chaotically nested order.
.Ingredients for Potion that Demystifies Documents
* all the headings
** syntax highlighted source code
*** non-syntax highlighted source code or just a listing block
* quote block
** verse block
*** table with some cell formatting
**** sequential paragraphs
***** admonition blocks, but use them sparingly
*** bullet list with nesting
** numbered list with nesting
** definition list
*** sidebar
* example block
** block image (no inline images)
*** inline formatting in a paragraph
**** two fresh Burdockian leaves
***** They must be harvested by the light of the teal moons.
Are you square?
[square]
* one
* two
* three
What is there to do?
* [x] Done
* [ ] Next
* Who's counting?
[[_searching_for_burdockian]]
==== Searching for Burdockian
.Steps for finding and preparing Burdockian leaves
. Locate dusty botany
.. Sneeze
... Sneeze some more
. Find section on Burdockian
.. Review its characteristics
... Take a picture of the diagram of its leaves
.... Don't rip out the picture like a troglodyte
..... Don't do it, I'm watching you
. Put on your hiking boots
. Freeze your butt off on the side of a mountain at midnight
Let's skip a few steps and start counting from 10.
[start=10]
. arabic (10)
.. loweralpha (a)
... lowerroman (i)
... lowerroman (ii)
... lowerroman (iii)
... lowerroman (iv)
.... upperalpha (A)
. arabic (11)
It's time for a top 5 list, made using the `reversed` option on an ordered list!
[%reversed]
. Stone Imperial Russian Stout
. Pliny the Elder
. Chimay Grande Réserve (Blue)
. St. Bernardus Abt 12
. Westvleteren 12 (XII)
How about a list with some terms?
* Fruits
Apple::::
The round fruit of a tree of the rose family, which typically has thin red or green skin and crisp flesh.
Yes, I said _flesh_.
Pear::::
A yellowish- or brownish-green edible fruit that is typically narrow at the stalk and wider toward the base, with sweet, slightly gritty flesh.
More flesh.
Mmmmm.
* Vegetables
Carrot::::
An orange-colored root eaten as a vegetable.
Beware, it's a favorite of the Wolpertinger.
[[_are_you_still_here]]
===== Are You Still Here?
.Move, move, move!
[CAUTION]
====
The Wolpertingers can smell your procrastination.
It's not their fault you can't find your boots.
====
[[_sigh]]
====== Sigh…
TIP: Your boots are in your closet.
[[_dawn_on_the_plateau]]
== Dawn on the Plateau
Lazarus was hanging from the bottom limb of a Burdockian tree, licking the bark.
[quote,Mark Tobey]
On pavements and the bark of trees I have found whole worlds.
"`If there are whole worlds on that bark, he just swallowed them,`" Kizmet replied.
[verse,The documentation attorneys]
____
No bark was harmed in the making of this potion.
We're not so sure about a couple ants though.
Nor those worlds...
Crap, I smell an injunction.
____
We'd retrieved the leaves, but we'd obviously lost our minds in the process.
[verse]
Roses are +++<span style="color: #FF0000">red</span>+++.
Violets are +++<span style="color: #0000FF">blue</span>+++__-ish__.
[[_words_seasoned_with_power]]
== Words Seasoned with Power
To _tame_ the [.wild]#wild# wolpertingers, we needed to build a *charm*.
But **ul**timate victory could only be won if we divined the *_true name_* of the __war__lock.
"`What kind of charm?`" Lazarus asked. "`An odoriferous one or a mineral one?`"
Kizmet shrugged. "`The note from Olaf's desk says '`wormwood and licorice,`' but these could be normal groceries for werewolves.`"
"`Well the H~2~O written on the security whiteboard could be part of a shopping list, but I don't think the local bodega also sells e = mc^2^,`" Lazarus replied.
"`Wait!`" Indigo plucked a small vial from her desk's top drawer and held it toward us.
The vial's label read '```e = mc^2^ *_the scent of science_* _smells like a genius_```'.
[[_can_i_get_some_code]]
=== Can I Get Some `Code`?
[%hardbreaks]
Sure.
Have a listing block.
[listing]
----
This is an example of a listing block.
The content inside is rendered as <pre> text.
----
But I'm not giving you any highlighting shazam just yet.
.What is a listing block?
Like literal blocks, the content in listing blocks is displayed exactly as you entered it.
Listing block content is rendered as `<pre>` text.
The `listing` style is applied to an element, such as a paragraph, by setting the `listing` attribute on that element.
Let's get our #((highlighting))# on!
<<<
Install Prawn:
[literal]
$ gem install prawn
Then create your first PDF document in Ruby!
.Generates a basic PDF document using Prawn
[source,ruby]
----
require 'prawn' # <1>
Prawn::Document.generate 'output.pdf' do # <3>
text 'Hello, World!' # <2>
end
----
<1> Imports Prawn library
<3> Adds text “Hello, World!” to first page
<2> Writes PDF to [file]_output.pdf_ after executing all statements
How about some source code that styles code? So meta!
[source,css]
----
code {
padding: 2px 4px;
font-size: 90%;
font-weight: normal;
color: #c7254e;
white-space: nowrap !important;
background-color: #f9f2f4;
border-radius: 4px;
}
----
Where could we go without some Java(TM)?
Naturally, some autosizing is necessary.
[source%autofit,java]
----
package org.javaee7.cdi.events;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.event.Observes;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.ws.rs.*;
/**
* This session-scoped bean receives greeting strings from the event bus
* and provides access to the collection of these greetings via a REST API.
*
* @author The Duke
* @since 1.0
*/
@SessionScoped
public class GreetingReceiver implements EventReceiver, Serializable {
private List<String> greetings;
@PostConstruct
void init() {
this.greetings = new ArrayList<String>();
}
void receive(@Observes String greet) {
this.greetings.add(greet);
}
@GET
@Produces("application/json")
public List<String> listAll(@QueryParam("start") Integer start, @QueryParam("max") Integer max) {
int numGreetings = this.greetings.size();
if (numGreetings == 0 || max == 0) {
return Collections.<String>emptyList();
}
if (start == null) {
start = 0;
}
if (max == null) {
max = numGreetings;
}
return this.greetings.subList(start, Math.min(max + start, numGreetings));
}
}
----
We already showed you an XML example in <<ravages>>, a language we often rant about over beers at <<bier-central>>.
I'll trade you a little table for some of that bark.
[table%header,grid=rows,cols=4,frame=topbot]
|===
<.<|Column 1
<.<|Column 2
<.<|Column 3
<.<|Column 4
^.<m|Prefix `{vbar}` with `{caret}` to center content horizontally within the cell.
<.>|Prefix `{vbar}` with a `.` and `>` to align content to the bottom of the cell.
^.^|Prefix `{vbar}` with a `^`, `.`, and `^` to place content in the middle of the cell.
>.<|Prefix `{vbar}` with `>` to align content to the right horizontally within the cell.
4+^.<e|This content spans all four columns (`4{plus}`) and is centered horizontally (`{caret}`) within the cell.
|===
Wait.
What?
Where is this story going?
`<span>`:::
an html tag that makes me crazy
align:::
something I never get going in the right direction.
Also has to do with my poor verbal communication skills
float:::
style:::
don't make me laugh
Does anyone have the time?
Tg lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborumj.
[[_keeping_it_together]]
== Keeping It Together
On this page we have nested "`keep together`" logic.
The combined block will be shifted to the next page if there isn't room available on this one.
[verse]
First,
we
need
to
waste
several
lines
using
a
verse
to
push
the
next
block
to
its
breaking
point.
.What happens if there is both a field and a method with the same name?
[NOTE]
====
Back to the previous example, suppose that we have both a field and a method with the same name, as in:
.Java class with a field and method that share the same name
[source,java]
----
public class Foo {
public String bar;
public String bar() {
return bar;
}
}
----
*Golo resolves methods first, fields last.*
Hence, the following Golo code will resolve the `bar()` method, not the `bar` field:
.Golo picks the method over the field with the same name
[source,golo]
----
let foo = Foo()
foo: bar("baz") # <1>
println(foo: bar()) # <2>
----
<1> Writes the field
<2> Calls the `bar()` method
====
<<<
Here's a preview of how each heading level is rendered.
[discrete]
= Heading 1 (Level 0)
filler content
[discrete]
== Heading 2 (Level 1)
filler content
[discrete]
=== Heading 3 (Level 2)
filler content
[discrete]
==== Heading 4 (Level 3)
filler content
[discrete]
===== Heading 5 (Level 4)
filler content
[discrete]
====== Heading 6 (Level 5)
filler content
'''
--
Here's some content inside an open block.
--
[[_credits]]
[appendix]
== Credits
.Brought to you with icon:heart[set=fas,role=love] by OpenDevise
[table%footer%header,grid=rows,width=75%,cols="2,2s,^4",frame=topbot]
|===
<.<|Name
<.<|Title
.<|Alias
<.<|Sarah White
<.<|President
.<|http://twitter.com/carbonfray[@carbonfray]
<.<|Dan Allen
<.<|Vice President
.<|http://twitter.com/mojavelinux[@mojavelinux]
3+^.<e|Powered by Open Source
|===
[[_index]]
[index]
== Index

View File

@@ -0,0 +1,48 @@
= Asciidoctor Changelog
:tip-caption: Tip
:appendix-caption: Appendix
:appendix-refsig: Appendix
:toc-title: Table of Contents
:iconsdir: ./images/icons
:warning-caption: Warning
:figure-caption: Figure
:attribute-missing: skip
:section-refsig: Section
:toc-placement: auto
:important-caption: Important
:note-caption: Note
:stylesdir: .
:untitled-label: Untitled
:max-include-depth: 64
:caution-caption: Caution
:user-home: .
:max-attribute-value-size: 4096
:safe-mode-level: 20
:safe-mode-name: secure
:table-caption: Table
:part-refsig: Part
:authorcount: 0
:example-caption: Example
:version-label: Version
:last-update-label: Last updated
:doctype: article
:chapter-refsig: Chapter
:attribute-undefined: drop-line
http://asciidoctor.org[Asciidoctor] is an open source text processor and publishing toolchain for converting http://asciidoctor.org[AsciiDoc] markup into HTML, DocBook and custom formats.
This document provides a high-level view of the changes introduced in Asciidoctor by release.
For a detailed view of what has changed, refer to the https://github.com/asciidoctor/asciidoctor/commits/master[commit history] on GitHub.
[[_0_1_4_2013_09_05_mojavelinux]]
== 0.1.4 (2013-09-05) - @mojavelinux
Performance::
* 15% increase in speed compared to 0.1.3
Enhancements::
* updated xref inline macro to support inter-document references (#417)
Bug Fixes::
* lowercase attribute names passed to API (#508)

View File

@@ -0,0 +1,77 @@
= Simple Inventory API
You <you@your-company.com>
v1.0.0
:tip-caption: Tip
:appendix-caption: Appendix
:appendix-refsig: Appendix
:authorinitials: Y
:toc-title: Table of Contents
:iconsdir: ./images/icons
:author: You
:warning-caption: Warning
:figure-caption: Figure
:attribute-missing: skip
:section-refsig: Section
:toc-placement: auto
:important-caption: Important
:authors: You
:note-caption: Note
:firstname: You
:stylesdir: .
:untitled-label: Untitled
:max-include-depth: 64
:caution-caption: Caution
:user-home: .
:max-attribute-value-size: 4096
:safe-mode-level: 20
:safe-mode-name: secure
:table-caption: Table
:part-refsig: Part
:authorcount: 1
:example-caption: Example
:email: you@your-company.com
:version-label: Version
:revnumber: 1.0.0
:last-update-label: Last updated
:doctype: article
:chapter-refsig: Chapter
:attribute-undefined: drop-line
[[_overview]]
== Overview
This is a simple API
[[_license]]
=== License
[%hardbreaks]
http://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0]
[[_servers]]
== Servers
* https://{username}.gigantic-server.com:{port}/{basePath}
+
The production API server
+
.Variables
username::
*this* __value__ is assigned by the service provider, in this example `gigantic-server.com`
Possible Values::
Any
Default::
demo
port::
Possible Values::
- 8443
- 443
Default::
8443
basePath::
Possible Values::
Any
Default::
v2

View File

@@ -0,0 +1,4 @@
= Document Title
[arrowsAndBoxes]
(User) > (Admin)

View File

@@ -0,0 +1,3 @@
= Title
include::b.adoc[]

View File

@@ -0,0 +1,4 @@
= Document Title
sample {content}

View File

@@ -0,0 +1,529 @@
= The Dangerous & _Thrilling_ Documentation Chronicles: Based on True Events
Kismet Caméléon; Lazarus het_Draeke
v1.0, 2014-01-01
:description: This story chronicles the inexplicable hazards and vicious beasts a \
team must conquer and vanquish on their journey to discovering the true power of \
Open Source.
:organization: Company Name
:doctype: book
// Settings:
:experimental:
:reproducible:
:icons: font
:listing-caption: Listing
:sectnums:
:toc:
:toclevels: 3
ifeval::["{asciidoctor-version}" < "1.5.7"]
:legacy-footnoteref:
endif::[]
ifdef::backend-pdf[]
:pdf-theme: chronicles
:pdf-themesdir: {docdir}
:title-logo-image: image:sample-banner.svg[pdfwidth=4.25in,align=center]
:source-highlighter: rouge
//:rouge-style: github
endif::[]
// URIs:
:uri-devoxx: https://devoxx.be
:uri-devoxx-top-talks: https://www.youtube.com/watch?v=1OpAgZvYXLQ&list=PLRsbF2sD7JVq7fv1GZGORShSUIae1ZAPy&index=1
:uri-stbernardusabt12: http://www.sintbernardus.be/stbernardusabt12.php?l=en
:uri-wolpertinger: http://en.wikipedia.org/wiki/Wolpertinger
[abstract]
{description}
== It's a City Under Siege
This journey begins one late Monday afternoon at {uri-devoxx}[((Devoxx))].
Our team needs coffee, _desperately_, but none of us dare open the theater doors...
During the {uri-devoxx-top-talks}[opening university session], a script-happy warlock inadvertently released a legion of Wolpertingers!
To leave now would mean *code dismemberment and certain death*.
Behold -> the horror!
.Wolpertinger, stuffed
[.left.thumb]
image::wolpertinger.jpg[Wolpertinger,pdfwidth=50%,link={uri-wolpertinger}]
(((Wolpertinger)))
(((Ravenous Beast,Wolpertinger)))
You may not be familiar with these {uri-wolpertinger}[ravenous beasts].
Trust us, they'll eat your shorts and suck loops from your code.
In light of this danger, we've searched high and wide for the security crew's defensive operations manual.
ifndef::legacy-footnoteref[]
We can't find it and the DefOps{empty}footnote:defops[DefOps is a portmanteau of "`defensive`" and "`operations`".] werewolves haven't returned from their rendezvous at Bier Central.
endif::[]
ifdef::legacy-footnoteref[]
We can't find it and the DefOps{empty}footnoteref:[defops,DefOps is a portmanteau of "`defensive`" and "`operations`".] werewolves haven't returned from their rendezvous at Bier Central.
endif::[]
They've either eaten each other or fallen victim to the Wolpertingers roaming the streets of ((Antwerp)).
Quick, hit kbd:[Ctrl,Alt,Backspace] or select menu:File[Quit] and let's bail out of here!
ifndef::legacy-footnoteref[]
WARNING: Working with DefOps{empty}footnote:defops[] werewolves leads to howling and trying to train aggressive regular expressions with Pavlovian reinforcement.
endif::[]
ifdef::legacy-footnoteref[]
WARNING: Working with DefOps{empty}footnoteref:[defops] werewolves leads to howling and trying to train aggressive regular expressions with Pavlovian reinforcement.
endif::[]
_Weak light from the hallway trickled across the theater, chased by a distant scream._
=== Rendezvous Point
Come on, [[bier-central,Bier Central]]_Bier Central_, of course!
Did you have to ask?
If you beat me there, order me a {uri-stbernardusabt12}[St. Bernardus Abt 12].
Here's some &#x20ac;.
[#ravages]
== The Ravages of Writing
Crystalline XML tags relentlessly bombarded the theater.
.XML tags
[source,xml]
----
<author id="1">
<personname>
<firstname>Lazarus</firstname>
<surname>het Draeke</surname>
</personname>
</author>
----
ifndef::legacy-footnoteref[]
Despite the assault, we continued our pursuit to draft a DefOps{empty}footnote:defops[] plan.
endif::[]
ifdef::legacy-footnoteref[]
Despite the assault, we continued our pursuit to draft a DefOps{empty}footnoteref:[defops] plan.
endif::[]
.DefOps Plan
====
Click btn:[Download Zip] to download the defensive operation plan bundle.
OMG!
Somebody please save us now!
I want my mum -- and an extra-large double macchiato, please.
====
Unfortunately, Lazarus and I had both come to the conclusion that we weren't going to get out of this without corrupted hardrives if we didn't locate caffeine within the next few hours.
=== A Recipe for Potion That Will Ensure You Win the Hearts of Developers
This potion for a sample document contains the following ingredients, which are listed in a very random, chaotically nested order.
.Ingredients for Potion that Demystifies Documents
* all the headings
** syntax highlighted source code
*** non-syntax highlighted source code or just a listing block
* quote block
** verse block
*** table with some cell formatting
**** sequential paragraphs
***** admonition blocks, but use them sparingly
*** bullet list with nesting
** numbered list with nesting
** definition list
*** sidebar
* example block
** block image (no inline images)
*** inline formatting in a paragraph
**** two fresh Burdockian leaves
***** They must be harvested by the light of the teal moons.
Are you square?
[square]
* one
* two
* three
What is there to do?
* [x] Done
* [ ] Next
* Who's counting?
==== Searching for Burdockian
.Steps for finding and preparing Burdockian leaves
. Locate dusty botany
.. Sneeze
... Sneeze some more
. Find section on Burdockian
.. Review its characteristics
... Take a picture of the diagram of its leaves
.... Don't rip out the picture like a troglodyte
..... Don't do it, I'm watching you
. Put on your hiking boots
. Freeze your butt off on the side of a mountain at midnight
Let's skip a few steps and start counting from 10.
[start=10]
. arabic (10)
.. loweralpha (a)
... lowerroman (i)
... lowerroman (ii)
... lowerroman (iii)
... lowerroman (iv)
.... upperalpha (A)
. arabic (11)
It's time for a top 5 list, made using the `reversed` option on an ordered list!
[%reversed]
. Stone Imperial Russian Stout
. Pliny the Elder
. Chimay Grande Réserve (Blue)
. St. Bernardus Abt 12
. Westvleteren 12 (XII)
How about a list with some terms?
* Fruits
Apple::
The round fruit of a tree of the rose family, which typically has thin red or green skin and crisp flesh.
Yes, I said _flesh_.
Pear::
A yellowish- or brownish-green edible fruit that is typically narrow at the stalk and wider toward the base, with sweet, slightly gritty flesh.
More flesh.
Mmmmm.
* Vegetables
Carrot::
An orange-colored root eaten as a vegetable.
Beware, it's a favorite of the Wolpertinger.
===== Are You Still Here?
.Move, move, move!
[CAUTION]
====
The Wolpertingers can smell your procrastination.
It's not their fault you can't find your boots.
====
====== Sigh...
TIP: Your boots are in your closet.
== Dawn on the Plateau
Lazarus was hanging from the bottom limb of a Burdockian tree, licking the bark.
[quote,Mark Tobey]
On pavements and the bark of trees I have found whole worlds.
"`If there are whole worlds on that bark, he just swallowed them,`" Kizmet replied.
[verse,The documentation attorneys]
____
No bark was harmed in the making of this potion.
We're not so sure about a couple ants though.
Nor those worlds...
Crap, I smell an injunction.
____
We'd retrieved the leaves, but we'd obviously lost our minds in the process.
[verse]
Roses are +++<span style="color: #FF0000">red</span>+++.
Violets are +++<span style="color: #0000FF">blue</span>+++__-ish__.
== Words Seasoned with Power
To _tame_ the [.wild]#wild# wolpertingers, we needed to build a *charm*.
But **ul**timate victory could only be won if we divined the *_true name_* of the __war__lock.
"`What kind of charm?`" Lazarus asked. "`An odoriferous one or a mineral one?`"
Kizmet shrugged. "`The note from Olaf's desk says '`wormwood and licorice,`' but these could be normal groceries for werewolves.`"
"`Well the H~2~O written on the security whiteboard could be part of a shopping list, but I don't think the local bodega also sells e = mc^2^,`" Lazarus replied.
"`Wait!`" Indigo plucked a small vial from her desk's top drawer and held it toward us.
The vial's label read '```e = mc^2^ *_the scent of science_* _smells like a genius_```'.
=== Can I Get Some `Code`?
[%hardbreaks]
Sure.
Have a listing block.
----
This is an example of a listing block.
The content inside is rendered as <pre> text.
----
But I'm not giving you any highlighting shazam just yet.
.What is a listing block?
****
Like literal blocks, the content in listing blocks is displayed exactly as you entered it.
Listing block content is rendered as `<pre>` text.
The `listing` style is applied to an element, such as a paragraph, by setting the `listing` attribute on that element.
****
Let's get our #((highlighting))# on!
<<<
Install Prawn:
$ gem install prawn
Then create your first PDF document in Ruby!
.Generates a basic PDF document using Prawn
[source,ruby]
----
require 'prawn' # <1>
Prawn::Document.generate 'output.pdf' do # <3>
text 'Hello, World!' # <2>
end
----
<1> Imports Prawn library
<2> Adds text “Hello, World!” to first page
<3> Writes PDF to [file]_output.pdf_ after executing all statements
How about some source code that styles code? So meta!
[source,css]
----
code {
padding: 2px 4px;
font-size: 90%;
font-weight: normal;
color: #c7254e;
white-space: nowrap !important;
background-color: #f9f2f4;
border-radius: 4px;
}
----
Where could we go without some Java(TM)?
Naturally, some autosizing is necessary.
[source%autofit,java]
----
package org.javaee7.cdi.events;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.event.Observes;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.ws.rs.*;
/**
* This session-scoped bean receives greeting strings from the event bus
* and provides access to the collection of these greetings via a REST API.
*
* @author The Duke
* @since 1.0
*/
@SessionScoped
public class GreetingReceiver implements EventReceiver, Serializable {
private List<String> greetings;
@PostConstruct
void init() {
this.greetings = new ArrayList<String>();
}
void receive(@Observes String greet) {
this.greetings.add(greet);
}
@GET
@Produces("application/json")
public List<String> listAll(@QueryParam("start") Integer start, @QueryParam("max") Integer max) {
int numGreetings = this.greetings.size();
if (numGreetings == 0 || max == 0) {
return Collections.<String>emptyList();
}
if (start == null) {
start = 0;
}
if (max == null) {
max = numGreetings;
}
return this.greetings.subList(start, Math.min(max + start, numGreetings));
}
}
----
We already showed you an XML example in <<ravages>>, a language we often rant about over beers at <<bier-central>>.
I'll trade you a little table for some of that bark.
[cols=4,frame=topbot,grid=rows]
|===
|Column 1 |Column 2 |Column 3 |Column 4
^m|Prefix `{vbar}` with `{caret}` to center content horizontally within the cell.
.>|Prefix `{vbar}` with a `.` and `>` to align content to the bottom of the cell.
^.^|Prefix `{vbar}` with a `^`, `.`, and `^` to place content in the middle of the cell.
>|Prefix `{vbar}` with `>` to align content to the right horizontally within the cell.
4+^e|This content spans all four columns (`4{plus}`) and is centered horizontally (`{caret}`) within the cell.
|===
Wait.
What?
Where is this story going?
`<span>`:: an html tag that makes me crazy
align:: something I never get going in the right direction.
Also has to do with my poor verbal communication skills
float::
style::
don't make me laugh
Does anyone have the time?
Tg lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborumj.
== Keeping It Together
On this page we have nested "`keep together`" logic.
The combined block will be shifted to the next page if there isn't room available on this one.
[verse]
First,
we
need
to
waste
several
lines
using
a
verse
to
push
the
next
block
to
its
breaking
point.
[NOTE]
.What happens if there is both a field and a method with the same name?
====
Back to the previous example, suppose that we have both a field and a method with the same name, as in:
.Java class with a field and method that share the same name
[source,java]
----
public class Foo {
public String bar;
public String bar() {
return bar;
}
}
----
*Golo resolves methods first, fields last.*
Hence, the following Golo code will resolve the `bar()` method, not the `bar` field:
.Golo picks the method over the field with the same name
[source,golo]
----
let foo = Foo()
foo: bar("baz") # <1>
println(foo: bar()) # <2>
----
<1> Writes the field
<2> Calls the `bar()` method
====
<<<
Here's a preview of how each heading level is rendered.
[discrete]
= Heading 1 (Level 0)
filler content
[discrete]
== Heading 2 (Level 1)
filler content
[discrete]
=== Heading 3 (Level 2)
filler content
[discrete]
==== Heading 4 (Level 3)
filler content
[discrete]
===== Heading 5 (Level 4)
filler content
[discrete]
====== Heading 6 (Level 5)
filler content
---
--
Here's some content inside an open block.
--
[appendix]
== Credits
.Brought to you with icon:heart[set=fas,role=love] by OpenDevise
[%header%footer,cols="2,2s,^4",grid=rows,frame=topbot,width=75%,caption=]
|===
|Name |Title |Alias
|Sarah White
|President
|http://twitter.com/carbonfray[@carbonfray]
|Dan Allen
|Vice President
|http://twitter.com/mojavelinux[@mojavelinux]
3+^.e|Powered by Open Source
|===
[index]
== Index

View File

@@ -0,0 +1,21 @@
= Asciidoctor Changelog
http://asciidoctor.org[Asciidoctor] is an open source text processor and publishing toolchain for converting http://asciidoctor.org[AsciiDoc] markup into HTML, DocBook and custom formats.
This document provides a high-level view of the changes introduced in Asciidoctor by release.
For a detailed view of what has changed, refer to the https://github.com/asciidoctor/asciidoctor/commits/master[commit history] on GitHub.
== 0.1.4 (2013-09-05) - @mojavelinux
Performance::
* 15% increase in speed compared to 0.1.3
Enhancements::
* updated xref inline macro to support inter-document references (#417)
Bug Fixes::
* lowercase attribute names passed to API (#508)

View File

@@ -0,0 +1,28 @@
= Simple Inventory API
You <you@your-company.com>
v1.0.0
== Overview
This is a simple API
=== License
[%hardbreaks]
http://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0]
== Servers
* https://{username}.gigantic-server.com:{port}/{basePath}
+
The production API server
+
.Variables
username:: *this* __value__ is assigned by the service provider, in this example `gigantic-server.com`
Possible Values::: Any
Default::: demo
port::
Possible Values:::
- 8443
- 443
Default::: 8443
basePath::
Possible Values::: Any
Default::: v2

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="io.github.swagger2markup" level="DEBUG"/>
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
</configuration>

View File

@@ -25,6 +25,7 @@ import io.github.swagger2markup.markup.builder.internal.Markup;
* @author Robert Winkler
*/
public enum AsciiDoc implements Markup {
ATTRIBUTE(":"),
TABLE("|==="),
TABLE_COLUMN_DELIMITER("|"),
TITLE("="),

Some files were not shown because too many files have changed in this diff Show More