Skip to content

Commit ba98b64

Browse files
authored
Merge pull request #41 from jmini/patch-18
Migrate `html2` Codegen
2 parents c22a2c2 + 92fba22 commit ba98b64

25 files changed

+3366
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
package io.swagger.codegen.languages.html;
2+
3+
import io.swagger.codegen.CliOption;
4+
import io.swagger.codegen.CodegenConfig;
5+
import io.swagger.codegen.CodegenConstants;
6+
import io.swagger.codegen.CodegenOperation;
7+
import io.swagger.codegen.CodegenParameter;
8+
import io.swagger.codegen.CodegenResponse;
9+
import io.swagger.codegen.CodegenType;
10+
import io.swagger.codegen.SupportingFile;
11+
import io.swagger.codegen.languages.DefaultCodegenConfig;
12+
import io.swagger.codegen.utils.Markdown;
13+
import io.swagger.v3.oas.models.OpenAPI;
14+
import io.swagger.v3.oas.models.Operation;
15+
import io.swagger.v3.oas.models.info.Info;
16+
import io.swagger.v3.oas.models.media.ArraySchema;
17+
import io.swagger.v3.oas.models.media.MapSchema;
18+
import io.swagger.v3.oas.models.media.Schema;
19+
import org.apache.commons.lang3.StringUtils;
20+
import java.util.HashMap;
21+
import java.util.HashSet;
22+
import java.util.List;
23+
import java.util.Map;
24+
import static io.swagger.codegen.languages.helpers.ExtensionHelper.getBooleanValue;
25+
26+
public class StaticHtml2Codegen extends DefaultCodegenConfig implements CodegenConfig {
27+
protected String invokerPackage = "io.swagger.client"; // default for Java and Android
28+
protected String phpInvokerPackage = "Swagger\\Client"; // default for PHP
29+
protected String packageName = "IO.Swagger"; // default for C#
30+
protected String groupId = "io.swagger";
31+
protected String artifactId = "swagger-client";
32+
protected String artifactVersion = "1.0.0";
33+
protected String jsProjectName;
34+
protected String jsModuleName;
35+
protected String perlModuleName = "WWW::SwaggerClient";
36+
protected String pythonPackageName = "swagger_client";
37+
38+
public StaticHtml2Codegen() {
39+
super();
40+
outputFolder = "docs";
41+
42+
defaultIncludes = new HashSet<String>();
43+
44+
cliOptions.add(new CliOption("appName", "short name of the application"));
45+
cliOptions.add(new CliOption("appDescription", "description of the application"));
46+
cliOptions.add(new CliOption("infoUrl", "a URL where users can get more information about the application"));
47+
cliOptions.add(new CliOption("infoEmail", "an email address to contact for inquiries about the application"));
48+
cliOptions.add(new CliOption("licenseInfo", "a short description of the license"));
49+
cliOptions.add(new CliOption("licenseUrl", "a URL pointing to the full license"));
50+
cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC));
51+
cliOptions.add(new CliOption(CodegenConstants.PHP_INVOKER_PACKAGE, CodegenConstants.PHP_INVOKER_PACKAGE_DESC));
52+
cliOptions.add(new CliOption(CodegenConstants.PERL_MODULE_NAME, CodegenConstants.PERL_MODULE_NAME_DESC));
53+
cliOptions.add(new CliOption(CodegenConstants.PYTHON_PACKAGE_NAME, CodegenConstants.PYTHON_PACKAGE_NAME_DESC));
54+
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "C# package name"));
55+
cliOptions.add(new CliOption(CodegenConstants.GROUP_ID, CodegenConstants.GROUP_ID_DESC));
56+
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_ID, CodegenConstants.ARTIFACT_ID_DESC));
57+
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, CodegenConstants.ARTIFACT_VERSION_DESC));
58+
59+
additionalProperties.put("appName", "Swagger Sample");
60+
additionalProperties.put("appDescription", "A sample swagger server");
61+
additionalProperties.put("infoUrl", "https://helloreverb.com");
62+
additionalProperties.put("infoEmail", "[email protected]");
63+
additionalProperties.put("licenseInfo", "All rights reserved");
64+
additionalProperties.put("licenseUrl", "http://apache.org/licenses/LICENSE-2.0.html");
65+
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
66+
additionalProperties.put(CodegenConstants.PHP_INVOKER_PACKAGE, phpInvokerPackage);
67+
additionalProperties.put(CodegenConstants.PERL_MODULE_NAME, perlModuleName);
68+
additionalProperties.put(CodegenConstants.PYTHON_PACKAGE_NAME, pythonPackageName);
69+
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
70+
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
71+
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
72+
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
73+
74+
supportingFiles.add(new SupportingFile("index.mustache", "", "index.html"));
75+
reservedWords = new HashSet<String>();
76+
77+
languageSpecificPrimitives = new HashSet<String>();
78+
importMapping = new HashMap<String, String>();
79+
}
80+
81+
@Override
82+
public CodegenType getTag() {
83+
return CodegenType.DOCUMENTATION;
84+
}
85+
86+
@Override
87+
public String getArgumentsLocation() {
88+
return "";
89+
}
90+
91+
@Override
92+
public String getName() {
93+
return "html2";
94+
}
95+
96+
@Override
97+
public String escapeText(String input) {
98+
// newline escaping disabled for HTML documentation for markdown to work
99+
// correctly
100+
return input;
101+
}
102+
103+
@Override
104+
public String getHelp() {
105+
return "Generates a static HTML file.";
106+
}
107+
108+
@Override
109+
public String getTypeDeclaration(Schema propertySchema) {
110+
if (propertySchema instanceof ArraySchema) {
111+
Schema inner = ((ArraySchema) propertySchema).getItems();
112+
return String.format("%s[%s]", getSchemaType(propertySchema), getTypeDeclaration(inner));
113+
}
114+
else if (propertySchema instanceof MapSchema && propertySchema.getAdditionalProperties() instanceof Schema) {
115+
Schema inner = (Schema) propertySchema.getAdditionalProperties();
116+
return String.format("%s[String, %s]", getSchemaType(propertySchema), getTypeDeclaration(inner));
117+
}
118+
return super.getTypeDeclaration(propertySchema);
119+
}
120+
121+
@Override
122+
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
123+
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
124+
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
125+
for (CodegenOperation op : operationList) {
126+
op.httpMethod = op.httpMethod.toLowerCase();
127+
for (CodegenResponse response : op.responses) {
128+
if ("0".equals(response.code)) {
129+
response.code = "default";
130+
}
131+
}
132+
op.formParams = postProcessParameterEnum(op.formParams);
133+
}
134+
return objs;
135+
}
136+
137+
@Override
138+
public void processOpts() {
139+
super.processOpts();
140+
141+
String templateVersion = getTemplateVersion();
142+
if (StringUtils.isNotBlank(templateVersion)) {
143+
embeddedTemplateDir = templateDir = String.format("%s/htmlDocs2", templateVersion);
144+
}
145+
else {
146+
embeddedTemplateDir = templateDir = String.format("%s/htmlDocs2", DEFAULT_TEMPLATE_VERSION);
147+
}
148+
}
149+
150+
@Override
151+
public void preprocessOpenAPI(OpenAPI openAPI) {
152+
super.preprocessOpenAPI(openAPI);
153+
154+
if (openAPI.getInfo() != null) {
155+
Info info = openAPI.getInfo();
156+
if (StringUtils.isBlank(jsProjectName) && info.getTitle() != null) {
157+
// when jsProjectName is not specified, generate it from info.title
158+
jsProjectName = sanitizeName(dashize(info.getTitle()));
159+
}
160+
}
161+
162+
// default values
163+
if (StringUtils.isBlank(jsProjectName)) {
164+
jsProjectName = "swagger-js-client";
165+
}
166+
if (StringUtils.isBlank(jsModuleName)) {
167+
jsModuleName = camelize(underscore(jsProjectName));
168+
}
169+
170+
additionalProperties.put("jsProjectName", jsProjectName);
171+
additionalProperties.put("jsModuleName", jsModuleName);
172+
173+
preparHtmlForGlobalDescription(openAPI);
174+
}
175+
176+
@Override
177+
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Schema> definitions, OpenAPI ope) {
178+
CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, ope);
179+
if (op.returnType != null) {
180+
op.returnType = normalizeType(op.returnType);
181+
}
182+
183+
// path is an unescaped variable in the mustache template api.mustache
184+
// line 82 '<&path>'
185+
op.path = sanitizePath(op.path);
186+
187+
// Set vendor-extension to be used in template:
188+
// x-codegen-hasMoreRequired
189+
// x-codegen-hasMoreOptional
190+
// x-codegen-hasRequiredParams
191+
CodegenParameter lastRequired = null;
192+
CodegenParameter lastOptional = null;
193+
for (CodegenParameter p : op.allParams) {
194+
if (p.required) {
195+
lastRequired = p;
196+
}
197+
else {
198+
lastOptional = p;
199+
}
200+
}
201+
for (CodegenParameter p : op.allParams) {
202+
if (p == lastRequired) {
203+
p.vendorExtensions.put("x-codegen-hasMoreRequired", false);
204+
}
205+
else if (p == lastOptional) {
206+
p.vendorExtensions.put("x-codegen-hasMoreOptional", false);
207+
}
208+
else {
209+
p.vendorExtensions.put("x-codegen-hasMoreRequired", true);
210+
p.vendorExtensions.put("x-codegen-hasMoreOptional", true);
211+
}
212+
}
213+
op.vendorExtensions.put("x-codegen-hasRequiredParams", lastRequired != null);
214+
215+
op.vendorExtensions.put("x-codegen-httpMethodUpperCase", httpMethod.toUpperCase());
216+
217+
return op;
218+
}
219+
220+
/**
221+
* Parse Markdown to HTML for the main "Description" attribute
222+
*
223+
* @param openAPI
224+
* The base object containing the global description through
225+
* "Info" class
226+
* @return Void
227+
*/
228+
private void preparHtmlForGlobalDescription(OpenAPI openAPI) {
229+
String currentDescription = openAPI.getInfo().getDescription();
230+
if (currentDescription != null && !currentDescription.isEmpty()) {
231+
Markdown markInstance = new Markdown();
232+
openAPI.getInfo().setDescription(markInstance.toHtml(currentDescription));
233+
}
234+
else {
235+
LOGGER.error("Swagger object description is empty [" + openAPI.getInfo().getTitle() + "]");
236+
}
237+
}
238+
239+
/**
240+
* Format to HTML the enums contained in every operations
241+
*
242+
* @param parameterList
243+
* The whole parameters contained in one operation
244+
* @return String | Html formated enum
245+
*/
246+
public List<CodegenParameter> postProcessParameterEnum(List<CodegenParameter> parameterList) {
247+
String enumFormatted = "";
248+
for (CodegenParameter parameter : parameterList) {
249+
if (getBooleanValue(parameter, CodegenConstants.IS_ENUM_EXT_NAME)) {
250+
for (int i = 0; i < parameter._enum.size(); i++) {
251+
String spacer = (i == (parameter._enum.size() - 1)) ? " " : ", ";
252+
253+
if (parameter._enum.get(i) != null)
254+
enumFormatted += "`" + parameter._enum.get(i) + "`" + spacer;
255+
}
256+
Markdown markInstance = new Markdown();
257+
if (!enumFormatted.isEmpty())
258+
parameter.vendorExtensions.put("x-eumFormatted", markInstance.toHtml(enumFormatted));
259+
}
260+
}
261+
return parameterList;
262+
}
263+
264+
private String sanitizePath(String p) {
265+
// prefer replace a ', instead of a fuLL URL encode for readability
266+
return p.replaceAll("'", "%27");
267+
}
268+
269+
/**
270+
* Normalize type by wrapping primitive types with single quotes.
271+
*
272+
* @param type
273+
* Primitive type
274+
* @return Normalized type
275+
*/
276+
public String normalizeType(String type) {
277+
return type.replaceAll("\\b(Boolean|Integer|Number|String|Date)\\b", "'$1'");
278+
}
279+
280+
@Override
281+
public String escapeQuotationMark(String input) {
282+
// just return the original string
283+
return input;
284+
}
285+
286+
@Override
287+
public String escapeUnsafeCharacters(String input) {
288+
// just return the original string
289+
return input;
290+
}
291+
}

src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
io.swagger.codegen.languages.html.StaticDocCodegen
22
io.swagger.codegen.languages.html.StaticHtmlCodegen
3+
io.swagger.codegen.languages.html.StaticHtml2Codegen
34
io.swagger.codegen.languages.java.JavaClientCodegen
45
io.swagger.codegen.languages.java.JavaCXFServerCodegen
56
io.swagger.codegen.languages.java.JavaInflectorServerCodegen

src/main/resources/v2/htmlDocs2/css_bootstrap.mustache

+10
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)