@scalar/openapi-to-markdown 1.5.3 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +27 -1
- package/dist/create-markdown-from-openapi.d.ts +5 -2
- package/dist/create-markdown-from-openapi.d.ts.map +1 -1
- package/dist/create-markdown-from-openapi.js +7 -3
- package/dist/document-anchors.d.ts.map +1 -1
- package/dist/document-anchors.js +4 -2
- package/dist/document-examples.d.ts.map +1 -1
- package/dist/document-examples.js +10 -5
- package/dist/get-markdown-examples.d.ts.map +1 -1
- package/dist/get-markdown-examples.js +48 -24
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/load-document.d.ts +8 -1
- package/dist/load-document.d.ts.map +1 -1
- package/dist/load-document.js +34 -23
- package/dist/markdown/index.d.ts +5 -0
- package/dist/markdown/index.d.ts.map +1 -0
- package/dist/markdown/index.js +4 -0
- package/dist/markdown-nodes.d.ts.map +1 -1
- package/dist/markdown-nodes.js +1 -0
- package/dist/parse-description.d.ts.map +1 -1
- package/dist/parse-description.js +36 -18
- package/dist/render-document.d.ts.map +1 -1
- package/dist/render-document.js +50 -26
- package/dist/render-examples.d.ts.map +1 -1
- package/dist/render-examples.js +8 -4
- package/dist/render-operation-details.d.ts.map +1 -1
- package/dist/render-operation-details.js +28 -14
- package/dist/render-operation.d.ts.map +1 -1
- package/dist/render-operation.js +60 -31
- package/dist/render-schema.d.ts.map +1 -1
- package/dist/render-schema.js +145 -77
- package/dist/render-security.d.ts.map +1 -1
- package/dist/render-security.js +12 -6
- package/dist/render-tags.d.ts +7 -0
- package/dist/render-tags.d.ts.map +1 -0
- package/dist/render-tags.js +73 -0
- package/dist/restore-boolean-schemas.d.ts.map +1 -1
- package/dist/restore-boolean-schemas.js +22 -11
- package/dist/select-document.d.ts.map +1 -1
- package/dist/select-document.js +5 -1
- package/package.json +14 -9
|
@@ -10,8 +10,9 @@ const clean = (node) => {
|
|
|
10
10
|
node.url = safeUrl(node.url);
|
|
11
11
|
}
|
|
12
12
|
if ('children' in node) {
|
|
13
|
-
for (const child of node.children)
|
|
13
|
+
for (const child of node.children) {
|
|
14
14
|
clean(child);
|
|
15
|
+
}
|
|
15
16
|
// The filter preserves the parent's existing child types.
|
|
16
17
|
const previousLength = node.children.length;
|
|
17
18
|
node.children = node.children.filter((child) => child.type !== 'image' &&
|
|
@@ -33,10 +34,12 @@ const clean = (node) => {
|
|
|
33
34
|
if (node.children.length !== previousLength) {
|
|
34
35
|
const first = node.children.at(0);
|
|
35
36
|
const last = node.children.at(-1);
|
|
36
|
-
if (first?.type === 'text')
|
|
37
|
+
if (first?.type === 'text') {
|
|
37
38
|
first.value = first.value.trimStart();
|
|
38
|
-
|
|
39
|
+
}
|
|
40
|
+
if (last?.type === 'text') {
|
|
39
41
|
last.value = last.value.trimEnd();
|
|
42
|
+
}
|
|
40
43
|
}
|
|
41
44
|
}
|
|
42
45
|
delete node.position;
|
|
@@ -47,24 +50,31 @@ const pruneDefinitions = (tree) => {
|
|
|
47
50
|
const footnotes = new Set();
|
|
48
51
|
const definitions = new Map(tree.children.filter((node) => node.type === 'footnoteDefinition').map((node) => [node.identifier, node]));
|
|
49
52
|
const collect = (node) => {
|
|
50
|
-
if (node.type === 'linkReference')
|
|
53
|
+
if (node.type === 'linkReference') {
|
|
51
54
|
links.add(node.identifier);
|
|
52
|
-
|
|
55
|
+
}
|
|
56
|
+
if (node.type === 'footnoteReference') {
|
|
53
57
|
footnotes.add(node.identifier);
|
|
54
|
-
|
|
58
|
+
}
|
|
59
|
+
if ('children' in node) {
|
|
55
60
|
node.children.forEach(collect);
|
|
61
|
+
}
|
|
56
62
|
};
|
|
57
63
|
tree.children.filter((node) => node.type !== 'footnoteDefinition').forEach(collect);
|
|
58
64
|
// Set iteration also visits footnotes discovered inside another footnote.
|
|
59
|
-
for (const identifier of footnotes)
|
|
65
|
+
for (const identifier of footnotes) {
|
|
60
66
|
definitions.get(identifier)?.children.forEach(collect);
|
|
67
|
+
}
|
|
61
68
|
tree.children = tree.children.filter((node) => {
|
|
62
|
-
if (node.type === 'definition')
|
|
69
|
+
if (node.type === 'definition') {
|
|
63
70
|
return links.has(node.identifier);
|
|
64
|
-
|
|
71
|
+
}
|
|
72
|
+
if (node.type === 'footnoteDefinition') {
|
|
65
73
|
return footnotes.has(node.identifier);
|
|
66
|
-
|
|
74
|
+
}
|
|
75
|
+
if (node.type === 'paragraph') {
|
|
67
76
|
return node.children.some((child) => child.type !== 'text' || child.value.trim());
|
|
77
|
+
}
|
|
68
78
|
return true;
|
|
69
79
|
});
|
|
70
80
|
};
|
|
@@ -78,8 +88,9 @@ export const createDescriptionParser = () => {
|
|
|
78
88
|
const cache = new Map();
|
|
79
89
|
const parse = async (value) => {
|
|
80
90
|
// Most schema descriptions are one plain sentence. Parsing them costs more than the page's other text.
|
|
81
|
-
if (isPlainText(value))
|
|
91
|
+
if (isPlainText(value)) {
|
|
82
92
|
return [{ type: 'paragraph', children: [{ type: 'text', value: value.trim() }] }];
|
|
93
|
+
}
|
|
83
94
|
const parsed = parser.parse(value);
|
|
84
95
|
// Raw HTML and GitHub alerts retain Scalar's existing conversion behavior.
|
|
85
96
|
const tree = containsHtml(parsed) || /^\s*>\s*\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION|SUCCESS)\]/im.test(value)
|
|
@@ -93,26 +104,31 @@ export const createDescriptionParser = () => {
|
|
|
93
104
|
const copy = { ...node };
|
|
94
105
|
if ('identifier' in copy) {
|
|
95
106
|
copy.identifier = `${prefix}${copy.identifier}`;
|
|
96
|
-
if ('label' in copy)
|
|
107
|
+
if ('label' in copy) {
|
|
97
108
|
copy.label = copy.identifier;
|
|
98
|
-
|
|
109
|
+
}
|
|
110
|
+
if ('referenceType' in copy) {
|
|
99
111
|
copy.referenceType = 'full';
|
|
112
|
+
}
|
|
100
113
|
}
|
|
101
|
-
if ('children' in copy)
|
|
114
|
+
if ('children' in copy) {
|
|
102
115
|
copy.children = copy.children.map((child) => namespace(child, prefix));
|
|
116
|
+
}
|
|
103
117
|
return copy;
|
|
104
118
|
};
|
|
105
119
|
const hasReference = (node) => 'identifier' in node || ('children' in node && node.children.some(hasReference));
|
|
106
120
|
return () => {
|
|
107
121
|
const state = { nextId: 0 };
|
|
108
122
|
return async (value) => {
|
|
109
|
-
if (!value)
|
|
123
|
+
if (!value) {
|
|
110
124
|
return [];
|
|
125
|
+
}
|
|
111
126
|
const prefix = `description-${state.nextId++}-`;
|
|
112
127
|
const cached = cache.get(value) ?? parse(value);
|
|
113
128
|
if (!cache.has(value)) {
|
|
114
|
-
if (cache.size >= 8192)
|
|
129
|
+
if (cache.size >= 8192) {
|
|
115
130
|
cache.clear();
|
|
131
|
+
}
|
|
116
132
|
cache.set(value, cached);
|
|
117
133
|
}
|
|
118
134
|
const nodes = await cached;
|
|
@@ -127,10 +143,12 @@ export const expandDescriptions = async (nodes, description) => {
|
|
|
127
143
|
const found = [];
|
|
128
144
|
const collect = (siblings) => {
|
|
129
145
|
for (const node of siblings) {
|
|
130
|
-
if (node.type === 'descriptionPlaceholder')
|
|
146
|
+
if (node.type === 'descriptionPlaceholder') {
|
|
131
147
|
found.push({ siblings, node });
|
|
132
|
-
|
|
148
|
+
}
|
|
149
|
+
else if ('children' in node) {
|
|
133
150
|
collect(node.children);
|
|
151
|
+
}
|
|
134
152
|
}
|
|
135
153
|
};
|
|
136
154
|
collect(nodes);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-document.d.ts","sourceRoot":"","sources":["../src/render-document.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,eAAe,EAGhB,MAAM,8DAA8D,CAAA;
|
|
1
|
+
{"version":3,"file":"render-document.d.ts","sourceRoot":"","sources":["../src/render-document.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,eAAe,EAGhB,MAAM,8DAA8D,CAAA;AAerE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAwD7D,2FAA2F;AAC3F,eAAO,MAAM,sBAAsB,QAAO,CAAC,CACzC,QAAQ,EAAE,eAAe,EACzB,OAAO,CAAC,EAAE,oBAAoB,KAC3B,OAAO,CAAC,MAAM,CAAC,CAyRnB,CAAA"}
|
package/dist/render-document.js
CHANGED
|
@@ -12,20 +12,24 @@ import { renderExamples } from './render-examples.js';
|
|
|
12
12
|
import { formatOperationMethod, renderOperation } from './render-operation.js';
|
|
13
13
|
import { createSchemaRenderer } from './render-schema.js';
|
|
14
14
|
import { renderSecurity } from './render-security.js';
|
|
15
|
+
import { getTagSections } from './render-tags.js';
|
|
15
16
|
const serializer = unified()
|
|
16
17
|
.use(remarkGfm)
|
|
17
18
|
.use(remarkStringify, {
|
|
18
19
|
bullet: '-',
|
|
19
20
|
join: [
|
|
20
21
|
(left, right, parent) => {
|
|
21
|
-
if (!('spread' in parent))
|
|
22
|
+
if (!('spread' in parent)) {
|
|
22
23
|
return undefined;
|
|
24
|
+
}
|
|
23
25
|
// Inside a tight list item, content after a nested list would otherwise continue its last item.
|
|
24
|
-
if (left.type === 'list' && right.type !== 'list')
|
|
26
|
+
if (left.type === 'list' && right.type !== 'list') {
|
|
25
27
|
return 1;
|
|
28
|
+
}
|
|
26
29
|
// Code blocks in descriptions read better apart from the prose around them.
|
|
27
|
-
if (left.type === 'code' || right.type === 'code')
|
|
30
|
+
if (left.type === 'code' || right.type === 'code') {
|
|
28
31
|
return 1;
|
|
32
|
+
}
|
|
29
33
|
return undefined;
|
|
30
34
|
},
|
|
31
35
|
],
|
|
@@ -43,12 +47,14 @@ const renderShownModel = async (name, view, previous, description) => {
|
|
|
43
47
|
? [strong(text(view.title)), text(' ('), inlineCode(name), text(')')]
|
|
44
48
|
: [inlineCode(name)];
|
|
45
49
|
label.push(text(' — shown above'));
|
|
46
|
-
if (previous.name !== name)
|
|
50
|
+
if (previous.name !== name) {
|
|
47
51
|
label.push(text(' as '), inlineCode(previous.name));
|
|
52
|
+
}
|
|
48
53
|
label.push(text('.'));
|
|
49
54
|
const blocks = [paragraph(...label)];
|
|
50
|
-
if (view.description && view.description !== previous.description)
|
|
55
|
+
if (view.description && view.description !== previous.description) {
|
|
51
56
|
blocks.push(...(await description(view.description)));
|
|
57
|
+
}
|
|
52
58
|
return item(...blocks);
|
|
53
59
|
};
|
|
54
60
|
/** Build Markdown directly, retaining caches only for this immutable document snapshot. */
|
|
@@ -81,8 +87,9 @@ export const createDocumentRenderer = () => {
|
|
|
81
87
|
const entries = [];
|
|
82
88
|
for (const [path, reference] of Object.entries(group.paths ?? {})) {
|
|
83
89
|
const pathItem = getResolvedPathItem(reference);
|
|
84
|
-
if (!pathItem)
|
|
90
|
+
if (!pathItem) {
|
|
85
91
|
continue;
|
|
92
|
+
}
|
|
86
93
|
forEachPathItemOperation(reference, (method, operation) => {
|
|
87
94
|
const label = `${formatOperationMethod(method)} ${path}`;
|
|
88
95
|
entries.push({
|
|
@@ -107,8 +114,9 @@ export const createDocumentRenderer = () => {
|
|
|
107
114
|
const nodes = [];
|
|
108
115
|
const sections = [];
|
|
109
116
|
const flush = async () => {
|
|
110
|
-
if (!nodes.length)
|
|
117
|
+
if (!nodes.length) {
|
|
111
118
|
return;
|
|
119
|
+
}
|
|
112
120
|
const children = nodes.splice(0);
|
|
113
121
|
await expandDescriptions(children, description);
|
|
114
122
|
sections.push(serializer.stringify({ type: 'root', children }).trimEnd());
|
|
@@ -116,63 +124,73 @@ export const createDocumentRenderer = () => {
|
|
|
116
124
|
if (!single) {
|
|
117
125
|
const { info } = document;
|
|
118
126
|
const metadata = [field('OpenAPI Version', inlineCode(document.openapi))];
|
|
119
|
-
if (info.version)
|
|
127
|
+
if (info.version) {
|
|
120
128
|
metadata.push(field('API Version', inlineCode(info.version)));
|
|
121
|
-
|
|
129
|
+
}
|
|
130
|
+
if (info.termsOfService) {
|
|
122
131
|
metadata.push(field('Terms of service', link(info.termsOfService, info.termsOfService)));
|
|
132
|
+
}
|
|
123
133
|
if (info.contact) {
|
|
124
134
|
const contact = [text(info.contact.name ?? '')];
|
|
125
135
|
metadata.push(item(paragraph(strong(text('Contact:')), text(' '), ...contact, ...(info.contact.url ? [text(' '), link(info.contact.url, info.contact.url)] : []), ...(info.contact.email ? [text(' '), link(`mailto:${info.contact.email}`, info.contact.email)] : []))));
|
|
126
136
|
}
|
|
127
|
-
if (info.license)
|
|
137
|
+
if (info.license) {
|
|
128
138
|
metadata.push(field('License', info.license.url ? link(info.license.url, info.license.name ?? '') : text(info.license.name)));
|
|
139
|
+
}
|
|
129
140
|
nodes.push(heading(1, text(info.title)), list(metadata), ...(await description(info.description)));
|
|
130
141
|
if (whole) {
|
|
131
142
|
const contents = [];
|
|
132
143
|
for (const group of groups) {
|
|
133
|
-
if (!group.entries.length)
|
|
144
|
+
if (!group.entries.length) {
|
|
134
145
|
continue;
|
|
146
|
+
}
|
|
135
147
|
contents.push(paragraph(strong(text(group.title))), list(group.entries.map(({ id, label }) => item(paragraph(link(`#${encodeURIComponent(id)}`, label))))));
|
|
136
148
|
}
|
|
137
149
|
if (destinations?.size) {
|
|
138
150
|
contents.push(paragraph(strong(text('Schemas'))), list([...destinations].map(([name, url]) => item(paragraph(link(url, name))))));
|
|
139
151
|
}
|
|
140
|
-
if (contents.length)
|
|
152
|
+
if (contents.length) {
|
|
141
153
|
nodes.push(heading(2, text('Contents')), ...contents);
|
|
154
|
+
}
|
|
142
155
|
}
|
|
143
156
|
if (document.servers?.length || (whole && document.servers !== undefined)) {
|
|
144
|
-
if (documentContext?.servers)
|
|
157
|
+
if (documentContext?.servers) {
|
|
145
158
|
nodes.push(anchor(documentContext.servers));
|
|
159
|
+
}
|
|
146
160
|
nodes.push(heading(2, text('Servers')));
|
|
147
161
|
const effectiveServers = document.servers?.length
|
|
148
162
|
? document.servers
|
|
149
163
|
: [{ url: '/' }];
|
|
150
164
|
const servers = effectiveServers.map((server) => {
|
|
151
165
|
const nested = [];
|
|
152
|
-
if (server.description)
|
|
166
|
+
if (server.description) {
|
|
153
167
|
nested.push(field('Description', text(server.description)));
|
|
168
|
+
}
|
|
154
169
|
const variables = Object.entries(server.variables ?? {});
|
|
155
|
-
if (variables.length)
|
|
170
|
+
if (variables.length) {
|
|
156
171
|
nested.push(item(paragraph(strong(text('Variables:'))), list(variables.map(([name, variable]) => item(paragraph(inlineCode(name), text(' (default: '), inlineCode(variable.default), text(')'), ...(whole && variable.enum?.length
|
|
157
172
|
? [text(', possible values: '), inlineCode(variable.enum.join(', '))]
|
|
158
173
|
: []), text(variable.description ? `: ${variable.description}` : '')))))));
|
|
174
|
+
}
|
|
159
175
|
const entry = field('URL', inlineCode(server.url));
|
|
160
|
-
if (nested.length)
|
|
176
|
+
if (nested.length) {
|
|
161
177
|
entry.children.push(list(nested));
|
|
178
|
+
}
|
|
162
179
|
return entry;
|
|
163
180
|
});
|
|
164
181
|
nodes.push(list(servers));
|
|
165
182
|
}
|
|
166
|
-
if (documentContext?.authentication)
|
|
183
|
+
if (documentContext?.authentication) {
|
|
167
184
|
nodes.push(anchor(documentContext.authentication));
|
|
185
|
+
}
|
|
168
186
|
nodes.push(...(await renderSecurity(document.security, document.components?.securitySchemes, description, 2)));
|
|
169
187
|
if (document.tags?.length) {
|
|
170
188
|
nodes.push(heading(2, text('Tags')));
|
|
171
|
-
for (const tag of document.tags) {
|
|
172
|
-
const title = /^3\.2\./.test(openapiVersion) ? (tag.summary ?? tag.name) : tag.name;
|
|
189
|
+
for (const { tag, title } of getTagSections(document.tags, openapiVersion)) {
|
|
173
190
|
nodes.push(heading(3, text(title)), ...(await description(tag.description)));
|
|
174
|
-
if (tag.externalDocs)
|
|
191
|
+
if (tag.externalDocs) {
|
|
175
192
|
nodes.push(paragraph(link(tag.externalDocs.url, tag.externalDocs.description ?? tag.externalDocs.url)));
|
|
193
|
+
}
|
|
176
194
|
}
|
|
177
195
|
}
|
|
178
196
|
await flush();
|
|
@@ -180,12 +198,14 @@ export const createDocumentRenderer = () => {
|
|
|
180
198
|
for (const group of groups) {
|
|
181
199
|
let hasOperations = false;
|
|
182
200
|
for (const { path, pathItem, method, operation, id } of group.entries) {
|
|
183
|
-
if (!hasOperations && !single)
|
|
201
|
+
if (!hasOperations && !single) {
|
|
184
202
|
nodes.push(heading(2, text(group.title)));
|
|
203
|
+
}
|
|
185
204
|
hasOperations = true;
|
|
186
205
|
schemas.beginSection();
|
|
187
|
-
if (id)
|
|
206
|
+
if (id) {
|
|
188
207
|
nodes.push(anchor(id));
|
|
208
|
+
}
|
|
189
209
|
nodes.push(...(await renderOperation(document, path, method, pathItem, operation, group.webhook, {
|
|
190
210
|
description,
|
|
191
211
|
schemas,
|
|
@@ -201,11 +221,13 @@ export const createDocumentRenderer = () => {
|
|
|
201
221
|
const renderModel = async (name, schema, level) => {
|
|
202
222
|
const view = schemas.view(schema);
|
|
203
223
|
const summary = schemas.summarize(schema);
|
|
204
|
-
if (whole)
|
|
224
|
+
if (whole) {
|
|
205
225
|
nodes.push(anchor(anchors.get('schema', name)));
|
|
226
|
+
}
|
|
206
227
|
nodes.push(heading(level, text(view.title ?? name)));
|
|
207
|
-
if (summary.length)
|
|
228
|
+
if (summary.length) {
|
|
208
229
|
nodes.push(paragraph(strong(text('Type:')), text('\u00a0'), ...summary));
|
|
230
|
+
}
|
|
209
231
|
nodes.push(...(await description(view.description)), ...schemas.render(schema, 0, [], { hideDetails: true, name }));
|
|
210
232
|
if (view.type === 'object' || hasAuthoredExamples(view)) {
|
|
211
233
|
// A model page's own schema is bounded, so it gets a generated example even in linked mode.
|
|
@@ -224,13 +246,15 @@ export const createDocumentRenderer = () => {
|
|
|
224
246
|
await renderModel(selected[0], selected[1], 1);
|
|
225
247
|
}
|
|
226
248
|
const dependencies = models.filter(([name]) => name !== options.model);
|
|
227
|
-
if (dependencies.length)
|
|
249
|
+
if (dependencies.length) {
|
|
228
250
|
nodes.push(heading(2, text('Schemas')));
|
|
251
|
+
}
|
|
229
252
|
// Models the page already expanded cost one line each, grouped into a single list.
|
|
230
253
|
const shownAbove = [];
|
|
231
254
|
const flushShownAbove = () => {
|
|
232
|
-
if (shownAbove.length)
|
|
255
|
+
if (shownAbove.length) {
|
|
233
256
|
nodes.push(list(shownAbove.splice(0)));
|
|
257
|
+
}
|
|
234
258
|
};
|
|
235
259
|
for (const [name, schema] of dependencies) {
|
|
236
260
|
schemas.beginSection();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-examples.d.ts","sourceRoot":"","sources":["../src/render-examples.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAQ,WAAW,EAAE,MAAM,OAAO,CAAA;AAG9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,EAAE,KAAK,aAAa,EAAuB,MAAM,yBAAyB,CAAA;AAEjF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5D,+EAA+E;AAC/E,eAAO,MAAM,cAAc,GACzB,QAAQ,aAAa,EACrB,aAAa,iBAAiB,EAC9B,kBAA8B,EAC9B,OAAO,MAAM,GAAG,OAAO,EACvB,uBAAwB,EAExB,6BAAqC,EACrC,+BAIG;IACD,yFAAyF;IACzF,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,gFAAgF;IAChF,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,oFAAoF;IACpF,QAAQ,CAAC,EAAE,gBAAgB,CAAA;CACvB,KACL,OAAO,CAAC,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"render-examples.d.ts","sourceRoot":"","sources":["../src/render-examples.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAQ,WAAW,EAAE,MAAM,OAAO,CAAA;AAG9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,EAAE,KAAK,aAAa,EAAuB,MAAM,yBAAyB,CAAA;AAEjF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5D,+EAA+E;AAC/E,eAAO,MAAM,cAAc,GACzB,QAAQ,aAAa,EACrB,aAAa,iBAAiB,EAC9B,kBAA8B,EAC9B,OAAO,MAAM,GAAG,OAAO,EACvB,uBAAwB,EAExB,6BAAqC,EACrC,+BAIG;IACD,yFAAyF;IACzF,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,gFAAgF;IAChF,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,oFAAoF;IACpF,QAAQ,CAAC,EAAE,gBAAgB,CAAA;CACvB,KACL,OAAO,CAAC,WAAW,EAAE,CAgFvB,CAAA"}
|
package/dist/render-examples.js
CHANGED
|
@@ -10,11 +10,13 @@ schemaOpenapiVersion = openapiVersion, { linked = false, quiet = linked, example
|
|
|
10
10
|
const nodes = [];
|
|
11
11
|
const values = (examples?.get ?? getMarkdownExamples)(source, mediaType, mode, openapiVersion, schemaOpenapiVersion, linked);
|
|
12
12
|
for (const example of values) {
|
|
13
|
-
if ('omitted' in example && quiet)
|
|
13
|
+
if ('omitted' in example && quiet) {
|
|
14
14
|
continue;
|
|
15
|
+
}
|
|
15
16
|
const start = nodes.length;
|
|
16
17
|
const generated = examples && example.generated;
|
|
17
|
-
|
|
18
|
+
const exampleLabel = example.name ? `Example: ${example.name}` : 'Example:';
|
|
19
|
+
nodes.push(paragraph(strong(text(generated ? 'Generated example:' : exampleLabel))));
|
|
18
20
|
const addCode = (code) => {
|
|
19
21
|
if (generated) {
|
|
20
22
|
const scope = JSON.stringify([mediaType, mode, openapiVersion, schemaOpenapiVersion, code.lang]);
|
|
@@ -31,8 +33,9 @@ schemaOpenapiVersion = openapiVersion, { linked = false, quiet = linked, example
|
|
|
31
33
|
nodes.push(paragraph(emphasis(text('Generated example omitted because it is too large.'))));
|
|
32
34
|
continue;
|
|
33
35
|
}
|
|
34
|
-
if (example.summary)
|
|
36
|
+
if (example.summary) {
|
|
35
37
|
nodes.push(paragraph(text(example.summary)));
|
|
38
|
+
}
|
|
36
39
|
nodes.push(...(await description(example.description)));
|
|
37
40
|
if ('error' in example) {
|
|
38
41
|
nodes.push(paragraph(text(example.error)));
|
|
@@ -43,9 +46,10 @@ schemaOpenapiVersion = openapiVersion, { linked = false, quiet = linked, example
|
|
|
43
46
|
continue;
|
|
44
47
|
}
|
|
45
48
|
if ('serializedValue' in example) {
|
|
49
|
+
const textLanguage = mediaType.includes('json') ? 'json' : 'text';
|
|
46
50
|
addCode({
|
|
47
51
|
type: 'code',
|
|
48
|
-
lang: isXmlMediaType(mediaType) ? 'xml' :
|
|
52
|
+
lang: isXmlMediaType(mediaType) ? 'xml' : textLanguage,
|
|
49
53
|
value: example.serializedValue,
|
|
50
54
|
});
|
|
51
55
|
continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-operation-details.d.ts","sourceRoot":"","sources":["../src/render-operation-details.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,8DAA8D,CAAA;AAClH,OAAO,KAAK,EAAY,WAAW,EAAE,MAAM,OAAO,CAAA;AAElD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAE3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD,wFAAwF;AACxF,eAAO,MAAM,aAAa,GACxB,SAAS,cAAc,CAAC,SAAS,CAAC,EAClC,aAAa,iBAAiB,EAC9B,SAAS,cAAc,EACvB,gBAAgB,MAAM,EACtB,6BAAqC,EACrC,WAAW,gBAAgB,KAC1B,OAAO,CAAC,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"render-operation-details.d.ts","sourceRoot":"","sources":["../src/render-operation-details.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,8DAA8D,CAAA;AAClH,OAAO,KAAK,EAAY,WAAW,EAAE,MAAM,OAAO,CAAA;AAElD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAE3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD,wFAAwF;AACxF,eAAO,MAAM,aAAa,GACxB,SAAS,cAAc,CAAC,SAAS,CAAC,EAClC,aAAa,iBAAiB,EAC9B,SAAS,cAAc,EACvB,gBAAgB,MAAM,EACtB,6BAAqC,EACrC,WAAW,gBAAgB,KAC1B,OAAO,CAAC,WAAW,EAAE,CA8CvB,CAAA;AAED,mFAAmF;AACnF,eAAO,MAAM,cAAc,GACzB,UAAU,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,SAAS,EACpD,WAAW,MAAM,EACjB,aAAa,iBAAiB,EAC9B,SAAS,cAAc,EACvB,gBAAgB,MAAM,EACtB,6BAAqC,EACrC,WAAW,gBAAgB,KAC1B,OAAO,CAAC,WAAW,EAAE,CAqCvB,CAAA;AAID,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,GAC9B,OAAO,cAAc,CAAC,OAAO,CAAC,EAC9B,aAAa,iBAAiB,KAC7B,OAAO,CAAC,WAAW,EAAE,CAoCvB,CAAA"}
|
|
@@ -6,24 +6,28 @@ export const renderHeaders = async (headers, description, schemas, openapiVersio
|
|
|
6
6
|
const entries = [];
|
|
7
7
|
for (const [name, reference] of Object.entries(headers ?? {})) {
|
|
8
8
|
// OpenAPI reserves Content-Type for the media type map / encoding field.
|
|
9
|
-
if (name.toLowerCase() === 'content-type')
|
|
9
|
+
if (name.toLowerCase() === 'content-type') {
|
|
10
10
|
continue;
|
|
11
|
-
|
|
11
|
+
}
|
|
12
|
+
if (!getResolvedRef(reference)) {
|
|
12
13
|
continue;
|
|
14
|
+
}
|
|
13
15
|
const header = getResolvedRef(reference, mergeSiblingReferences);
|
|
14
16
|
const blocks = [
|
|
15
17
|
paragraph(strong(inlineCode(name)), text(header.required ? ' (required)' : '')),
|
|
16
18
|
...(await description(header.description)),
|
|
17
19
|
];
|
|
18
|
-
if ('schema' in header && header.schema !== undefined)
|
|
20
|
+
if ('schema' in header && header.schema !== undefined) {
|
|
19
21
|
blocks.push(...schemas.render(header.schema));
|
|
22
|
+
}
|
|
20
23
|
if ('example' in header || 'examples' in header) {
|
|
21
24
|
blocks.push(...(await renderExamples({ example: header.example, examples: header.examples }, description, 'application/json', undefined, openapiVersion, schemaOpenapiVersion, { linked: schemas.linked, examples })));
|
|
22
25
|
}
|
|
23
26
|
for (const [mediaType, content] of Object.entries('content' in header ? (header.content ?? {}) : {})) {
|
|
24
27
|
blocks.push(paragraph(strong(text('Content-Type:')), text(` ${mediaType}`)));
|
|
25
|
-
if (content.schema !== undefined)
|
|
28
|
+
if (content.schema !== undefined) {
|
|
26
29
|
blocks.push(...schemas.render(content.schema));
|
|
30
|
+
}
|
|
27
31
|
blocks.push(...(await renderExamples(content, description, mediaType, undefined, openapiVersion, schemaOpenapiVersion, {
|
|
28
32
|
linked: schemas.linked,
|
|
29
33
|
examples,
|
|
@@ -36,8 +40,9 @@ export const renderHeaders = async (headers, description, schemas, openapiVersio
|
|
|
36
40
|
/** Preserve explicit encoding settings, including false flags and part headers. */
|
|
37
41
|
export const renderEncoding = async (encoding, mediaType, description, schemas, openapiVersion, schemaOpenapiVersion = openapiVersion, examples) => {
|
|
38
42
|
const multipart = mediaType.startsWith('multipart/');
|
|
39
|
-
if (!multipart && mediaType !== 'application/x-www-form-urlencoded')
|
|
43
|
+
if (!multipart && mediaType !== 'application/x-www-form-urlencoded') {
|
|
40
44
|
return [];
|
|
45
|
+
}
|
|
41
46
|
const entries = [];
|
|
42
47
|
for (const [name, entry] of Object.entries(encoding ?? {})) {
|
|
43
48
|
const fields = [];
|
|
@@ -47,14 +52,17 @@ export const renderEncoding = async (encoding, mediaType, description, schemas,
|
|
|
47
52
|
['explode', 'Explode'],
|
|
48
53
|
['allowReserved', 'Allow reserved'],
|
|
49
54
|
]) {
|
|
50
|
-
if (entry[key] !== undefined)
|
|
55
|
+
if (entry[key] !== undefined) {
|
|
51
56
|
fields.push(item(paragraph(text(`${label}: `), inlineCode(entry[key]))));
|
|
57
|
+
}
|
|
52
58
|
}
|
|
53
59
|
const blocks = [paragraph(strong(inlineCode(name)))];
|
|
54
|
-
if (fields.length)
|
|
60
|
+
if (fields.length) {
|
|
55
61
|
blocks.push(list(fields));
|
|
56
|
-
|
|
62
|
+
}
|
|
63
|
+
if (multipart) {
|
|
57
64
|
blocks.push(...(await renderHeaders(entry.headers, description, schemas, openapiVersion, schemaOpenapiVersion, examples)));
|
|
65
|
+
}
|
|
58
66
|
entries.push(item(...blocks));
|
|
59
67
|
}
|
|
60
68
|
return entries.length ? [paragraph(strong(text('Encoding:'))), list(entries)] : [];
|
|
@@ -64,24 +72,30 @@ const formatValue = (value) => (typeof value === 'string' ? value : (JSON.string
|
|
|
64
72
|
export const renderResponseLinks = async (links, description) => {
|
|
65
73
|
const entries = [];
|
|
66
74
|
for (const [name, reference] of Object.entries(links ?? {})) {
|
|
67
|
-
if (!getResolvedRef(reference))
|
|
75
|
+
if (!getResolvedRef(reference)) {
|
|
68
76
|
continue;
|
|
77
|
+
}
|
|
69
78
|
const link = getResolvedRef(reference, mergeSiblingReferences);
|
|
70
79
|
const blocks = [
|
|
71
80
|
paragraph(strong(text(name))),
|
|
72
81
|
...(await description(link.description)),
|
|
73
82
|
];
|
|
74
|
-
if (link.operationId)
|
|
83
|
+
if (link.operationId) {
|
|
75
84
|
blocks.push(paragraph(strong(text('Operation ID:')), text(' '), inlineCode(link.operationId)));
|
|
76
|
-
|
|
85
|
+
}
|
|
86
|
+
if (link.operationRef) {
|
|
77
87
|
blocks.push(paragraph(strong(text('Operation reference:')), text(' '), inlineCode(link.operationRef)));
|
|
88
|
+
}
|
|
78
89
|
const parameters = Object.entries(link.parameters ?? {});
|
|
79
|
-
if (parameters.length)
|
|
90
|
+
if (parameters.length) {
|
|
80
91
|
blocks.push(list(parameters.map(([name, value]) => item(paragraph(strong(text(`${name}:`)), text(' '), inlineCode(formatValue(value)))))));
|
|
81
|
-
|
|
92
|
+
}
|
|
93
|
+
if (link.requestBody !== undefined) {
|
|
82
94
|
blocks.push(paragraph(strong(text('Request body:')), text(' '), inlineCode(formatValue(link.requestBody))));
|
|
83
|
-
|
|
95
|
+
}
|
|
96
|
+
if (link.server) {
|
|
84
97
|
blocks.push(paragraph(strong(text('Server:')), text(' '), inlineCode(link.server.url)));
|
|
98
|
+
}
|
|
85
99
|
entries.push(item(...blocks));
|
|
86
100
|
}
|
|
87
101
|
return entries.length ? [paragraph(strong(text('Links:'))), list(entries)] : [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-operation.d.ts","sourceRoot":"","sources":["../src/render-operation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EAEf,cAAc,EAGf,MAAM,8DAA8D,CAAA;AACrE,OAAO,KAAK,EAAsC,WAAW,EAAE,MAAM,OAAO,CAAA;AAE5E,OAAO,EAAU,KAAK,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAE3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAG5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAGrD,oEAAoE;AACpE,KAAK,aAAa,GAAG;IACnB,WAAW,EAAE,iBAAiB,CAAA;IAC9B,OAAO,EAAE,cAAc,CAAA;IACvB,QAAQ,CAAC,EAAE,gBAAgB,CAAA;IAC3B,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,qEAAqE;AACrE,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAA;IACjD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACrC,CAAA;
|
|
1
|
+
{"version":3,"file":"render-operation.d.ts","sourceRoot":"","sources":["../src/render-operation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EAEf,cAAc,EAGf,MAAM,8DAA8D,CAAA;AACrE,OAAO,KAAK,EAAsC,WAAW,EAAE,MAAM,OAAO,CAAA;AAE5E,OAAO,EAAU,KAAK,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAE3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAG5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAGrD,oEAAoE;AACpE,KAAK,aAAa,GAAG;IACnB,WAAW,EAAE,iBAAiB,CAAA;IAC9B,OAAO,EAAE,cAAc,CAAA;IACvB,QAAQ,CAAC,EAAE,gBAAgB,CAAA;IAC3B,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,qEAAqE;AACrE,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAA;IACjD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACrC,CAAA;AA8CD,yEAAyE;AACzE,eAAO,MAAM,qBAAqB,GAAI,QAAQ,MAAM,KAAG,MACkC,CAAA;AAEzF,iFAAiF;AACjF,eAAO,MAAM,eAAe,GAC1B,UAAU,eAAe,EACzB,MAAM,MAAM,EACZ,QAAQ,MAAM,EACd,UAAU,cAAc,EACxB,WAAW,eAAe,EAC1B,SAAS,OAAO,EAChB,4DAAgE,aAAa,KAC5E,OAAO,CAAC,WAAW,EAAE,CAwMvB,CAAA"}
|