90 lines
2.7 KiB
TypeScript
90 lines
2.7 KiB
TypeScript
import type { Env, MiddlewareHandler } from 'hono'
|
|
import { html } from 'hono/html'
|
|
import type { DistSwaggerUIOptions } from './swagger/renderer'
|
|
import { renderSwaggerUIOptions } from './swagger/renderer'
|
|
import type { AssetURLs } from './swagger/resource'
|
|
import { remoteAssets } from './swagger/resource'
|
|
|
|
type OriginalSwaggerUIOptions = {
|
|
version?: string
|
|
/**
|
|
* manuallySwaggerUIHtml is a string that is used to render SwaggerUI.
|
|
* If this is set, all other options will be ignored except version.
|
|
* The string will be inserted into the body of the HTML.
|
|
* This is useful when you want to fully customize the UI.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* const swaggerUI = SwaggerUI({
|
|
* manuallySwaggerUIHtml: (asset) => `
|
|
* <div>
|
|
* <div id="swagger-ui"></div>
|
|
* ${asset.css.map((url) => `<link rel="stylesheet" href="${url}" />`)}
|
|
* ${asset.js.map((url) => `<script src="${url}" crossorigin="anonymous"></script>`)}
|
|
* <script>
|
|
* window.onload = () => {
|
|
* window.ui = SwaggerUIBundle({
|
|
* dom_id: '#swagger-ui',
|
|
* url: 'https://petstore.swagger.io/v2/swagger.json',
|
|
* })
|
|
* }
|
|
* </script>
|
|
* </div>
|
|
* `,
|
|
* })
|
|
* ```
|
|
*/
|
|
manuallySwaggerUIHtml?: (asset: AssetURLs) => string
|
|
title?: string
|
|
}
|
|
|
|
type SwaggerUIOptions = OriginalSwaggerUIOptions & DistSwaggerUIOptions
|
|
|
|
const SwaggerUI = (options: SwaggerUIOptions): string => {
|
|
const asset = remoteAssets({ version: options?.version })
|
|
delete options.version
|
|
|
|
if (options.manuallySwaggerUIHtml) {
|
|
return options.manuallySwaggerUIHtml(asset)
|
|
}
|
|
|
|
const optionsStrings = renderSwaggerUIOptions(options)
|
|
|
|
return `
|
|
<div>
|
|
<div id="swagger-ui"></div>
|
|
${asset.css.map((url) => html`<link rel="stylesheet" href="${url}" />`)}
|
|
${asset.js.map((url) => html`<script src="${url}" crossorigin="anonymous"></script>`)}
|
|
<script>
|
|
window.onload = () => {
|
|
window.ui = SwaggerUIBundle({
|
|
dom_id: '#swagger-ui',${optionsStrings},
|
|
})
|
|
}
|
|
</script>
|
|
</div>
|
|
`
|
|
}
|
|
|
|
const middleware =
|
|
<E extends Env>(options: SwaggerUIOptions): MiddlewareHandler<E> =>
|
|
async (c) => {
|
|
const title = options?.title ?? 'SwaggerUI'
|
|
return c.html(/* html */ `
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<meta name="description" content="SwaggerUI" />
|
|
<title>${title}</title>
|
|
</head>
|
|
<body>
|
|
${SwaggerUI(options)}
|
|
</body>
|
|
</html>
|
|
`)
|
|
}
|
|
|
|
export { middleware as swaggerUI, SwaggerUI }
|
|
export { SwaggerUIOptions }
|