Skip to content

Commit b5e81d6

Browse files
authored
Merge pull request #2069 from altro3/scalar-multiple
Added support multiple documents for Scalar
2 parents 1f0f923 + 683c35a commit b5e81d6

File tree

24 files changed

+14870
-14506
lines changed

24 files changed

+14870
-14506
lines changed

openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -4576,7 +4576,7 @@ protected ApiResponse findMethodResponse(ApiResponses responses) {
45764576
* Set op's returnBaseType, returnType, examples etc.
45774577
*
45784578
* @param operation endpoint Operation
4579-
* @param schemas a map of the schemas in the openapi spec
4579+
* @param schemas a map of the schemas in the OpenAPI spec
45804580
* @param op endpoint CodegenOperation
45814581
* @param methodResponse the default ApiResponse for the endpoint
45824582
*/
@@ -4591,7 +4591,7 @@ protected void handleMethodResponse(Operation operation,
45914591
* Set op's returnBaseType, returnType, examples etc.
45924592
*
45934593
* @param operation endpoint Operation
4594-
* @param schemas a map of the schemas in the openapi spec
4594+
* @param schemas a map of the schemas in the OpenAPI spec
45954595
* @param op endpoint CodegenOperation
45964596
* @param methodResponse the default ApiResponse for the endpoint
45974597
* @param schemaMappings mappings of external types to be omitted by unaliasing

openapi/src/main/java/io/micronaut/openapi/view/OpenApiExplorerConfig.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package io.micronaut.openapi.view;
1717

1818
import io.micronaut.core.annotation.Nullable;
19-
import io.micronaut.core.util.StringUtils;
2019
import io.micronaut.inject.visitor.VisitorContext;
2120
import io.micronaut.openapi.view.OpenApiViewConfig.RendererType;
2221
import io.micronaut.openapi.visitor.Pair;
@@ -133,8 +132,8 @@ static OpenApiExplorerConfig fromProperties(Map<String, String> properties, Map<
133132
@Override
134133
public String render(String template, @Nullable VisitorContext context) {
135134
template = rapiPDFConfig.render(template, RendererType.OPENAPI_EXPLORER, context);
136-
template = OpenApiViewConfig.replacePlaceHolder(template, "openapi-explorer.js.url.prefix", isDefaultJsUrl ? getFinalUrlPrefix(RendererType.OPENAPI_EXPLORER, context) : jsUrl, StringUtils.EMPTY_STRING);
137-
return OpenApiViewConfig.replacePlaceHolder(template, "openapi-explorer.attributes", toHtmlAttributes(), StringUtils.EMPTY_STRING);
135+
template = OpenApiViewConfig.replacePlaceHolder(template, "openapi-explorer.js.url.prefix", isDefaultJsUrl ? getFinalUrlPrefix(RendererType.OPENAPI_EXPLORER, context) : jsUrl);
136+
return OpenApiViewConfig.replacePlaceHolder(template, "openapi-explorer.attributes", toHtmlAttributes());
138137
}
139138

140139
@Override

openapi/src/main/java/io/micronaut/openapi/view/OpenApiViewConfig.java

+10-9
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import java.util.Optional;
4545
import java.util.Properties;
4646

47+
import static io.micronaut.core.util.StringUtils.EMPTY_STRING;
4748
import static io.micronaut.openapi.adoc.utils.FileUtils.CLASSPATH_SCHEME;
4849
import static io.micronaut.openapi.adoc.utils.FileUtils.FILE_SCHEME;
4950
import static io.micronaut.openapi.adoc.utils.FileUtils.PROJECT_SCHEME;
@@ -143,7 +144,7 @@ private static Map<String, String> parse(String specification) {
143144
}
144145
var keyValue = prop.split("=", 2);
145146
var key = keyValue[0].strip();
146-
var value = keyValue.length == 1 ? StringUtils.EMPTY_STRING : keyValue[1].strip();
147+
var value = keyValue.length == 1 ? EMPTY_STRING : keyValue[1].strip();
147148
if (key.isEmpty()) {
148149
continue;
149150
}
@@ -335,7 +336,7 @@ private String readTemplateFromClasspath(String templateName) throws IOException
335336
}
336337

337338
private String readTemplateFromCustomPath(String customPathStr, @Nullable VisitorContext context) throws IOException {
338-
String projectDir = StringUtils.EMPTY_STRING;
339+
String projectDir = EMPTY_STRING;
339340
Path projectPath = context != null ? getProjectPath(context) : null;
340341
if (projectPath != null) {
341342
projectDir = projectPath.toString().replace("\\\\", SLASH);
@@ -387,9 +388,10 @@ private void render(AbstractViewConfig cfg, Path outputDir, String templateName,
387388
template = readTemplateFromCustomPath(cfg.templatePath, context);
388389
}
389390

391+
cfg.specUrl = getSpecURL(cfg, context);
390392
template = cfg.render(template, context);
391-
template = replacePlaceHolder(template, "specURL", getSpecURL(cfg, context), StringUtils.EMPTY_STRING);
392-
template = replacePlaceHolder(template, "title", title, StringUtils.EMPTY_STRING);
393+
template = replacePlaceHolder(template, "specURL", cfg.specUrl);
394+
template = replacePlaceHolder(template, "title", title);
393395
if (!Files.exists(outputDir)) {
394396
Files.createDirectories(outputDir);
395397
}
@@ -440,13 +442,13 @@ public String getSpecURL(AbstractViewConfig cfg, @Nullable VisitorContext contex
440442
return cfg.specUrl;
441443
}
442444
if (specFile == null) {
443-
return StringUtils.EMPTY_STRING;
445+
return EMPTY_STRING;
444446
}
445447

446448
// process micronaut.openapi.server.context.path
447449
String serverContextPath = ConfigUtils.getConfigProperty(MICRONAUT_OPENAPI_CONTEXT_SERVER_PATH, context);
448450
if (serverContextPath == null) {
449-
serverContextPath = StringUtils.EMPTY_STRING;
451+
serverContextPath = EMPTY_STRING;
450452
}
451453
String finalUrl = serverContextPath.startsWith(SLASH) ? serverContextPath : SLASH + serverContextPath;
452454
if (!finalUrl.endsWith(SLASH)) {
@@ -482,12 +484,11 @@ public void setSpecFile(String specFile) {
482484
* @param template A template.
483485
* @param placeHolder The placeholder to replace.
484486
* @param value The value that will replace the placeholder.
485-
* @param valuePrefix A prefix.
486487
*
487488
* @return The updated template.
488489
*/
489-
static String replacePlaceHolder(String template, String placeHolder, String value, String valuePrefix) {
490-
return template.replace("{{" + placeHolder + "}}", StringUtils.isNotEmpty(value) ? valuePrefix + value : StringUtils.EMPTY_STRING);
490+
public static String replacePlaceHolder(String template, String placeHolder, String value) {
491+
return template.replace("{{" + placeHolder + "}}", StringUtils.isNotEmpty(value) ? value : EMPTY_STRING);
491492
}
492493

493494
public SwaggerUIConfig getSwaggerUIConfig() {

openapi/src/main/java/io/micronaut/openapi/view/RapiPDFConfig.java

+8-8
Original file line numberDiff line numberDiff line change
@@ -144,18 +144,18 @@ String render(String template, RendererType rendererType, VisitorContext context
144144
options.put("style", DEFAULT_RAPIDOC_STYLE);
145145
}
146146
}
147-
String script = replacePlaceHolder(SCRIPT_RAPIPDF, "rapipdf.js.url.prefix", isDefaultJsUrl ? getFinalUrlPrefix(rendererType, context) : jsUrl, StringUtils.EMPTY_STRING);
148-
String rapipdfTag = replacePlaceHolder(TAG, "rapipdf.attributes", toHtmlAttributes(), StringUtils.EMPTY_STRING);
147+
String script = replacePlaceHolder(SCRIPT_RAPIPDF, "rapipdf.js.url.prefix", isDefaultJsUrl ? getFinalUrlPrefix(rendererType, context) : jsUrl);
148+
String rapipdfTag = replacePlaceHolder(TAG, "rapipdf.attributes", toHtmlAttributes());
149149
if (styleUpdated) {
150150
options.remove("style");
151151
}
152-
template = replacePlaceHolder(template, "rapipdf.script", script, StringUtils.EMPTY_STRING);
153-
template = replacePlaceHolder(template, "rapipdf.specurl", SPEC, StringUtils.EMPTY_STRING);
154-
return replacePlaceHolder(template, "rapipdf.tag", rapipdfTag, StringUtils.EMPTY_STRING);
152+
template = replacePlaceHolder(template, "rapipdf.script", script);
153+
template = replacePlaceHolder(template, "rapipdf.specurl", SPEC);
154+
return replacePlaceHolder(template, "rapipdf.tag", rapipdfTag);
155155
} else {
156-
template = replacePlaceHolder(template, "rapipdf.script", StringUtils.EMPTY_STRING, StringUtils.EMPTY_STRING);
157-
template = replacePlaceHolder(template, "rapipdf.specurl", StringUtils.EMPTY_STRING, StringUtils.EMPTY_STRING);
158-
return replacePlaceHolder(template, "rapipdf.tag", StringUtils.EMPTY_STRING, StringUtils.EMPTY_STRING);
156+
template = replacePlaceHolder(template, "rapipdf.script", StringUtils.EMPTY_STRING);
157+
template = replacePlaceHolder(template, "rapipdf.specurl", StringUtils.EMPTY_STRING);
158+
return replacePlaceHolder(template, "rapipdf.tag", StringUtils.EMPTY_STRING);
159159
}
160160
}
161161

openapi/src/main/java/io/micronaut/openapi/view/RapidocConfig.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package io.micronaut.openapi.view;
1717

1818
import io.micronaut.core.annotation.Nullable;
19-
import io.micronaut.core.util.StringUtils;
2019
import io.micronaut.inject.visitor.VisitorContext;
2120
import io.micronaut.openapi.view.OpenApiViewConfig.RendererType;
2221
import io.micronaut.openapi.visitor.Pair;
@@ -386,8 +385,8 @@ static RapidocConfig fromProperties(Map<String, String> properties, Map<Pair<Str
386385
@Override
387386
public String render(String template, @Nullable VisitorContext context) {
388387
template = rapiPDFConfig.render(template, RendererType.RAPIDOC, context);
389-
template = OpenApiViewConfig.replacePlaceHolder(template, "rapidoc.js.url.prefix", isDefaultJsUrl ? getFinalUrlPrefix(RendererType.RAPIDOC, context) : jsUrl, StringUtils.EMPTY_STRING);
390-
return OpenApiViewConfig.replacePlaceHolder(template, "rapidoc.attributes", toHtmlAttributes(), StringUtils.EMPTY_STRING);
388+
template = OpenApiViewConfig.replacePlaceHolder(template, "rapidoc.js.url.prefix", isDefaultJsUrl ? getFinalUrlPrefix(RendererType.RAPIDOC, context) : jsUrl);
389+
return OpenApiViewConfig.replacePlaceHolder(template, "rapidoc.attributes", toHtmlAttributes());
391390
}
392391

393392
@Override

openapi/src/main/java/io/micronaut/openapi/view/RedocConfig.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package io.micronaut.openapi.view;
1717

1818
import io.micronaut.core.annotation.Nullable;
19-
import io.micronaut.core.util.StringUtils;
2019
import io.micronaut.inject.visitor.VisitorContext;
2120
import io.micronaut.openapi.view.OpenApiViewConfig.RendererType;
2221
import io.micronaut.openapi.visitor.Pair;
@@ -148,8 +147,8 @@ static RedocConfig fromProperties(Map<String, String> properties, Map<Pair<Strin
148147
@Override
149148
public String render(String template, @Nullable VisitorContext context) {
150149
template = rapiPDFConfig.render(template, RendererType.REDOC, context);
151-
template = OpenApiViewConfig.replacePlaceHolder(template, "redoc.js.url.prefix", isDefaultJsUrl ? getFinalUrlPrefix(RendererType.REDOC, context) : jsUrl, StringUtils.EMPTY_STRING);
152-
return OpenApiViewConfig.replacePlaceHolder(template, "redoc.attributes", toHtmlAttributes(), StringUtils.EMPTY_STRING);
150+
template = OpenApiViewConfig.replacePlaceHolder(template, "redoc.js.url.prefix", isDefaultJsUrl ? getFinalUrlPrefix(RendererType.REDOC, context) : jsUrl);
151+
return OpenApiViewConfig.replacePlaceHolder(template, "redoc.attributes", toHtmlAttributes());
153152
}
154153

155154
@Override

openapi/src/main/java/io/micronaut/openapi/view/ScalarConfig.java

+36-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
*/
1616
package io.micronaut.openapi.view;
1717

18+
import io.micronaut.core.annotation.NonNull;
1819
import io.micronaut.core.annotation.Nullable;
20+
import io.micronaut.core.util.CollectionUtils;
1921
import io.micronaut.core.util.StringUtils;
2022
import io.micronaut.inject.visitor.VisitorContext;
2123
import io.micronaut.openapi.view.OpenApiViewConfig.RendererType;
@@ -30,8 +32,10 @@
3032

3133
import static io.micronaut.core.util.StringUtils.EMPTY_STRING;
3234
import static io.micronaut.openapi.view.OpenApiViewConfig.replacePlaceHolder;
35+
import static io.micronaut.openapi.visitor.StringUtil.CLOSE_BRACE;
3336
import static io.micronaut.openapi.visitor.StringUtil.COMMA_NEW_LINE;
3437
import static io.micronaut.openapi.visitor.StringUtil.KEY_VALUE_SEPARATOR;
38+
import static io.micronaut.openapi.visitor.StringUtil.OPEN_BRACE;
3539
import static io.micronaut.openapi.visitor.StringUtil.SLASH;
3640

3741
/**
@@ -88,7 +92,7 @@ public final class ScalarConfig extends AbstractViewConfig {
8892
VALID_OPTIONS.put("hideClientButton", AbstractViewConfig::asBoolean);
8993

9094
DEFAULT_OPTIONS.put("defaultHttpClient", "{targetKey: 'shell', clientKey: 'curl'}");
91-
// by default, we have only shell curl (currl), Invoke-WebRequest Powershell (webrequest), java.net.http Java (nethttp), Fetch JavaScript (fetch), Axios JavaScript (axios)
95+
// by default, we have only shell curl (curl), Invoke-WebRequest Powershell (webrequest), java.net.http Java (nethttp), Fetch JavaScript (fetch), Axios JavaScript (axios)
9296
DEFAULT_OPTIONS.put("hiddenClients", "['libcurl', 'clj_http', 'httpclient', 'restsharp', 'native', 'http1.1', 'asynchttp', 'okhttp', 'unirest', 'xhr', 'jquery', 'native', 'request', 'unirest', 'ofetch', 'nsurlsession', 'cohttp', 'guzzle', 'http', 'http1', 'http2', 'restmethod', 'python3', 'requests', 'httr', 'native', 'curl', 'httpie', 'wget', 'nsurlsession', 'undici'],");
9397
}
9498

@@ -126,9 +130,37 @@ static ScalarConfig fromProperties(Map<String, String> properties, Map<Pair<Stri
126130
@Override
127131
public String render(String template, @Nullable VisitorContext context) {
128132
template = rapiPDFConfig.render(template, RendererType.SCALAR, context);
129-
template = replacePlaceHolder(template, "scalar.js.url.prefix", isDefaultJsUrl ? getFinalUrlPrefix(RendererType.SCALAR, context) : jsUrl, StringUtils.EMPTY_STRING);
130-
template = replacePlaceHolder(template, "style", StringUtils.isNotEmpty(style) ? "<style>" + style + "</style>" : EMPTY_STRING, EMPTY_STRING);
131-
return replacePlaceHolder(template, "scalar.attributes", toOptions(), StringUtils.EMPTY_STRING);
133+
template = replacePlaceHolder(template, "scalar.js.url.prefix", isDefaultJsUrl ? getFinalUrlPrefix(RendererType.SCALAR, context) : jsUrl);
134+
template = replacePlaceHolder(template, "style", StringUtils.isNotEmpty(style) ? "<style>" + style + "</style>" : EMPTY_STRING);
135+
template = replacePlaceHolder(template, "scalar.sources", getSourcesStr());
136+
return replacePlaceHolder(template, "scalar.attributes", toOptions());
137+
}
138+
139+
@NonNull
140+
private String getSourcesStr() {
141+
var result = new StringBuilder("sources: [");
142+
// case with single document
143+
if (CollectionUtils.isEmpty(urls) || (withUrls != null && !withUrls)) {
144+
result.append("{url: contextPath + \"").append(specUrl).append("\"}");
145+
} else {
146+
// case with multiple documents
147+
var isFirst = true;
148+
for (var url : urls) {
149+
if (!isFirst) {
150+
result.append(',');
151+
}
152+
result.append(OPEN_BRACE)
153+
.append("title: \"").append(url.name()).append("\",")
154+
.append("url: contextPath + \"").append(url.url()).append("\",");
155+
if (StringUtils.isNotEmpty(primaryName) && primaryName.equals(url.name())) {
156+
result.append("default: true");
157+
}
158+
result.append(CLOSE_BRACE);
159+
isFirst = false;
160+
}
161+
}
162+
result.append("],");
163+
return result.toString();
132164
}
133165

134166
@Override

openapi/src/main/java/io/micronaut/openapi/view/SwaggerUIConfig.java

+17-13
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,15 @@
3434

3535
import static io.micronaut.core.util.StringUtils.EMPTY_STRING;
3636
import static io.micronaut.openapi.view.OpenApiViewConfig.replacePlaceHolder;
37+
import static io.micronaut.openapi.visitor.StringUtil.CLOSE_BRACE;
3738
import static io.micronaut.openapi.visitor.StringUtil.COMMA_NEW_LINE;
3839
import static io.micronaut.openapi.visitor.StringUtil.DOT;
3940
import static io.micronaut.openapi.visitor.StringUtil.KEY_VALUE_SEPARATOR;
41+
import static io.micronaut.openapi.visitor.StringUtil.OPEN_BRACE;
4042
import static io.micronaut.openapi.visitor.StringUtil.SLASH;
4143

4244
/**
43-
* Swagger-ui configuration.
45+
* Swagger UI configuration.
4446
*
4547
* @author croudet
4648
*/
@@ -157,7 +159,7 @@ public static SyntaxHighlightTheme byCode(String code) {
157159
}
158160

159161
/**
160-
* Swagger-ui themes. <a href="https://github.com/ilyamixaltik/swagger-themes">link</a>
162+
* Swagger UI themes. <a href="https://github.com/ilyamixaltik/swagger-themes">link</a>
161163
*/
162164
enum Theme {
163165
CLASSIC("classic"),
@@ -260,31 +262,31 @@ public String render(String template, @Nullable VisitorContext context) {
260262
String finalUrlPrefix = getFinalUrlPrefix(RendererType.SWAGGER_UI, context);
261263

262264
template = rapiPDFConfig.render(template, RendererType.SWAGGER_UI, context);
263-
template = replacePlaceHolder(template, PREFIX_SWAGGER_UI + ".js.url.prefix", isDefaultJsUrl ? finalUrlPrefix : jsUrl, EMPTY_STRING);
264-
template = replacePlaceHolder(template, PREFIX_SWAGGER_UI + ".attributes", toOptions(), EMPTY_STRING);
265+
template = replacePlaceHolder(template, PREFIX_SWAGGER_UI + ".js.url.prefix", isDefaultJsUrl ? finalUrlPrefix : jsUrl);
266+
template = replacePlaceHolder(template, PREFIX_SWAGGER_UI + ".attributes", toOptions());
265267

266268
if (theme != null && Theme.CLASSIC != theme) {
267269
var themeCssLink = isDefaultThemeUrl ? finalUrlPrefix + theme.getCss() + ".css" : themeUrl;
268-
template = template.replace("{{" + PREFIX_SWAGGER_UI + ".theme}}", "link(contextPath + \"" + themeCssLink + "\", head, \"text/css\", \"stylesheet\")");
270+
template = replacePlaceHolder(template, PREFIX_SWAGGER_UI + ".theme", "link(contextPath + \"" + themeCssLink + "\", head, \"text/css\", \"stylesheet\")");
269271
} else {
270-
template = template.replace("{{" + PREFIX_SWAGGER_UI + ".theme}}", EMPTY_STRING);
272+
template = replacePlaceHolder(template, PREFIX_SWAGGER_UI + ".theme", EMPTY_STRING);
271273
}
272-
template = template.replace("{{" + PREFIX_SWAGGER_UI + DOT + OPTION_OAUTH2 + "}}", hasOauth2Option(options) ? toOauth2Options() : EMPTY_STRING);
273-
template = template.replace("{{" + PREFIX_SWAGGER_UI + DOT + OPTION_PRIMARY_NAME + "}}", StringUtils.isNotEmpty(primaryName) ? getPrimaryName(context) : EMPTY_STRING);
274-
template = template.replace("{{" + PREFIX_SWAGGER_UI + DOT + OPTION_URLS + "}}", getUrlStr(context));
274+
template = replacePlaceHolder(template, PREFIX_SWAGGER_UI + DOT + OPTION_OAUTH2, hasOauth2Option(options) ? toOauth2Options() : EMPTY_STRING);
275+
template = replacePlaceHolder(template, PREFIX_SWAGGER_UI + DOT + OPTION_PRIMARY_NAME, StringUtils.isNotEmpty(primaryName) ? getPrimaryName() : EMPTY_STRING);
276+
template = replacePlaceHolder(template, PREFIX_SWAGGER_UI + DOT + OPTION_URLS, getUrlStr());
275277
return template;
276278
}
277279

278280
@NonNull
279-
private String getPrimaryName(VisitorContext context) {
281+
private String getPrimaryName() {
280282
if (StringUtils.isEmpty(primaryName)) {
281283
return EMPTY_STRING;
282284
}
283285
return "\"urls.primaryName\":\"" + primaryName + "\",";
284286
}
285287

286288
@NonNull
287-
private String getUrlStr(VisitorContext context) {
289+
private String getUrlStr() {
288290
if (CollectionUtils.isEmpty(urls) || (withUrls != null && !withUrls)) {
289291
return EMPTY_STRING;
290292
}
@@ -295,8 +297,10 @@ private String getUrlStr(VisitorContext context) {
295297
if (!isFirst) {
296298
result.append(',');
297299
}
298-
result.append("{url: contextPath + '").append(url.url())
299-
.append("', name: '").append(url.name()).append("'}");
300+
result.append(OPEN_BRACE)
301+
.append("name: \"").append(url.name()).append("\",")
302+
.append("url: contextPath + \"").append(url.url()).append('\"')
303+
.append(CLOSE_BRACE);
300304
isFirst = false;
301305
}
302306
result.append("],");

openapi/src/main/java/io/micronaut/openapi/visitor/OpenApiConfigProperty.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -332,14 +332,14 @@ public interface OpenApiConfigProperty {
332332
* Properties prefix to set custom schema implementations for selected classes.
333333
* For example, if you want to set simple 'java.lang.String' class to some complex 'org.somepackage.MyComplexType' class you need to write:
334334
* <p>
335-
* -Dmicronaut.openapi.group.my-group1.title="Title 1"
335+
* -Dmicronaut.openapi.groups.my-group1.title="Title 1"
336336
* <p>
337337
* Also, you can set it in your application.yml file like this:
338338
* <p>
339339
* <pre>
340340
* micronaut:
341341
* openapi:
342-
* group:
342+
* groups:
343343
* my-group1:
344344
* title: Title 1
345345
* filename: swagger-${group}-${apiVersion}-${version}.yml

openapi/src/main/java/io/micronaut/openapi/visitor/group/GroupProperties.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ public final class GroupProperties {
3232
*/
3333
private final String name;
3434
/**
35-
* Group title for swagger-ui selector.
35+
* Group title for Swagger UI / Scalar selector.
3636
*/
3737
private String displayName;
3838
/**
39-
* Is this group primary for swagger-ui.
39+
* Is this group primary for Swagger UI / Scalar.
4040
*/
4141
private Boolean primary;
4242
/**

0 commit comments

Comments
 (0)