Add support for Markdown in -l html (#5144)

* Sync with upstream/master

* Support Markdown in -l html

Add https://github.com/atlassian/commonmark-java to modules/swagger-codegen to convert Markdown to HTML,
update StaticHtmlGenerator to use this (see the toHeml() method and its uses)

Add a new test case bin/html-markdown.sh and
modules/swagger-codegen/src/test/resources/2_0/markdown.yaml

* Support Markdown in -l html

Add https://github.com/atlassian/commonmark-java to modules/swagger-codegen to convert Markdown to HTML,
update StaticHtmlGenerator to use this (see the toHeml() method and its uses)

Add a new test case bin/html-markdown.sh and
modules/swagger-codegen/src/test/resources/2_0/markdown.yaml
This commit is contained in:
David Biesack
2017-03-23 03:15:01 -04:00
committed by wing328
parent 55b7db3456
commit 5f27fcab18
9 changed files with 601 additions and 70 deletions

View File

@@ -3,22 +3,31 @@ package io.swagger.codegen.languages;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenParameter;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenResponse;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.Operation;
import io.swagger.models.Info;
import io.swagger.models.Model;
import io.swagger.models.Swagger;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import java.util.ArrayList;
import io.swagger.codegen.utils.Markdown;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import com.samskivert.mustache.Escapers;
import com.samskivert.mustache.Mustache.Compiler;
import io.swagger.codegen.utils.Markdown;
public class StaticHtmlGenerator extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger";
@@ -61,13 +70,19 @@ public class StaticHtmlGenerator extends DefaultCodegen implements CodegenConfig
importMapping = new HashMap<String, String>();
}
@Override
/**
* Convert Markdown (CommonMark) to HTML. This class also disables normal HTML
* escaping in the Mustache engine (see {@link #processCompiler(Compiler)} above.)
*/
@Override
public String escapeText(String input) {
// newline escaping disabled for HTML documentation for markdown to work correctly
return input;
return toHtml(input);
}
@Override
@Override
public CodegenType getTag() {
return CodegenType.DOCUMENTATION;
}
@@ -124,4 +139,61 @@ public class StaticHtmlGenerator extends DefaultCodegen implements CodegenConfig
// just return the original string
return input;
}
/**
* Markdown conversion emits HTML and by default, the Mustache
* {@link Compiler} will escape HTML. For example a summary
* <code>"Text with **bold**"</code> is converted from Markdown to HTML as
* <code>"Text with &lt;strong&gt;bold&lt;/strong&gt; text"</code> and then
* the default compiler with HTML escaping on turns this into
* <code>"Text with &amp;lt;strong&amp;gt;bold&amp;lt;/strong&amp;gt; text"</code>.
* Here, we disable escaping by setting the compiler to {@link Escapers#NONE
* Escapers.NONE}
*/
@Override
public Compiler processCompiler(Compiler compiler) {
return compiler.withEscaper(Escapers.NONE);
}
private Markdown markdownConverter = new Markdown();
private static final boolean CONVERT_TO_MARKDOWN_VIA_ESCAPE_TEXT = false;
/**
* Convert Markdown text to HTML
* @param input text in Markdown; may be null.
* @return the text, converted to Markdown. For null input, "" is returned.
*/
public String toHtml(String input) {
if (input == null)
return "";
return markdownConverter.toHtml(input);
}
public void preprocessSwagger(Swagger swagger) {
Info info = swagger.getInfo();
info.setDescription(toHtml(info.getDescription()));
info.setTitle(toHtml(info.getTitle()));
Map<String, Model> models = swagger.getDefinitions();
for (Model model : models.values()) {
model.setDescription(toHtml(model.getDescription()));
model.setTitle(toHtml(model.getTitle()));
}
}
// override to post-process any parameters
public void postProcessParameter(CodegenParameter parameter) {
parameter.description = toHtml(parameter.description);
parameter.unescapedDescription = toHtml(
parameter.unescapedDescription);
}
// override to post-process any model properties
public void postProcessModelProperty(CodegenModel model,
CodegenProperty property) {
property.description = toHtml(property.description);
property.unescapedDescription = toHtml(
property.unescapedDescription);
}
}

View File

@@ -0,0 +1,47 @@
package io.swagger.codegen.utils;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
/**
* Utility class to convert Markdown (CommonMark) to HTML.
* <a href='https://github.com/atlassian/commonmark-java/issues/83'>This class is threadsafe.</a>
*/
public class Markdown {
// see https://github.com/atlassian/commonmark-java
private final Parser parser = Parser.builder().build();
private final HtmlRenderer renderer = HtmlRenderer.builder().build();
/**
* Convert input markdown text to HTML.
* Simple text is not wrapped in <p>...</p>.
* @param markdown text with Markdown styles. If <code>null<code>, </code>""</code> is returned.
* @return HTML rendering from the Markdown
*/
public String toHtml(String markdown) {
if (markdown == null)
return "";
Node document = parser.parse(markdown);
String html = renderer.render(document);
html = unwrapped(html);
return html;
}
// The CommonMark library wraps the HTML with
// <p> ... html ... </p>\n
// This method removes that markup wrapper if there are no other <p> elements,
// do that Markdown can be used in non-block contexts such as operation summary etc.
private static final String P_END = "</p>\n";
private static final String P_START = "<p>";
private String unwrapped(String html) {
if (html.startsWith(P_START) && html.endsWith(P_END)
&& html.lastIndexOf(P_START) == 0)
return html.substring(P_START.length(),
html.length() - P_END.length());
else
return html;
}
}