@scalar/openapi-to-markdown 1.3.0 → 1.5.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 +32 -0
- package/README.md +114 -2
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +1 -1
- package/dist/create-markdown-from-openapi.js +1 -1
- package/dist/document-anchors.d.ts +8 -0
- package/dist/document-anchors.d.ts.map +1 -0
- package/dist/document-anchors.js +25 -0
- package/dist/document-examples.d.ts +14 -0
- package/dist/document-examples.d.ts.map +1 -0
- package/dist/document-examples.js +54 -0
- package/dist/get-markdown-examples.d.ts +3 -1
- package/dist/get-markdown-examples.d.ts.map +1 -1
- package/dist/get-markdown-examples.js +12 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/markdown-nodes.d.ts +22 -1
- package/dist/markdown-nodes.d.ts.map +1 -1
- package/dist/markdown-nodes.js +4 -0
- package/dist/parse-description.d.ts +2 -0
- package/dist/parse-description.d.ts.map +1 -1
- package/dist/parse-description.js +28 -1
- package/dist/render-document.d.ts +2 -1
- package/dist/render-document.d.ts.map +1 -1
- package/dist/render-document.js +217 -84
- package/dist/render-examples.d.ts +9 -1
- package/dist/render-examples.d.ts.map +1 -1
- package/dist/render-examples.js +26 -8
- package/dist/render-operation-details.d.ts +3 -2
- package/dist/render-operation-details.d.ts.map +1 -1
- package/dist/render-operation-details.js +8 -5
- package/dist/render-operation.d.ts +16 -1
- package/dist/render-operation.d.ts.map +1 -1
- package/dist/render-operation.js +168 -42
- package/dist/render-schema.d.ts +32 -3
- package/dist/render-schema.d.ts.map +1 -1
- package/dist/render-schema.js +499 -104
- package/dist/render-security.d.ts +7 -3
- package/dist/render-security.d.ts.map +1 -1
- package/dist/render-security.js +61 -12
- package/dist/select-document.d.ts +19 -2
- package/dist/select-document.d.ts.map +1 -1
- package/dist/select-document.js +9 -6
- package/package.json +19 -10
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { OpenApiDocument } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document';
|
|
2
|
-
import type { RootContent } from 'mdast';
|
|
2
|
+
import type { Heading, RootContent } from 'mdast';
|
|
3
3
|
import type { DescriptionParser } from './parse-description.js';
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Preserve OR between requirements and AND between schemes within a requirement.
|
|
6
|
+
* Without declared requirements there is nothing to say: only an explicit empty list means that
|
|
7
|
+
* no authentication is required.
|
|
8
|
+
*/
|
|
9
|
+
export declare const renderSecurity: (requirements: OpenApiDocument["security"], schemes: NonNullable<OpenApiDocument["components"]>["securitySchemes"], description: DescriptionParser, level?: Heading["depth"]) => Promise<RootContent[]>;
|
|
6
10
|
//# sourceMappingURL=render-security.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-security.d.ts","sourceRoot":"","sources":["../src/render-security.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAA;AACnG,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"render-security.d.ts","sourceRoot":"","sources":["../src/render-security.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAA;AACnG,OAAO,KAAK,EAAE,OAAO,EAA6B,WAAW,EAAE,MAAM,OAAO,CAAA;AAG5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAsD5D;;;;GAIG;AACH,eAAO,MAAM,cAAc,GACzB,cAAc,eAAe,CAAC,UAAU,CAAC,EACzC,SAAS,WAAW,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,iBAAiB,CAAC,EACtE,aAAa,iBAAiB,EAC9B,QAAO,OAAO,CAAC,OAAO,CAAK,KAC1B,OAAO,CAAC,WAAW,EAAE,CAsBvB,CAAA"}
|
package/dist/render-security.js
CHANGED
|
@@ -1,10 +1,61 @@
|
|
|
1
1
|
import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref';
|
|
2
|
-
import { heading, item, list, paragraph, strong, text } from './markdown-nodes.js';
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { heading, inlineCode, item, list, paragraph, strong, text } from './markdown-nodes.js';
|
|
3
|
+
const flowNames = {
|
|
4
|
+
implicit: 'implicit',
|
|
5
|
+
password: 'password',
|
|
6
|
+
clientCredentials: 'client credentials',
|
|
7
|
+
authorizationCode: 'authorization code',
|
|
8
|
+
deviceAuthorization: 'device authorization',
|
|
9
|
+
};
|
|
10
|
+
/** Summarize a security scheme on one line, for example "API key in header `X-Api-Key`". */
|
|
11
|
+
const summarizeScheme = (scheme) => {
|
|
12
|
+
const value = scheme;
|
|
13
|
+
switch (value.type) {
|
|
14
|
+
case 'apiKey':
|
|
15
|
+
return [text(`API key in ${String(value.in ?? 'header')} `), inlineCode(value.name)];
|
|
16
|
+
case 'http': {
|
|
17
|
+
const name = typeof value.scheme === 'string' ? value.scheme.toLowerCase() : '';
|
|
18
|
+
return [
|
|
19
|
+
text(`HTTP ${name || 'authentication'}`),
|
|
20
|
+
...(typeof value.bearerFormat === 'string' ? [text(' ('), inlineCode(value.bearerFormat), text(')')] : []),
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
case 'oauth2': {
|
|
24
|
+
const flows = Object.entries(typeof value.flows === 'object' && value.flows ? value.flows : {});
|
|
25
|
+
const nodes = [text('OAuth 2.0')];
|
|
26
|
+
for (const [index, [flow, settings]] of flows.entries()) {
|
|
27
|
+
const urls = settings;
|
|
28
|
+
nodes.push(text(`${index ? '; ' : ': '}${flowNames[flow] ?? flow}`));
|
|
29
|
+
for (const [key, label] of [
|
|
30
|
+
['authorizationUrl', 'authorize'],
|
|
31
|
+
['deviceAuthorizationUrl', 'device authorization'],
|
|
32
|
+
['tokenUrl', 'token'],
|
|
33
|
+
['refreshUrl', 'refresh'],
|
|
34
|
+
]) {
|
|
35
|
+
// Coercion fills in optional URLs as empty strings.
|
|
36
|
+
if (typeof urls[key] === 'string' && urls[key])
|
|
37
|
+
nodes.push(text(`, ${label} `), inlineCode(urls[key]));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return nodes;
|
|
41
|
+
}
|
|
42
|
+
case 'openIdConnect':
|
|
43
|
+
return [text('OpenID Connect '), inlineCode(value.openIdConnectUrl)];
|
|
44
|
+
case 'mutualTLS':
|
|
45
|
+
return [text('Mutual TLS')];
|
|
46
|
+
default:
|
|
47
|
+
return [inlineCode(value.type)];
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Preserve OR between requirements and AND between schemes within a requirement.
|
|
52
|
+
* Without declared requirements there is nothing to say: only an explicit empty list means that
|
|
53
|
+
* no authentication is required.
|
|
54
|
+
*/
|
|
55
|
+
export const renderSecurity = async (requirements, schemes, description, level = 4) => {
|
|
5
56
|
if (!requirements)
|
|
6
57
|
return [];
|
|
7
|
-
const nodes = [heading(
|
|
58
|
+
const nodes = [heading(level, text('Authentication'))];
|
|
8
59
|
if (!requirements.length)
|
|
9
60
|
nodes.push(paragraph(text('No authentication required.')));
|
|
10
61
|
for (const [index, requirement] of requirements.entries()) {
|
|
@@ -17,15 +68,13 @@ export const renderSecurity = async (requirements, schemes, description) => {
|
|
|
17
68
|
}
|
|
18
69
|
const entriesNodes = [];
|
|
19
70
|
for (const [name, scopes] of entries) {
|
|
20
|
-
const blocks = [
|
|
21
|
-
paragraph(strong(text(name)), ...(scopes?.length ? [text(` Scopes: ${scopes.join(', ')}`)] : [])),
|
|
22
|
-
];
|
|
23
71
|
const scheme = getResolvedRef(schemes?.[name]);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
72
|
+
const line = [strong(text(name))];
|
|
73
|
+
if (scheme)
|
|
74
|
+
line.push(text(': '), ...summarizeScheme(scheme));
|
|
75
|
+
if (scopes?.length)
|
|
76
|
+
line.push(text(', scopes: '), inlineCode(scopes.join(', ')));
|
|
77
|
+
entriesNodes.push(item(paragraph(...line), ...(await description(scheme?.description))));
|
|
29
78
|
}
|
|
30
79
|
nodes.push(list(entriesNodes));
|
|
31
80
|
}
|
|
@@ -10,9 +10,26 @@ export type OperationSelector = {
|
|
|
10
10
|
pointer: string;
|
|
11
11
|
};
|
|
12
12
|
/** Select one reference page, or omit selectors for the whole document. */
|
|
13
|
-
export type OpenApiRenderOptions = {
|
|
13
|
+
export type OpenApiRenderOptions = SchemaReferenceOptions & ({
|
|
14
14
|
[Key in keyof PageSelectors]: Partial<Record<Exclude<keyof PageSelectors, Key>, never>> & Pick<PageSelectors, Key>;
|
|
15
|
-
}[keyof PageSelectors] | Partial<Record<keyof PageSelectors, never
|
|
15
|
+
}[keyof PageSelectors] | Partial<Record<keyof PageSelectors, never>>);
|
|
16
|
+
/** Control shared-schema expansion without assuming a documentation URL layout. */
|
|
17
|
+
export type SchemaReferenceOptions = {
|
|
18
|
+
/** Expand root schemas, link nested references, and omit generated examples and the transitive appendix. */
|
|
19
|
+
schemaReferences?: {
|
|
20
|
+
mode: 'linked';
|
|
21
|
+
/** Return a published URL, or undefined to retain the schema name as plain text. */
|
|
22
|
+
resolveUrl?: (reference: {
|
|
23
|
+
ref: string;
|
|
24
|
+
name: string;
|
|
25
|
+
}) => string | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Render references to primitive, enum and `const` schemas, and to aliases of them, in place
|
|
28
|
+
* instead of linking them. Their whole definition fits on one line. Defaults to `true`.
|
|
29
|
+
*/
|
|
30
|
+
inlinePrimitives?: boolean;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
16
33
|
type PageSelectors = {
|
|
17
34
|
operation: OperationSelector;
|
|
18
35
|
tag: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select-document.d.ts","sourceRoot":"","sources":["../src/select-document.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAA;AACjF,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,8DAA8D,CAAA;AAEnH,gFAAgF;AAChF,MAAM,MAAM,iBAAiB,GACzB;IACE,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,eAAe,CAAA;CACxB,GACD;IACE,WAAW,EAAE,MAAM,CAAA;CACpB,GACD;IACE,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AACL,2EAA2E;AAC3E,MAAM,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"select-document.d.ts","sourceRoot":"","sources":["../src/select-document.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAA;AACjF,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,8DAA8D,CAAA;AAEnH,gFAAgF;AAChF,MAAM,MAAM,iBAAiB,GACzB;IACE,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,eAAe,CAAA;CACxB,GACD;IACE,WAAW,EAAE,MAAM,CAAA;CACpB,GACD;IACE,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AACL,2EAA2E;AAC3E,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,GACvD,CACI;KACG,GAAG,IAAI,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,aAAa,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,GACrF,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC;CAC3B,CAAC,MAAM,aAAa,CAAC,GACtB,OAAO,CAAC,MAAM,CAAC,MAAM,aAAa,EAAE,KAAK,CAAC,CAAC,CAC9C,CAAA;AAEH,mFAAmF;AACnF,MAAM,MAAM,sBAAsB,GAAG;IACnC,4GAA4G;IAC5G,gBAAgB,CAAC,EAAE;QACjB,IAAI,EAAE,QAAQ,CAAA;QACd,oFAAoF;QACpF,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,KAAK,MAAM,GAAG,SAAS,CAAA;QAC7E;;;WAGG;QACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAC3B,CAAA;CACF,CAAA;AAED,KAAK,aAAa,GAAG;IACnB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,eAAe,CAAA;KAAE,CAAA;IAClD,YAAY,EAAE,IAAI,CAAA;CACnB,CAAA;AAyKD,sEAAsE;AACtE,eAAO,MAAM,cAAc,GAAI,UAAU,eAAe,EAAE,UAAS,oBAAyB,KAAG,eA4N9F,CAAA"}
|
package/dist/select-document.js
CHANGED
|
@@ -126,7 +126,7 @@ export const selectDocument = (document, options = {}) => {
|
|
|
126
126
|
if (!isObject(options)) {
|
|
127
127
|
throw new Error('Render options must be an object');
|
|
128
128
|
}
|
|
129
|
-
const keys = Object.keys(options).filter((key) => options[key] !== undefined);
|
|
129
|
+
const keys = Object.keys(options).filter((key) => key !== 'schemaReferences' && options[key] !== undefined);
|
|
130
130
|
if (!keys.length) {
|
|
131
131
|
return document;
|
|
132
132
|
}
|
|
@@ -231,8 +231,9 @@ export const selectDocument = (document, options = {}) => {
|
|
|
231
231
|
parameters.set(`${parameter.in}:${parameter.name}`, ref);
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
|
-
|
|
235
|
-
|
|
234
|
+
// Undeclared security stays undeclared: an empty list would claim that no authentication is required.
|
|
235
|
+
const security = operation.security ?? document.security;
|
|
236
|
+
for (const requirement of security ?? []) {
|
|
236
237
|
for (const name of Object.keys(requirement)) {
|
|
237
238
|
securityNames.add(name);
|
|
238
239
|
}
|
|
@@ -320,9 +321,11 @@ export const selectDocument = (document, options = {}) => {
|
|
|
320
321
|
}
|
|
321
322
|
}
|
|
322
323
|
};
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
324
|
+
if (options.schemaReferences?.mode !== 'linked') {
|
|
325
|
+
visit({ paths: selected.paths, webhooks: selected.webhooks });
|
|
326
|
+
for (const root of modelRoots) {
|
|
327
|
+
visit(root);
|
|
328
|
+
}
|
|
326
329
|
}
|
|
327
330
|
selected.components = {
|
|
328
331
|
...document.components,
|
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"llm",
|
|
17
17
|
"swagger"
|
|
18
18
|
],
|
|
19
|
-
"version": "1.
|
|
19
|
+
"version": "1.5.0",
|
|
20
20
|
"engines": {
|
|
21
21
|
"node": ">=22"
|
|
22
22
|
},
|
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@scalar/code-highlight": "0.4.7",
|
|
44
|
-
"@scalar/helpers": "0.
|
|
45
|
-
"@scalar/json-magic": "0.15.
|
|
46
|
-
"@scalar/openapi-upgrader": "0.4.
|
|
47
|
-
"@scalar/workspace-store": "0.67.
|
|
44
|
+
"@scalar/helpers": "0.16.0",
|
|
45
|
+
"@scalar/json-magic": "0.15.3",
|
|
46
|
+
"@scalar/openapi-upgrader": "0.4.1",
|
|
47
|
+
"@scalar/workspace-store": "0.67.2",
|
|
48
48
|
"rehype-parse": "^9.0.1",
|
|
49
49
|
"rehype-remark": "^10.0.1",
|
|
50
50
|
"rehype-sanitize": "^6.0.0",
|
|
@@ -54,16 +54,25 @@
|
|
|
54
54
|
"unified": "^11.0.5"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@
|
|
57
|
+
"@scalar/components": "0.30.5",
|
|
58
58
|
"@scalar/galaxy": "0.7.1",
|
|
59
|
+
"@scalar/themes": "0.18.1",
|
|
60
|
+
"@tailwindcss/vite": "^4.3.3",
|
|
59
61
|
"@types/mdast": "^4.0.4",
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
+
"@vitejs/plugin-vue": "^6.0.8",
|
|
63
|
+
"marked": "^14.0.0",
|
|
64
|
+
"rehype-stringify": "^10.0.1",
|
|
65
|
+
"tailwindcss": "^4.3.3",
|
|
66
|
+
"tsx": "4.19.4",
|
|
67
|
+
"vite": "8.1.5",
|
|
68
|
+
"vitest": "4.1.10",
|
|
69
|
+
"vue": "^3.5.40",
|
|
70
|
+
"vue-tsc": "^3.3.8"
|
|
62
71
|
},
|
|
63
72
|
"scripts": {
|
|
64
73
|
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
65
|
-
"dev": "
|
|
74
|
+
"dev": "cd playground && vite",
|
|
66
75
|
"test": "vitest --run",
|
|
67
|
-
"types:check": "tsgo --noEmit"
|
|
76
|
+
"types:check": "tsgo --noEmit && vue-tsc --noEmit -p playground/tsconfig.json"
|
|
68
77
|
}
|
|
69
78
|
}
|