Skip to content

Commit

Permalink
Merge pull request #832 from edeesis/issue-829
Browse files Browse the repository at this point in the history
fix #829 Fix issue with javascript path rendering in views
  • Loading branch information
graemerocher authored Nov 2, 2022
2 parents 2588a14 + 3336dfe commit 27b9767
Show file tree
Hide file tree
Showing 14 changed files with 162 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,21 +82,17 @@ protected String toHtmlAttributes() {
.collect(Collectors.joining(" "));
}

protected String getFinalUrl(VisitorContext context) {
if (isDefaultJsUrl) {
String contextPath = OpenApiApplicationVisitor.getConfigurationProperty("micronaut.server.context-path", context);
if (contextPath == null) {
contextPath = StringUtils.EMPTY_STRING;
}
String finalUrl = contextPath + (contextPath.endsWith("/") ? resourcesContextPath.substring(1) : resourcesContextPath);
if (!finalUrl.endsWith("/")) {
finalUrl += "/";
}

return finalUrl;
protected String getFinalUrlPrefix(OpenApiViewConfig.RendererType rendererType, VisitorContext context) {
String contextPath = OpenApiApplicationVisitor.getConfigurationProperty("micronaut.server.context-path", context);
if (contextPath == null) {
contextPath = StringUtils.EMPTY_STRING;
}
String finalUrl = contextPath + (contextPath.endsWith("/") ? resourcesContextPath.substring(1) : resourcesContextPath);
if (!finalUrl.endsWith("/")) {
finalUrl += "/";
}

return jsUrl;
return rendererType.getTemplatePath() + finalUrl;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,20 @@ public final class OpenApiViewConfig {
* The Renderer types.
*/
enum RendererType {
SWAGGER_UI, REDOC, RAPIDOC

SWAGGER_UI(TEMPLATES_SWAGGER_UI),
REDOC(TEMPLATES_REDOC),
RAPIDOC(TEMPLATES_RAPIDOC);

private final String templatePath;

RendererType(String templatePath) {
this.templatePath = templatePath;
}

public String getTemplatePath() {
return templatePath;
}
}

private OpenApiViewConfig() {
Expand Down Expand Up @@ -159,7 +172,7 @@ public void render(Path outputDir, VisitorContext visitorContext) throws IOExcep
render(rapidocConfig, rapidocDir, TEMPLATES + SLASH + TEMPLATES_RAPIDOC + SLASH + TEMPLATE_INDEX_HTML, visitorContext);
copyResources(rapidocConfig, rapidocDir, TEMPLATES_RAPIDOC, rapidocConfig.getResources(), visitorContext);
if (rapidocConfig.rapiPDFConfig.enabled) {
copyResources(rapidocConfig.rapiPDFConfig, rapidocDir, TEMPLATES_RAPIPDF, redocConfig.rapiPDFConfig.getResources(), visitorContext);
copyResources(rapidocConfig.rapiPDFConfig, rapidocDir, TEMPLATES_RAPIPDF, rapidocConfig.rapiPDFConfig.getResources(), visitorContext);
}
}
if (swaggerUIConfig != null) {
Expand All @@ -170,7 +183,7 @@ public void render(Path outputDir, VisitorContext visitorContext) throws IOExcep
}
copyResources(swaggerUIConfig, swaggerUiDir, TEMPLATES_SWAGGER_UI, swaggerUIConfig.getResources(), visitorContext);
if (swaggerUIConfig.rapiPDFConfig.enabled) {
copyResources(swaggerUIConfig.rapiPDFConfig, swaggerUiDir, TEMPLATES_RAPIPDF, redocConfig.rapiPDFConfig.getResources(), visitorContext);
copyResources(swaggerUIConfig.rapiPDFConfig, swaggerUiDir, TEMPLATES_RAPIPDF, swaggerUIConfig.rapiPDFConfig.getResources(), visitorContext);
}
copySwaggerUiTheme(swaggerUIConfig.theme.getCss() + ".css", swaggerUiDir, TEMPLATES_SWAGGER_UI, visitorContext);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@
*/
final class RapiPDFConfig extends AbstractViewConfig {

private static final String DEFAULT_RAPIPDF_JS_PATH = OpenApiViewConfig.RESOURCE_DIR + "/rapipdf-min.js";
private static final String DEFAULT_RAPIPDF_JS_PATH = OpenApiViewConfig.RESOURCE_DIR + "/";

private static final List<String> RESOURCE_FILES = Collections.singletonList(
DEFAULT_RAPIPDF_JS_PATH
DEFAULT_RAPIPDF_JS_PATH + "rapipdf-min.js"
);

private static final String LINK = "<script src='{{rapipdf.js.url}}'></script>";
private static final String LINK = "<script src='{{rapipdf.js.url.prefix}}rapipdf-min.js'></script>";
private static final String TAG = "<rapi-pdf id='rapi-pdf' {{rapipdf.attributes}}></rapi-pdf>";
private static final String SPEC = "document.getElementById('rapi-pdf').setAttribute('spec-url', contextPath + '{{specURL}}');";
private static final Map<String, Object> DEFAULT_OPTIONS = new HashMap<>(6);
Expand Down Expand Up @@ -135,7 +135,7 @@ String render(String template, RendererType rendererType, VisitorContext context
options.put("style", DEFAULT_RAPIDOC_STYLE);
}
}
String script = OpenApiViewConfig.replacePlaceHolder(LINK, "rapipdf.js.url", getFinalUrl(context), "");
String script = OpenApiViewConfig.replacePlaceHolder(LINK, "rapipdf.js.url.prefix", isDefaultJsUrl ? getFinalUrlPrefix(rendererType, context) : jsUrl, "");
String rapipdfTag = OpenApiViewConfig.replacePlaceHolder(TAG, "rapipdf.attributes", toHtmlAttributes(), "");
if (styleUpdated) {
options.remove("style");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@
final class RapidocConfig extends AbstractViewConfig implements Renderer {

public static final String RAPIDOC_PREFIX = "rapidoc.";
private static final String DEFAULT_RAPIDOC_JS_PATH = OpenApiViewConfig.RESOURCE_DIR + "/rapidoc-min.js";
private static final String DEFAULT_RAPIDOC_JS_PATH = OpenApiViewConfig.RESOURCE_DIR + "/";

private static final List<String> RESOURCE_FILES = Collections.singletonList(
DEFAULT_RAPIDOC_JS_PATH
DEFAULT_RAPIDOC_JS_PATH + "rapidoc-min.js"
);

private static final Map<String, Object> DEFAULT_OPTIONS = new HashMap<>();
Expand Down Expand Up @@ -398,7 +398,7 @@ static RapidocConfig fromProperties(Map<String, String> properties) {
@Override
public String render(String template, VisitorContext context) {
template = rapiPDFConfig.render(template, RendererType.RAPIDOC, context);
template = OpenApiViewConfig.replacePlaceHolder(template, "rapidoc.js.url", getFinalUrl(context), "");
template = OpenApiViewConfig.replacePlaceHolder(template, "rapidoc.js.url.prefix", isDefaultJsUrl ? getFinalUrlPrefix(RendererType.RAPIDOC, context) : jsUrl, "");
return OpenApiViewConfig.replacePlaceHolder(template, "rapidoc.attributes", toHtmlAttributes(), "");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@
*/
final class RedocConfig extends AbstractViewConfig implements Renderer {

private static final String DEFAULT_REDOC_JS_PATH = OpenApiViewConfig.RESOURCE_DIR + "/redoc.standalone.js";
private static final String DEFAULT_REDOC_JS_PATH = OpenApiViewConfig.RESOURCE_DIR + "/";

private static final List<String> RESOURCE_FILES = Collections.singletonList(
DEFAULT_REDOC_JS_PATH
DEFAULT_REDOC_JS_PATH + "redoc.standalone.js"
);

private static final Map<String, Object> DEFAULT_OPTIONS = Collections.emptyMap();
Expand Down Expand Up @@ -147,7 +147,7 @@ static RedocConfig fromProperties(Map<String, String> properties) {
@Override
public String render(String template, VisitorContext context) {
template = rapiPDFConfig.render(template, RendererType.REDOC, context);
template = OpenApiViewConfig.replacePlaceHolder(template, "redoc.js.url", getFinalUrl(context), "");
template = OpenApiViewConfig.replacePlaceHolder(template, "redoc.js.url.prefix", isDefaultJsUrl ? getFinalUrlPrefix(RendererType.REDOC, context) : jsUrl, "");
return OpenApiViewConfig.replacePlaceHolder(template, "redoc.attributes", toHtmlAttributes(), "");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,13 @@ static SwaggerUIConfig fromProperties(Map<String, String> properties) {
@Override
public String render(String template, VisitorContext context) {

String finalUrl = getFinalUrl(context);
String finalUrlPrefix = getFinalUrlPrefix(RendererType.SWAGGER_UI, context);

template = rapiPDFConfig.render(template, RendererType.SWAGGER_UI, context);
template = OpenApiViewConfig.replacePlaceHolder(template, PREFIX_SWAGGER_UI + ".js.url", finalUrl, "");
template = OpenApiViewConfig.replacePlaceHolder(template, PREFIX_SWAGGER_UI + ".js.url.prefix", isDefaultJsUrl ? finalUrlPrefix : jsUrl, "");
template = OpenApiViewConfig.replacePlaceHolder(template, PREFIX_SWAGGER_UI + ".attributes", toOptions(), "");
template = template.replace("{{" + PREFIX_SWAGGER_UI + ".theme}}", theme == null || Theme.CLASSIC == theme ? "" :
"<link rel='stylesheet' type='text/css' href='" + finalUrl + theme.getCss() + ".css' />");
"<link rel='stylesheet' type='text/css' href='" + finalUrlPrefix + theme.getCss() + ".css' />");
template = template.replace("{{" + PREFIX_SWAGGER_UI + DOT + OPTION_OAUTH2 + "}}", hasOauth2Option(options) ? toOauth2Options() : "");
return template;
}
Expand Down
2 changes: 1 addition & 1 deletion openapi/src/main/resources/templates/rapidoc/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<!-- Important: The Custom element uses utf8 characters -->
<meta charset='utf-8' />
<meta name='viewport' content='width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes' />
<script src='{{rapidoc.js.url}}'></script>
<script src='{{rapidoc.js.url.prefix}}rapidoc-min.js'></script>
{{rapipdf.script}}
</head>
<body>
Expand Down
2 changes: 1 addition & 1 deletion openapi/src/main/resources/templates/redoc/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<body>
{{rapipdf.tag}}
<redoc id='redoc' {{redoc.attributes}}></redoc>
<script src='{{redoc.js.url}}'></script>
<script src='{{redoc.js.url.prefix}}redoc.standalone.js'></script>
<script>
const extract = function(v) {
return decodeURIComponent(v.replace(/(?:(?:^|.*;\s*)contextPath\s*\=\s*([^;]*).*$)|^.*$/, "$1"));
Expand Down
10 changes: 5 additions & 5 deletions openapi/src/main/resources/templates/swagger-ui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
<head>
<meta charset='UTF-8' />
<title>{{title}}</title>
<link rel='icon' type='image/png' href='{{swagger-ui.js.url}}favicon-32x32.png' sizes='32x32' />
<link rel='icon' type='image/png' href='{{swagger-ui.js.url}}favicon-16x16.png' sizes='16x16' />
<script src='{{swagger-ui.js.url}}swagger-ui-bundle.js'></script>
<script src='{{swagger-ui.js.url}}swagger-ui-standalone-preset.js'></script>
<link rel='stylesheet' type='text/css' href='{{swagger-ui.js.url}}swagger-ui.css' />
<link rel='icon' type='image/png' href='{{swagger-ui.js.url.prefix}}favicon-32x32.png' sizes='32x32' />
<link rel='icon' type='image/png' href='{{swagger-ui.js.url.prefix}}favicon-16x16.png' sizes='16x16' />
<script src='{{swagger-ui.js.url.prefix}}swagger-ui-bundle.js'></script>
<script src='{{swagger-ui.js.url.prefix}}swagger-ui-standalone-preset.js'></script>
<link rel='stylesheet' type='text/css' href='{{swagger-ui.js.url.prefix}}swagger-ui.css' />
{{swagger-ui.theme}}
{{rapipdf.script}}
</head>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class OpenApiOperationViewRenderSpec extends Specification {

void "test render OpenApiView specification"() {
given:
String spec = "redoc.enabled=true,rapidoc.enabled=true,swagger-ui.enabled=true,rapipdf.enabled=true,swagger-ui.theme=flattop,redoc.js.url=https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"
String spec = "redoc.enabled=true,rapidoc.enabled=true,swagger-ui.enabled=true,rapipdf.enabled=true,swagger-ui.theme=flattop"
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, new Properties())
Path outputDir = Paths.get("output")
cfg.title = "OpenAPI documentation"
Expand All @@ -32,7 +32,7 @@ class OpenApiOperationViewRenderSpec extends Specification {
cfg.specFile == "swagger.yml"
cfg.getSpecURL() == "/swagger/swagger.yml"
Files.exists(outputDir.resolve("redoc").resolve("index.html"))
!Files.exists(outputDir.resolve("redoc").resolve("res").resolve("redoc.standalone.js"))
Files.exists(outputDir.resolve("redoc").resolve("res").resolve("redoc.standalone.js"))
Files.exists(outputDir.resolve("redoc").resolve("res").resolve("rapipdf-min.js"))
Files.exists(outputDir.resolve("rapidoc").resolve("index.html"))
Files.exists(outputDir.resolve("rapidoc").resolve("res").resolve("rapidoc-min.js"))
Expand All @@ -46,11 +46,78 @@ class OpenApiOperationViewRenderSpec extends Specification {
Files.exists(outputDir.resolve("swagger-ui").resolve("res").resolve("rapipdf-min.js"))
Files.exists(outputDir.resolve("swagger-ui").resolve("res").resolve("flattop.css"))

outputDir.resolve("redoc").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js")

outputDir.resolve("redoc").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("redoc/res/redoc.standalone.js")
outputDir.resolve("redoc").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains(cfg.getSpecURL())
outputDir.resolve("redoc").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("redoc/res/rapipdf-min.js")
outputDir.resolve("rapidoc").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("rapidoc/res/rapidoc-min.js")
outputDir.resolve("rapidoc").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains(cfg.getSpecURL())
outputDir.resolve("rapidoc").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("rapidoc/res/rapipdf-min.js")
outputDir.resolve("swagger-ui").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("swagger-ui/res/swagger-ui-bundle.js")
outputDir.resolve("swagger-ui").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("swagger-ui/res/swagger-ui-standalone-preset.js")
outputDir.resolve("swagger-ui").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("swagger-ui/res/swagger-ui.css")
outputDir.resolve("swagger-ui").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("swagger-ui/res/favicon-32x32.png")
outputDir.resolve("swagger-ui").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("swagger-ui/res/favicon-16x16.png")
outputDir.resolve("swagger-ui").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains(cfg.getSpecURL())
outputDir.resolve("swagger-ui").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("swagger-ui/res/rapipdf-min.js")
}

void "test render OpenApiView specification with custom redoc js url"() {
given:
String spec = "redoc.enabled=true,rapipdf.enabled=true,redoc.js.url=https://cdn.redoc.ly/redoc/latest/bundles/"
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, new Properties())
Path outputDir = Paths.get("output")
cfg.title = "OpenAPI documentation"
cfg.specFile = "swagger.yml"
cfg.render(outputDir, null)

expect:
cfg.enabled
cfg.mappingPath == "swagger"
cfg.rapidocConfig == null
cfg.redocConfig != null
cfg.swaggerUIConfig == null
cfg.title == "OpenAPI documentation"
cfg.specFile == "swagger.yml"
cfg.getSpecURL() == "/swagger/swagger.yml"
Files.exists(outputDir.resolve("redoc").resolve("index.html"))
!Files.exists(outputDir.resolve("redoc").resolve("res").resolve("redoc.standalone.js"))
Files.exists(outputDir.resolve("redoc").resolve("res").resolve("rapipdf-min.js"))

outputDir.resolve("redoc").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("<script src='https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js'></script>")
outputDir.resolve("redoc").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains(cfg.getSpecURL())
}

void "test render OpenApiView specification with custom swagger js and css urls"() {
given:
String spec = "swagger-ui.enabled=true,rapipdf.enabled=true,swagger-ui.theme=flattop,swagger-ui.js.url=https://unpkg.com/swagger-ui-dist/"
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, new Properties())
Path outputDir = Paths.get("output")
cfg.title = "OpenAPI documentation"
cfg.specFile = "swagger.yml"
cfg.render(outputDir, null)

expect:
cfg.enabled
cfg.mappingPath == "swagger"
cfg.rapidocConfig == null
cfg.redocConfig == null
cfg.swaggerUIConfig != null
cfg.title == "OpenAPI documentation"
cfg.specFile == "swagger.yml"
cfg.getSpecURL() == "/swagger/swagger.yml"
Files.exists(outputDir.resolve("swagger-ui").resolve("index.html"))
!Files.exists(outputDir.resolve("swagger-ui").resolve("res").resolve("swagger-ui.css"))
!Files.exists(outputDir.resolve("swagger-ui").resolve("res").resolve("favicon-16x16.png"))
!Files.exists(outputDir.resolve("swagger-ui").resolve("res").resolve("favicon-32x32.png"))
!Files.exists(outputDir.resolve("swagger-ui").resolve("res").resolve("swagger-ui-bundle.js"))
!Files.exists(outputDir.resolve("swagger-ui").resolve("res").resolve("swagger-ui-standalone-preset.js"))
Files.exists(outputDir.resolve("swagger-ui").resolve("res").resolve("flattop.css"))
Files.exists(outputDir.resolve("swagger-ui").resolve("res").resolve("rapipdf-min.js"))

outputDir.resolve("swagger-ui").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains(cfg.getSpecURL())
outputDir.resolve("swagger-ui").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("<script src='https://unpkg.com/swagger-ui-dist/swagger-ui-standalone-preset.js'></script>")
outputDir.resolve("swagger-ui").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("<script src='https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js'></script>")
outputDir.resolve("swagger-ui").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("<link rel='stylesheet' type='text/css' href='https://unpkg.com/swagger-ui-dist/swagger-ui.css' />")
}

void "test render OpenApiView specification with server context path"() {
Expand Down
Loading

0 comments on commit 27b9767

Please sign in to comment.