-
Notifications
You must be signed in to change notification settings - Fork 191
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: introduce Swagger Editor middleware (#800)
Closes honojs/hono#1415 * chore(swagger-editor): 🔨 init * ci: 🎡 swagger editor workflow create workflow for swagger-editor package * docs: 📝 readme have writed documentation * test(test): ✅ create test for swagger-editor middleware * fix(swagger-editor): 🐛 fixed cdn url in html content * chore: 🔨 v0.1.0 release * format * fix the typos * remove unnecessary `.` * remove unnecessay `vite` and fix the `vitest.config.ts` * fix the relase workflow * update the changeset and `package.json` --------- Co-authored-by: Yusuke Wada <yusuke@kamawada.com>
- Loading branch information
1 parent
2c0c41f
commit 5fd8026
Showing
11 changed files
with
670 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@hono/swagger-editor': major | ||
--- | ||
|
||
Create swagger editor middleware for hono |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
name: ci-swagger-editor | ||
on: | ||
push: | ||
branches: [main] | ||
paths: | ||
- 'packages/swagger-editor/**' | ||
pull_request: | ||
branches: ['*'] | ||
paths: | ||
- 'packages/swagger-editor/**' | ||
|
||
jobs: | ||
ci: | ||
runs-on: ubuntu-latest | ||
defaults: | ||
run: | ||
working-directory: ./packages/swagger-editor | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-node@v4 | ||
with: | ||
node-version: 20.x | ||
- run: yarn install --frozen-lockfile | ||
- run: yarn build | ||
- run: yarn test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# Swagger Editor Middleware for Hono | ||
|
||
This library, `@hono/swagger-editor` is the middleware for integrating Swagger Editor with Hono applications. The Swagger Editor is an open source editor to design, define and document RESTful APIs in the Swagger Specification. | ||
|
||
## Installation | ||
|
||
```bash | ||
npm install @hono/swagger-editor | ||
# or | ||
yarn add @hono/swagger-editor | ||
``` | ||
|
||
## Usage | ||
|
||
You can use the `swaggerEditor` middleware to serve Swagger Editor on a specific route in your Hono application. Here's how you can do it: | ||
|
||
|
||
```ts | ||
import { Hono } from 'hono' | ||
import { swaggerUI } from '@hono/swagger-ui' | ||
|
||
const app = new Hono() | ||
|
||
// Use the middleware to serve Swagger Editor at /swagger-editor | ||
app.get('/swagger-editor', swaggerEditor({ url: '/doc' })) | ||
|
||
export default app | ||
``` | ||
|
||
## Options | ||
|
||
Middleware supports almost all swagger-editor options. See full documentation: <https://swagger.io/docs/open-source-tools/swagger-editor/> | ||
|
||
## Authors | ||
|
||
- Ogabek Yuldoshev <https://github.com/OgabekYuldoshev> | ||
|
||
## License | ||
|
||
MIT |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
{ | ||
"name": "@hono/swagger-editor", | ||
"version": "0.0.0", | ||
"description": "A middleware for using Swagger Editor in Hono", | ||
"type": "module", | ||
"main": "dist/index.cjs", | ||
"module": "dist/index.js", | ||
"types": "dist/index.d.cts", | ||
"exports": { | ||
".": { | ||
"import": { | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.js" | ||
}, | ||
"require": { | ||
"types": "./dist/index.d.cts", | ||
"default": "./dist/index.cjs" | ||
} | ||
} | ||
}, | ||
"files": [ | ||
"dist" | ||
], | ||
"scripts": { | ||
"test": "vitest run", | ||
"build": "tsup ./src/index.ts --format esm,cjs --dts", | ||
"prerelease": "yarn build && yarn test", | ||
"release": "yarn publish" | ||
}, | ||
"license": "MIT", | ||
"publishConfig": { | ||
"registry": "https://registry.npmjs.org", | ||
"access": "public" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/honojs/middleware.git" | ||
}, | ||
"homepage": "https://github.com/honojs/middleware", | ||
"peerDependencies": { | ||
"hono": "*" | ||
}, | ||
"devDependencies": { | ||
"hono": "^3.11.7", | ||
"tsup": "^7.2.0", | ||
"vitest": "^0.34.5" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
import type { Context } from 'hono' | ||
import type { CustomSwaggerUIOptions } from './types' | ||
|
||
const DEFAULT_VERSION = '4.13.1' | ||
|
||
const CDN_LINK = 'https://cdn.jsdelivr.net/npm/swagger-editor-dist' | ||
|
||
export const MODERN_NORMALIZE_CSS = ` | ||
*, | ||
::before, | ||
::after { | ||
box-sizing: border-box; | ||
} | ||
html { | ||
font-family: | ||
system-ui, | ||
'Segoe UI', | ||
Roboto, | ||
Helvetica, | ||
Arial, | ||
sans-serif, | ||
'Apple Color Emoji', | ||
'Segoe UI Emoji'; | ||
line-height: 1.15; /* 1. Correct the line height in all browsers. */ | ||
-webkit-text-size-adjust: 100%; /* 2. Prevent adjustments of font size after orientation changes in iOS. */ | ||
tab-size: 4; /* 3. Use a more readable tab size (opinionated). */ | ||
} | ||
body { | ||
margin: 0; | ||
} | ||
b, | ||
strong { | ||
font-weight: bolder; | ||
} | ||
code, | ||
kbd, | ||
samp, | ||
pre { | ||
font-family: | ||
ui-monospace, | ||
SFMono-Regular, | ||
Consolas, | ||
'Liberation Mono', | ||
Menlo, | ||
monospace; /* 1 */ | ||
font-size: 1em; /* 2 */ | ||
} | ||
small { | ||
font-size: 80%; | ||
} | ||
sub, | ||
sup { | ||
font-size: 75%; | ||
line-height: 0; | ||
position: relative; | ||
vertical-align: baseline; | ||
} | ||
sub { | ||
bottom: -0.25em; | ||
} | ||
sup { | ||
top: -0.5em; | ||
} | ||
table { | ||
border-color: currentcolor; | ||
} | ||
button, | ||
input, | ||
optgroup, | ||
select, | ||
textarea { | ||
font-family: inherit; /* 1 */ | ||
font-size: 100%; /* 1 */ | ||
line-height: 1.15; /* 1 */ | ||
margin: 0; /* 2 */ | ||
} | ||
button, | ||
[type='button'], | ||
[type='reset'], | ||
[type='submit'] { | ||
-webkit-appearance: button; | ||
} | ||
legend { | ||
padding: 0; | ||
} | ||
progress { | ||
vertical-align: baseline; | ||
} | ||
::-webkit-inner-spin-button, | ||
::-webkit-outer-spin-button { | ||
height: auto; | ||
} | ||
[type='search'] { | ||
-webkit-appearance: textfield; /* 1 */ | ||
outline-offset: -2px; /* 2 */ | ||
} | ||
::-webkit-search-decoration { | ||
-webkit-appearance: none; | ||
} | ||
::-webkit-file-upload-button { | ||
-webkit-appearance: button; /* 1 */ | ||
font: inherit; /* 2 */ | ||
} | ||
summary { | ||
display: list-item; | ||
} | ||
.Pane2 { | ||
overflow-y: scroll; | ||
} | ||
` | ||
|
||
function getUrl(version?: string) { | ||
return `${CDN_LINK}@${version ? version : DEFAULT_VERSION}` | ||
} | ||
|
||
export interface SwaggerEditorOptions extends CustomSwaggerUIOptions { | ||
version?: string | ||
} | ||
|
||
export function swaggerEditor(options: SwaggerEditorOptions = {}) { | ||
const url = getUrl() | ||
|
||
options.layout = 'StandaloneLayout' | ||
|
||
const optionString = Object.entries(options) | ||
.map(([key, value]) => { | ||
if (typeof value === 'string') { | ||
return `${key}:'${value}'` | ||
} | ||
if (Array.isArray(value)) { | ||
return `${key}:${value.map((v) => `${v}`).join(', ')}` | ||
} | ||
if (typeof value === 'object') { | ||
return `${key}:${JSON.stringify(value)}` | ||
} | ||
|
||
return `${key}: ${value}` | ||
}) | ||
.join(',') | ||
|
||
return async (c: Context) => | ||
c.html(` | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<title>Swagger Editor</title> | ||
<style> | ||
${MODERN_NORMALIZE_CSS} | ||
</style> | ||
<link href="${url}/swagger-editor.css" rel="stylesheet"> | ||
<link rel="icon" type="image/png" href="${url}/favicon-32x32.png" sizes="32x32" /> | ||
<link rel="icon" type="image/png" href="${url}/favicon-16x16.png" sizes="16x16" /> | ||
</head> | ||
<body> | ||
<div id="swagger-editor"></div> | ||
<script src="${url}/swagger-editor-bundle.js"> </script> | ||
<script src="${url}/swagger-editor-standalone-preset.js"> </script> | ||
<script> | ||
window.onload = function() { | ||
const editor = SwaggerEditorBundle({ | ||
dom_id: '#swagger-editor', | ||
presets: [ | ||
SwaggerEditorStandalonePreset | ||
], | ||
queryConfigEnabled: true, | ||
${optionString} | ||
}) | ||
window.editor = editor | ||
} | ||
</script> | ||
</body> | ||
</html> | ||
`) | ||
} |
Oops, something went wrong.