mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
small api doc cleanup; large refactor (resources as resources, not java strings)
This commit is contained in:
@ -22,6 +22,7 @@
|
|||||||
package com.kingsrook.qqq.api.javalin;
|
package com.kingsrook.qqq.api.javalin;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -90,12 +91,14 @@ import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
|||||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||||
import com.kingsrook.qqq.backend.core.utils.collections.ListBuilder;
|
import com.kingsrook.qqq.backend.core.utils.collections.ListBuilder;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.collections.MapBuilder;
|
||||||
import com.kingsrook.qqq.backend.javalin.QJavalinAccessLogger;
|
import com.kingsrook.qqq.backend.javalin.QJavalinAccessLogger;
|
||||||
import com.kingsrook.qqq.backend.javalin.QJavalinImplementation;
|
import com.kingsrook.qqq.backend.javalin.QJavalinImplementation;
|
||||||
import io.javalin.apibuilder.ApiBuilder;
|
import io.javalin.apibuilder.ApiBuilder;
|
||||||
import io.javalin.apibuilder.EndpointGroup;
|
import io.javalin.apibuilder.EndpointGroup;
|
||||||
import io.javalin.http.ContentType;
|
import io.javalin.http.ContentType;
|
||||||
import io.javalin.http.Context;
|
import io.javalin.http.Context;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang.BooleanUtils;
|
import org.apache.commons.lang.BooleanUtils;
|
||||||
import org.eclipse.jetty.http.HttpStatus;
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
@ -141,8 +144,24 @@ public class QJavalinApiHandler
|
|||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
ApiBuilder.post("/api/oauth/token", QJavalinApiHandler::handleAuthorization);
|
ApiBuilder.post("/api/oauth/token", QJavalinApiHandler::handleAuthorization);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////
|
||||||
|
// static endpoints to support rapidoc pages //
|
||||||
|
///////////////////////////////////////////////
|
||||||
|
ApiBuilder.get("/api/docs/js/rapidoc.min.js", (context) -> QJavalinApiHandler.serveResource(context, "rapidoc/rapidoc-9.3.4.min.js", MapBuilder.of("Content-Type", ContentType.JAVASCRIPT)));
|
||||||
|
ApiBuilder.get("/api/docs/css/qqq-api-styles.css", (context) -> QJavalinApiHandler.serveResource(context, "rapidoc/rapidoc-overrides.css", MapBuilder.of("Content-Type", ContentType.CSS)));
|
||||||
|
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
// default page is the current version spec //
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
ApiBuilder.get("/api/", QJavalinApiHandler::doSpecHtml);
|
||||||
|
|
||||||
ApiBuilder.path("/api/{version}", () -> // todo - configurable, that /api/ bit?
|
ApiBuilder.path("/api/{version}", () -> // todo - configurable, that /api/ bit?
|
||||||
{
|
{
|
||||||
|
////////////////////////////////////////////
|
||||||
|
// default page for a version is its spec //
|
||||||
|
////////////////////////////////////////////
|
||||||
|
ApiBuilder.get("/", QJavalinApiHandler::doSpecHtml);
|
||||||
|
|
||||||
ApiBuilder.get("/openapi.yaml", QJavalinApiHandler::doSpecYaml);
|
ApiBuilder.get("/openapi.yaml", QJavalinApiHandler::doSpecYaml);
|
||||||
ApiBuilder.get("/openapi.json", QJavalinApiHandler::doSpecJson);
|
ApiBuilder.get("/openapi.json", QJavalinApiHandler::doSpecJson);
|
||||||
ApiBuilder.get("/openapi.html", QJavalinApiHandler::doSpecHtml);
|
ApiBuilder.get("/openapi.html", QJavalinApiHandler::doSpecHtml);
|
||||||
@ -171,7 +190,6 @@ public class QJavalinApiHandler
|
|||||||
});
|
});
|
||||||
|
|
||||||
ApiBuilder.get("/api/versions.json", QJavalinApiHandler::doVersions);
|
ApiBuilder.get("/api/versions.json", QJavalinApiHandler::doVersions);
|
||||||
ApiBuilder.get("/api/qqq-api-styles.css", QJavalinApiHandler::doStyles);
|
|
||||||
|
|
||||||
ApiBuilder.before("/*", QJavalinApiHandler::setupCORS);
|
ApiBuilder.before("/*", QJavalinApiHandler::setupCORS);
|
||||||
|
|
||||||
@ -199,6 +217,21 @@ public class QJavalinApiHandler
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static void serveResource(Context context, String resourcePath, Map<String, String> headers)
|
||||||
|
{
|
||||||
|
InputStream resourceAsStream = QJavalinApiHandler.class.getClassLoader().getResourceAsStream(resourcePath);
|
||||||
|
for(Map.Entry<String, String> entry : CollectionUtils.nonNullMap(headers).entrySet())
|
||||||
|
{
|
||||||
|
context.header(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
context.result(resourceAsStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -248,43 +281,6 @@ public class QJavalinApiHandler
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
private static void doSpecYaml(Context context)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
QContext.init(qInstance, null);
|
|
||||||
String version = context.pathParam("version");
|
|
||||||
|
|
||||||
GenerateOpenApiSpecInput input = new GenerateOpenApiSpecInput().withVersion(version);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if(StringUtils.hasContent(context.pathParam("tableName")))
|
|
||||||
{
|
|
||||||
input.setTableName(context.pathParam("tableName"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
///////////////////////////
|
|
||||||
// leave table param out //
|
|
||||||
///////////////////////////
|
|
||||||
}
|
|
||||||
|
|
||||||
GenerateOpenApiSpecOutput output = new GenerateOpenApiSpecAction().execute(input);
|
|
||||||
context.contentType(ContentType.APPLICATION_YAML);
|
|
||||||
context.result(output.getYaml());
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
handleException(context, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -380,6 +376,43 @@ public class QJavalinApiHandler
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static void doSpecYaml(Context context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
QContext.init(qInstance, null);
|
||||||
|
String version = context.pathParam("version");
|
||||||
|
|
||||||
|
GenerateOpenApiSpecInput input = new GenerateOpenApiSpecInput().withVersion(version);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(StringUtils.hasContent(context.pathParam("tableName")))
|
||||||
|
{
|
||||||
|
input.setTableName(context.pathParam("tableName"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
///////////////////////////
|
||||||
|
// leave table param out //
|
||||||
|
///////////////////////////
|
||||||
|
}
|
||||||
|
|
||||||
|
GenerateOpenApiSpecOutput output = new GenerateOpenApiSpecAction().execute(input);
|
||||||
|
context.contentType(ContentType.APPLICATION_YAML);
|
||||||
|
context.result(output.getYaml());
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
handleException(context, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -422,71 +455,19 @@ public class QJavalinApiHandler
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private static void doSpecHtml(Context context)
|
private static void doSpecHtml(Context context)
|
||||||
{
|
{
|
||||||
|
String version;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
QContext.init(qInstance, null);
|
version = context.pathParam("version");
|
||||||
|
|
||||||
QBrandingMetaData branding = QContext.getQInstance().getBranding();
|
|
||||||
String html = """
|
|
||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"></script>
|
|
||||||
<link rel="stylesheet" href="/api/qqq-api-styles.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<rapi-doc
|
|
||||||
id="the-rapi-doc"
|
|
||||||
spec-url="/api/{version}/openapi.json"
|
|
||||||
regular-font="Roboto,Helvetica,Arial,sans-serif"
|
|
||||||
mono-font="Monaco, Menlo, Consolas, source-code-pro, monospace"
|
|
||||||
font-size="large"
|
|
||||||
show-header="false"
|
|
||||||
allow-server-selection="false"
|
|
||||||
allow-spec-file-download="true"
|
|
||||||
primary-color="{primaryColor}"
|
|
||||||
sort-endpoints-by="method"
|
|
||||||
persist-auth="true"
|
|
||||||
render-style="focused"
|
|
||||||
show-method-in-nav-bar="as-colored-block"
|
|
||||||
nav-item-spacing="relaxed"
|
|
||||||
css-file="qqq-api-styles.css"
|
|
||||||
css-classes="qqqApi"
|
|
||||||
info-description-headings-in-navbar="true"
|
|
||||||
>
|
|
||||||
{navLogoImg}
|
|
||||||
</rapi-doc>
|
|
||||||
<script>
|
|
||||||
window.addEventListener('DOMContentLoaded', (event) => {
|
|
||||||
const rapidocEl = document.getElementById('the-rapi-doc');
|
|
||||||
rapidocEl.addEventListener('spec-loaded', (e) => {
|
|
||||||
console.log("rapidoc el: " + rapidocEl);
|
|
||||||
const shadowRoot = rapidocEl.shadowRoot;
|
|
||||||
console.log("shadowRoot: " + shadowRoot);
|
|
||||||
const collapseButton = shadowRoot.querySelector(".nav-bar-collapse-all")
|
|
||||||
collapseButton.click();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
"""
|
|
||||||
.replace("{version}", context.pathParam("version"))
|
|
||||||
.replace("{primaryColor}", branding == null ? "#FF791A" : branding.getAccentColor());
|
|
||||||
|
|
||||||
if(branding != null && StringUtils.hasContent(branding.getLogo()))
|
|
||||||
{
|
|
||||||
html = html.replace("{navLogoImg}", "<img slot=\"nav-logo\" src=\"" + branding.getLogo() + "\" style=\"width: fit-content; max-width: 280px; margin: auto;\"/>");
|
|
||||||
}
|
|
||||||
|
|
||||||
context.contentType(ContentType.HTML);
|
|
||||||
context.result(html);
|
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
handleException(context, e);
|
ApiInstanceMetaData apiInstanceMetaData = ApiInstanceMetaData.of(qInstance);
|
||||||
|
version = apiInstanceMetaData.getCurrentVersion().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doSpecHtml(context, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -494,53 +475,45 @@ public class QJavalinApiHandler
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private static void doStyles(Context context)
|
private static void doSpecHtml(Context context, String version)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
QContext.init(qInstance, null);
|
QBrandingMetaData branding = qInstance.getBranding();
|
||||||
|
ApiInstanceMetaData apiInstanceMetaData = ApiInstanceMetaData.of(qInstance);
|
||||||
|
|
||||||
String css = """
|
//////////////////////////////////
|
||||||
#api-info
|
// read html from resource file //
|
||||||
{
|
//////////////////////////////////
|
||||||
margin-left: 0px !important;
|
InputStream resourceAsStream = QJavalinApiHandler.class.getClassLoader().getResourceAsStream("rapidoc/rapidoc-container.html");
|
||||||
}
|
String html = IOUtils.toString(resourceAsStream, StandardCharsets.UTF_8.name());
|
||||||
|
|
||||||
#api-info button
|
|
||||||
{
|
|
||||||
width: auto !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#api-title span
|
|
||||||
{
|
|
||||||
font-size: 24px !important;
|
|
||||||
margin-left: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-scroll
|
|
||||||
{
|
|
||||||
padding-left: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag-description.expanded
|
|
||||||
{
|
|
||||||
max-height: initial !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag-description .m-markdown p
|
|
||||||
{
|
|
||||||
margin-block-end: 0.5em !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
api-response
|
|
||||||
{
|
|
||||||
margin-bottom: 50vh;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
""";
|
|
||||||
|
|
||||||
context.contentType(ContentType.CSS);
|
/////////////////////////////////
|
||||||
context.result(css);
|
// do replacements in the html //
|
||||||
|
/////////////////////////////////
|
||||||
|
html = html.replace("{version}", version);
|
||||||
|
html = html.replace("{primaryColor}", branding == null ? "#FF791A" : branding.getAccentColor());
|
||||||
|
|
||||||
|
if(branding != null && StringUtils.hasContent(branding.getLogo()))
|
||||||
|
{
|
||||||
|
html = html.replace("{navLogoImg}", "<img id=\"navLogo\" slot=\"nav-logo\" src=\"" + branding.getLogo() + "\" />");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
html = html.replace("{navLogoImg}", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
html = html.replace("{title}", apiInstanceMetaData.getName() + " - " + version);
|
||||||
|
|
||||||
|
StringBuilder otherVersionOptions = new StringBuilder();
|
||||||
|
for(APIVersion supportedVersion : apiInstanceMetaData.getSupportedVersions())
|
||||||
|
{
|
||||||
|
otherVersionOptions.append("<option value=\"/api/").append(supportedVersion).append("/openapi.html\">").append(supportedVersion).append("</option>");
|
||||||
|
}
|
||||||
|
html = html.replace("{otherVersionOptions}", otherVersionOptions.toString());
|
||||||
|
|
||||||
|
context.contentType(ContentType.HTML);
|
||||||
|
context.result(html);
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
|
3895
qqq-middleware-api/src/main/resources/rapidoc/rapidoc-9.3.4.min.js
vendored
Normal file
3895
qqq-middleware-api/src/main/resources/rapidoc/rapidoc-9.3.4.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,86 @@
|
|||||||
|
<!--
|
||||||
|
~ QQQ - Low-code Application Framework for Engineers.
|
||||||
|
~ Copyright (C) 2021-2023. Kingsrook, LLC
|
||||||
|
~ 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
~ contact@kingsrook.com
|
||||||
|
~ https://github.com/Kingsrook/
|
||||||
|
~
|
||||||
|
~ This program is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU Affero General Public License as
|
||||||
|
~ published by the Free Software Foundation, either version 3 of the
|
||||||
|
~ License, or (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU Affero General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU Affero General Public License
|
||||||
|
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<title>{title}</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<!-- <script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"></script> -->
|
||||||
|
<script type="module" src="/api/docs/js/rapidoc.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="/api/docs/css/qqq-api-styles.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<rapi-doc
|
||||||
|
id="the-rapi-doc"
|
||||||
|
spec-url="/api/{version}/openapi.json"
|
||||||
|
regular-font="Roboto,Helvetica,Arial,sans-serif"
|
||||||
|
mono-font="Monaco, Menlo, Consolas, source-code-pro, monospace"
|
||||||
|
font-size="large"
|
||||||
|
show-header="false"
|
||||||
|
allow-server-selection="false"
|
||||||
|
allow-spec-file-download="true"
|
||||||
|
primary-color="{primaryColor}"
|
||||||
|
sort-endpoints-by="method"
|
||||||
|
persist-auth="true"
|
||||||
|
render-style="focused"
|
||||||
|
show-method-in-nav-bar="as-colored-block"
|
||||||
|
nav-item-spacing="relaxed"
|
||||||
|
css-file="qqq-api-styles.css"
|
||||||
|
css-classes="qqqApi"
|
||||||
|
info-description-headings-in-navbar="true"
|
||||||
|
>
|
||||||
|
{navLogoImg}
|
||||||
|
<div slot="overview" id="otherVersions">
|
||||||
|
<label for="otherVersionsSelect">Other Versions:</label>
|
||||||
|
<select id="otherVersionsSelect" onchange=changeVersion()>
|
||||||
|
<option value="/api/">--</option>
|
||||||
|
{otherVersionOptions}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</rapi-doc>
|
||||||
|
<script>
|
||||||
|
window.addEventListener('DOMContentLoaded', (event) => {
|
||||||
|
const rapidocEl = document.getElementById('the-rapi-doc');
|
||||||
|
rapidocEl.addEventListener('spec-loaded', (e) => {
|
||||||
|
|
||||||
|
const shadowRoot = rapidocEl.shadowRoot;
|
||||||
|
const collapseButton = shadowRoot.querySelector(".nav-bar-collapse-all");
|
||||||
|
if(collapseButton)
|
||||||
|
{
|
||||||
|
collapseButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
const navLogo = document.querySelector("#navLogo");
|
||||||
|
if(navLogo)
|
||||||
|
{
|
||||||
|
navLogo.style.visibility = "visible";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function changeVersion()
|
||||||
|
{
|
||||||
|
document.location.href = document.getElementById("otherVersionsSelect").value;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2023. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#api-info
|
||||||
|
{
|
||||||
|
margin-left: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#api-info button
|
||||||
|
{
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#api-title span
|
||||||
|
{
|
||||||
|
font-size: 24px !important;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-scroll
|
||||||
|
{
|
||||||
|
padding-left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-description.expanded
|
||||||
|
{
|
||||||
|
max-height: initial !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-description .m-markdown p
|
||||||
|
{
|
||||||
|
margin-block-end: 0.5em !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
api-response
|
||||||
|
{
|
||||||
|
margin-bottom: 50vh;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#otherVersions
|
||||||
|
{
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navLogo
|
||||||
|
{
|
||||||
|
width: fit-content;
|
||||||
|
max-width: 280px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
Reference in New Issue
Block a user