diff --git a/README.md b/README.md index 2b2ac94..6d8bf1b 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,13 @@ Then go to `http://localhost:8080/swagger`. # config +## provider +@default 'scalar' +Choose between [Scalar](https://swagger.io/specification/v2/) & [SwaggerUI](https://github.com/swagger-api/swagger-ui) + +## scalar +Customize scalarConfig, refers to [Scalar config](https://github.com/scalar/scalar) + ## swagger Customize Swagger config, refers to [Swagger 2.0 config](https://swagger.io/specification/v2/) diff --git a/bun.lockb b/bun.lockb index 831b74f..24ab1cf 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 24923cc..4c184c3 100644 --- a/package.json +++ b/package.json @@ -47,9 +47,10 @@ "typescript": "^5.0.4" }, "dependencies": { + "@scalar/api-reference": "^1.12.5", "@types/lodash.clonedeep": "^4.5.7", "@types/swagger-ui": "^3.52.2", "lodash.clonedeep": "^4.5.0", "openapi-types": "^12.1.3" } -} \ No newline at end of file +} diff --git a/src/index.ts b/src/index.ts index ad2a91c..10d2ebd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,7 @@ import { type Elysia, type InternalRoute } from 'elysia' import { filterPaths, registerSchemaPath } from './utils' import type { OpenAPIV3 } from 'openapi-types' +import type { ReferenceConfiguration } from '@scalar/api-reference' import type { ElysiaSwaggerConfig } from './types' import { SwaggerUIRender } from './swagger-ui' import { ScalarRender } from './scalar' @@ -18,6 +19,7 @@ export const swagger = { provider = 'scalar', scalarVersion = '1.12.5', + scalarConfig = {}, documentation = {}, version = '5.9.0', excludeStaticFile = true, @@ -29,6 +31,7 @@ export const swagger = }: ElysiaSwaggerConfig = { provider: 'scalar', scalarVersion: '1.12.5', + scalarConfig: {}, documentation: {}, version: '5.9.0', excludeStaticFile: true, @@ -71,8 +74,15 @@ export const swagger = } ) + const scalarConfiguration: ReferenceConfiguration = { + spec: { + url: `${relativePath}/json` + }, + ...scalarConfig + } - return new Response(provider === 'swagger-ui' ? SwaggerUIRender(info, version, theme, stringifiedSwaggerOptions, autoDarkMode) : ScalarRender(`${relativePath}/json`, scalarVersion), + + return new Response(provider === 'swagger-ui' ? SwaggerUIRender(info, version, theme, stringifiedSwaggerOptions, autoDarkMode) : ScalarRender(scalarVersion, scalarConfiguration), { headers: { 'content-type': 'text/html; charset=utf8' diff --git a/src/scalar-elysia-theme.ts b/src/scalar-elysia-theme.ts index f7f5105..7cb59d1 100644 --- a/src/scalar-elysia-theme.ts +++ b/src/scalar-elysia-theme.ts @@ -1,6 +1,4 @@ -export default `:root { - --theme-font: "Inter", var(--system-fonts); -} +export default ` /* basic theme */ .light-mode { --theme-color-1: #2a2f45; @@ -43,6 +41,20 @@ export default `:root { --sidebar-search-border-color: var(--theme-border-color); --sidebar-search--color: var(--theme-color-3); } +/* Document header only shows on mobile*/ +.dark-mode .t-doc__header, +.light-mode .t-doc__header { + --header-background-1: rgba(255, 255, 255, 0.85); + --header-border-color: transparent; + --header-color-1: var(--theme-color-1); + --header-color-2: var(--theme-color-2); + --header-background-toggle: var(--theme-color-3); + --header-call-to-action-color: var(--theme-color-accent); +} + +.dark-mode .t-doc__header { + --header-background-1: rgba(17, 23, 40, 0.75); +} /* advanced */ .light-mode { @@ -75,61 +87,7 @@ export default `:root { --theme-scrollbar-color: rgba(255, 255, 255, 0.24); --theme-scrollbar-color-active: rgba(255, 255, 255, 0.48); } -.section-container:first-of-type:after, -.section-container:first-of-type:before { - --stripes: repeating-linear-gradient( - 100deg, - #fff 0%, - #fff 0%, - transparent 2%, - transparent 12%, - #fff 17% - ); - --stripesDark: repeating-linear-gradient( - 100deg, - #000 0%, - #000 0%, - transparent 10%, - transparent 12%, - #000 17% - ); - --rainbow: repeating-linear-gradient( - 100deg, - #60a5fa 10%, - #e879f9 16%, - #5eead4 22%, - #60a5fa 30% - ); - content: ""; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - height: 200px; - background-image: var(--stripesDark), var(--rainbow); - background-size: 200%, 100%; - background-attachment: fixed; - mix-blend-mode: difference; - filter: opacity(10%) saturate(200%); - -webkit-mask-image: radial-gradient( - ellipse at 100% 0%, - black 40%, - transparent 75% - ); - mask-image: radial-gradient(ellipse at 100% 0%, black 40%, transparent 75%); - z-index: 0; - pointer-events: none; -} -.section-container:first-of-type:after { - mix-blend-mode: unset; -} -.light-mode .section-container:first-of-type:after, -.light-mode .section-container:first-of-type:before { - background-image: var(--stripes), var(--rainbow); - filter: opacity(4%) saturate(200%); - mix-blend-mode: unset; -} +/* Elysia Specific */ .scalar-api-client__send-request-button, .show-api-client-button { background: #3c82f6 !important; @@ -137,13 +95,7 @@ export default `:root { .show-api-client-button:before { display: none; } -.section-container .section:first-of-type { - border-bottom: 1px solid - var(--theme-border-color, var(--default-theme-border-color)); -} -.section-container[data-v-fcff76dc]:not(:first-of-type) { - border-top: none; -} + .sidebar-search:hover { transition: all 0.15s ease-in-out; --sidebar-search-border-color: var(--theme-color-accent) !important; @@ -152,4 +104,93 @@ export default `:root { .scalar-api-client__container .sidebar { --sidebar-border-color: var(--theme-border-color); } +@media (min-width: 1150px) { + .section-container:has( ~ .footer):before, + .tag-section-container:before { + content: ""; + position: absolute; + top: -5px; + left: 0; + width: 100%; + height: 10px; + background: linear-gradient(90deg, var(--theme-background-1) 3%,transparent 10%); + } +} +.section-flare { + position: absolute; + width: 100vw; + height: 300px; + --stripes: repeating-linear-gradient( + 100deg, + #fff 0%, + #fff 7%, + transparent 10%, + transparent 12%, + #fff 16% + ); + --stripesDark: repeating-linear-gradient( + 100deg, + #000 0%, + #000 7%, + transparent 10%, + transparent 12%, + #000 16% + ); + --rainbow: repeating-linear-gradient( + 100deg, + #60a5fa 10%, + #e879f9 16%, + #5eead4 22%, + #60a5fa 30% + ); + background-image: var(--stripes), var(--rainbow); + background-size: 300%, 200%; + background-position: 50% 50%, 50% 50%; + filter: invert(100%); + -webkit-mask-image: radial-gradient( + ellipse at 100% 0%, + black 40%, + transparent 70% + ); + mask-image: radial-gradient(ellipse at 100% 0%, black 40%, transparent 70%); + pointer-events: none; + opacity: 0.15; +} +.dark-mode .section-flare { + background-image: var(--stripesDark), var(--rainbow); + filter: opacity(50%) saturate(200%); + opacity: 0.25; +} +.section-flare:after { + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-image: var(--stripes), var(--rainbow); + background-size: 200%, 100%; + background-attachment: fixed; + mix-blend-mode: difference; +} +.dark-mode .section-flare:after { + background-image: var(--stripesDark), var(--rainbow); +} +@keyframes headerbackground { + from { + background: transparent; + backdrop-filter: none; + } + to { + background: var(--header-background-1); + backdrop-filter: blur(12px); + } +} +.light-mode .t-doc__header, +.dark-mode .t-doc__header { + animation: headerbackground forwards; + animation-timeline: scroll(); + animation-range: 0px 200px; + --header-border-color: transparent; +} ` \ No newline at end of file diff --git a/src/scalar.ts b/src/scalar.ts index e3f26de..ef70de8 100644 --- a/src/scalar.ts +++ b/src/scalar.ts @@ -1,6 +1,7 @@ +import type { ReferenceConfiguration } from '@scalar/api-reference' import scalarElysiaTheme from './scalar-elysia-theme' -export const ScalarRender = (specUrl: string, version: string, customCss?: string) => ` +export const ScalarRender = (version: string, config: ReferenceConfiguration) => ` API Reference @@ -14,13 +15,13 @@ export const ScalarRender = (specUrl: string, version: string, customCss?: strin } + data-url="${config.spec?.url}"> ` \ No newline at end of file diff --git a/src/types.ts b/src/types.ts index 1ea054c..9ca1876 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,6 +1,6 @@ import type { OpenAPIV3 } from 'openapi-types' import type { SwaggerUIOptions } from 'swagger-ui' - +import type { ReferenceConfiguration } from '@scalar/api-reference' export type SwaggerInfo = { title: string @@ -34,6 +34,13 @@ export interface ElysiaSwaggerConfig { * @see https://github.com/scalar/scalar */ scalarVersion?: string + /** + * Scalar configuration to customize scalar + * + * @default '1.12.5' + * @see https://github.com/scalar/scalar + */ + scalarConfig?: ReferenceConfiguration /** * Version to use for swagger cdn bundle *