Skip to content

Commit

Permalink
feat: introduce Swagger Editor middleware (#800)
Browse files Browse the repository at this point in the history
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
OgabekYuldoshev and yusukebe authored Nov 5, 2024
1 parent 2c0c41f commit 5fd8026
Show file tree
Hide file tree
Showing 11 changed files with 670 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/tender-candles-laugh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hono/swagger-editor': major
---

Create swagger editor middleware for hono
25 changes: 25 additions & 0 deletions .github/workflows/ci-swagger-editor.yml
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"build:zod-openapi": "yarn workspace @hono/zod-openapi install && yarn workspace @hono/zod-openapi build",
"build:typia-validator": "yarn workspace @hono/typia-validator build",
"build:swagger-ui": "yarn workspace @hono/swagger-ui build",
"build:swagger-editor": "yarn workspace @hono/swagger-editor build",
"build:esbuild-transpiler": "yarn workspace @hono/esbuild-transpiler build",
"build:event-emitter": "yarn workspace @hono/event-emitter build",
"build:oauth-providers": "yarn workspace @hono/oauth-providers build",
Expand Down
40 changes: 40 additions & 0 deletions packages/swagger-editor/README.md
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
48 changes: 48 additions & 0 deletions packages/swagger-editor/package.json
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"
}
}
195 changes: 195 additions & 0 deletions packages/swagger-editor/src/index.ts
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>
`)
}
Loading

0 comments on commit 5fd8026

Please sign in to comment.