Skip to content

Commit 27f31c3

Browse files
authored
Merge pull request #22 from qazsato/fix_resolve_ref
fix swagger $ref resolve error
2 parents af34300 + c894195 commit 27f31c3

8 files changed

Lines changed: 272 additions & 62 deletions

File tree

package-lock.json

Lines changed: 15 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "openapi-generate-html",
3-
"version": "0.4.3",
3+
"version": "0.4.4",
44
"description": "Generate standalone HTML from OpenAPI Specification",
55
"type": "module",
66
"bin": {
@@ -24,9 +24,10 @@
2424
"author": "qazsato <qazsato@gmail.com>",
2525
"license": "MIT",
2626
"dependencies": {
27-
"@apidevtools/json-schema-ref-parser": "^11.7.2",
27+
"@apidevtools/json-schema-ref-parser": "^14.1.0",
2828
"commander": "^12.1.0",
2929
"ejs": "^3.1.10",
30+
"fast-safe-stringify": "^2.1.1",
3031
"inquirer": "^12.0.0",
3132
"js-yaml": "^4.1.0"
3233
},

resources/swagger/template.ejs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
<meta charset="UTF-8">
66
<meta name="viewport" content="width=device-width, initial-scale=1.0">
77
<meta name="description" content="<%= description %>">
8-
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5.11.0/swagger-ui.css" />
8+
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5.26.2/swagger-ui.css" />
99
<style><%- cssContent %></style>
1010
<script>window.apiDocs = <%- apiDocs %></script>
1111
</head>
1212
<body>
1313
<div id="swagger-ui"></div>
14-
<script src="https://unpkg.com/swagger-ui-dist@5.11.0/swagger-ui-bundle.js" crossorigin></script>
14+
<script src="https://unpkg.com/swagger-ui-dist@5.26.2/swagger-ui-bundle.js" crossorigin></script>
1515
<script><%- jsContent %></script>
1616
</body>
1717
</html>

src/constants/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1-
export const UI = ['stoplight', 'swagger', 'redoc']
1+
export const UI = {
2+
STOPLIGHT: 'stoplight',
3+
SWAGGER: 'swagger',
4+
REDOC: 'redoc',
5+
}
26
export const THEME = ['light', 'dark']
37
export const ENABLE_INPUT_EXTS = ['.json', '.yaml', '.yml']

src/index.js

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@
22
import { program } from 'commander'
33
import inquirer from 'inquirer'
44
import fs from 'fs'
5-
import yaml from 'js-yaml'
65
import ejs from 'ejs'
76
import path from 'path'
87
import { fileURLToPath } from 'url'
9-
import $RefParser from '@apidevtools/json-schema-ref-parser'
108
import { UI } from './constants/index.js'
119
import {
1210
validateCommandInput,
@@ -16,9 +14,8 @@ import {
1614
validateInquirerInput,
1715
validateInquirerOutput,
1816
isValidUrl,
19-
isJSON,
20-
isYAML,
2117
} from './utils/validate.js'
18+
import { parseOpenApi } from './utils/parser.js'
2219

2320
const __filename = fileURLToPath(import.meta.url)
2421
const __dirname = path.dirname(__filename)
@@ -50,7 +47,11 @@ function getCliOptions() {
5047
'Output HTML file name',
5148
validateCommandOutput,
5249
)
53-
.option('--ui <ui>', `Choose UI (${UI.join(', ')})`, validateCommandUi)
50+
.option(
51+
'--ui <ui>',
52+
`Choose UI (${Object.values(UI).join(', ')})`,
53+
validateCommandUi,
54+
)
5455
.option('--title <title>', 'Title of the HTML page', 'OpenAPI Docs')
5556
.option('--description <description>', 'Description of the HTML page', '')
5657
.option(
@@ -68,8 +69,8 @@ async function askQuestions(options) {
6869
type: 'list',
6970
name: 'ui',
7071
message: 'Which UI would you like to use?',
71-
default: UI[0],
72-
choices: UI,
72+
default: UI.STOPLIGHT,
73+
choices: Object.values(UI),
7374
when: !options.ui,
7475
},
7576
{
@@ -114,29 +115,15 @@ async function renderOpenApiHtml(result) {
114115
} else {
115116
rawApiDocsText = fs.readFileSync(input, 'utf-8')
116117
}
117-
118-
let rawApiDocs
119-
if (isJSON(rawApiDocsText)) {
120-
rawApiDocs = JSON.parse(rawApiDocsText)
121-
} else if (isYAML(rawApiDocsText)) {
122-
rawApiDocs = yaml.load(rawApiDocsText)
123-
} else {
124-
throw new Error(
125-
'Unsupported file format. Please provide a .json or .yaml/.yml file.',
126-
)
127-
}
128-
129-
// resolve $ref pointers
130-
// https://github.com/APIDevTools/json-schema-ref-parser/blob/main/docs/ref-parser.md#bundleschema-options-callback
131-
const apiDocs = await $RefParser.bundle(rawApiDocs)
118+
const apiDocs = await parseOpenApi(rawApiDocsText, ui)
132119

133120
return ejs.render(template, {
134121
theme: result.theme,
135122
title: result.title,
136123
description: result.description,
137124
jsContent,
138125
cssContent,
139-
apiDocs: JSON.stringify(apiDocs),
126+
apiDocs,
140127
})
141128
}
142129

src/utils/parser.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import $RefParser from '@apidevtools/json-schema-ref-parser'
2+
import stringify from 'fast-safe-stringify'
3+
import yaml from 'js-yaml'
4+
import { UI } from '../constants/index.js'
5+
6+
export async function parseOpenApi(rawApiDocsText, ui) {
7+
let rawApiDocs
8+
if (isJSON(rawApiDocsText)) {
9+
rawApiDocs = JSON.parse(rawApiDocsText)
10+
} else if (isYAML(rawApiDocsText)) {
11+
rawApiDocs = yaml.load(rawApiDocsText)
12+
} else {
13+
throw new Error(
14+
'Unsupported file format. Please provide a .json or .yaml/.yml file.',
15+
)
16+
}
17+
// resolve $ref pointers
18+
if (ui === UI.SWAGGER) {
19+
// https://github.com/APIDevTools/json-schema-ref-parser/blob/main/docs/ref-parser.md#dereferenceschema-options-callback
20+
const apiDocs = await $RefParser.dereference(rawApiDocs)
21+
return stringify(apiDocs)
22+
}
23+
// https://github.com/APIDevTools/json-schema-ref-parser/blob/main/docs/ref-parser.md#bundleschema-options-callback
24+
const apiDocs = await $RefParser.bundle(rawApiDocs)
25+
return JSON.stringify(apiDocs)
26+
}
27+
28+
function isJSON(string) {
29+
try {
30+
JSON.parse(string)
31+
return true
32+
} catch {
33+
return false
34+
}
35+
}
36+
37+
function isYAML(string) {
38+
try {
39+
yaml.load(string)
40+
return true
41+
} catch {
42+
return false
43+
}
44+
}

0 commit comments

Comments
 (0)