Skip to content

Commit

Permalink
Merge pull request #3199 from alexander-klimov/add-redoc-feat-and-the…
Browse files Browse the repository at this point in the history
…me-options

Add Redoc feature and theming options for API documentation
  • Loading branch information
adamw authored Sep 25, 2023
2 parents 855ef8d + 5affe52 commit 3e3c98d
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 30 deletions.
70 changes: 43 additions & 27 deletions docs/redoc/src/main/scala/sttp/tapir/redoc/Redoc.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,42 @@ object Redoc {

val defaultRedocVersion = "2.0.0-rc.56"

def redocHtml(title: String, specUrl: String, redocVersion: String = defaultRedocVersion): String = s"""
|<!DOCTYPE html>
|<html>
|<head>
| <title>$title</title>
| <!-- needed for adaptive design -->
| <meta charset="utf-8"/>
| <meta name="viewport" content="width=device-width, initial-scale=1">
| <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
| <!--
| ReDoc doesn't change outer page styles
| -->
| <style>
| body {
| margin: 0;
| padding: 0;
| }
| </style>
|</head>
|<body>
|<redoc spec-url='$specUrl' expand-responses="200,201"></redoc>
|<script src="https://cdn.jsdelivr.net/npm/redoc@$redocVersion/bundles/redoc.standalone.js"></script>
|</body>
|</html>
|""".stripMargin
def redocHtml(
title: String,
specUrl: String,
redocVersion: String = defaultRedocVersion,
redocOptions: Option[String] = None,
redocThemeOptionsJson: Option[String] = None
): String = {
val options = redocOptions.filterNot(_.isEmpty).getOrElse("")
val themeOptions = redocThemeOptionsJson.filterNot(_.isEmpty).fold("")(json => s"theme='$json'")
s"""
|<!DOCTYPE html>
|<html>
|<head>
| <title>$title</title>
| <!-- needed for adaptive design -->
| <meta charset="utf-8"/>
| <meta name="viewport" content="width=device-width, initial-scale=1">
| <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
| <!--
| ReDoc doesn't change outer page styles
| -->
| <style>
| body {
| margin: 0;
| padding: 0;
| }
| </style>
|</head>
|<body>
| <redoc spec-url='$specUrl' expand-responses="200,201" $options $themeOptions></redoc>
| <script src="https://cdn.jsdelivr.net/npm/redoc@$redocVersion/bundles/redoc.standalone.js"></script>
|</body>
|</html>
|""".stripMargin
}

def apply[F[_]](
title: String,
Expand All @@ -60,7 +70,13 @@ object Redoc {
val specEndpoint = contentEndpoint(specName, specMediaType).serverLogicPure[F](_ => Right(spec))

val specPrefix = if (options.useRelativePaths) "." else "/" + (options.contextPath ++ options.pathPrefix).mkString("/")
val html: String = redocHtml(title, s"$specPrefix/$specName", options.redocVersion)
val html: String = redocHtml(
title,
s"$specPrefix/$specName",
options.redocVersion,
options.redocOptions,
options.redocThemeOptionsJson
)
val htmlEndpoint = contentEndpoint(htmlName, MediaType.TextHtml).serverLogicPure[F](_ => Right(html))

val lastSegmentInput: EndpointInput[Option[String]] = extractFromRequest(_.uri.path.lastOption)
Expand Down
15 changes: 12 additions & 3 deletions docs/redoc/src/main/scala/sttp/tapir/redoc/RedocUIOptions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,33 @@ package sttp.tapir.redoc
* Should relative paths be used for yaml references and redirects. Defaults to `true`.
* @param redocVersion
* Version of Redoc library
* @param redocOptions
* Options to pass to the Redoc library (see https://redocly.com/docs/api-reference-docs/configuration/functionality/)
* @param redocThemeOptionsJson
* Theming options to pass to the Redoc library (see https://redocly.com/docs/api-reference-docs/configuration/theming/). Must be a valid JSON if not empty
*/
case class RedocUIOptions(
pathPrefix: List[String],
specName: String,
htmlName: String,
contextPath: List[String],
useRelativePaths: Boolean,
redocVersion: String
redocVersion: String,
redocOptions: Option[String],
redocThemeOptionsJson: Option[String]
) {
def pathPrefix(pathPrefix: List[String]): RedocUIOptions = copy(pathPrefix = pathPrefix)
def specName(specName: String): RedocUIOptions = copy(specName = specName)
def htmlName(htmlName: String): RedocUIOptions = copy(htmlName = htmlName)
def contextPath(contextPath: List[String]): RedocUIOptions = copy(contextPath = contextPath)
def withRelativePaths: RedocUIOptions = copy(useRelativePaths = true)
def withAbsolutePaths: RedocUIOptions = copy(useRelativePaths = false)
def redocVersion(redocVersion: String): RedocUIOptions = copy(redocVersion = redocVersion)
def redocVersion(redocVersion: String): RedocUIOptions = copy(redocVersion = redocVersion)
def redocOptions(redocOptions: String): RedocUIOptions = copy(redocOptions = Some(redocOptions))
def redocThemeOptionsJson(redocThemeOptionsJson: String): RedocUIOptions =
copy(redocThemeOptionsJson = Some(redocThemeOptionsJson))
}

object RedocUIOptions {
val default: RedocUIOptions = RedocUIOptions(List("docs"), "docs.yaml", "index.html", Nil, useRelativePaths = true, "2.0.0-rc.56")
val default: RedocUIOptions = RedocUIOptions(List("docs"), "docs.yaml", "index.html", Nil, useRelativePaths = true, "2.0.0-rc.56", None, None)
}

0 comments on commit 3e3c98d

Please sign in to comment.