@scalar/openapi-to-markdown 1.3.0 → 1.4.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @scalar/openapi-to-markdown
2
2
 
3
+ ## 1.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#10394](https://github.com/scalar/scalar/pull/10394): Add opt-in linked schema rendering with caller-supplied model URLs for bounded operation, model, and webhook pages. Keep default expansion unchanged, retain reference siblings and inline schemas, and omit generated examples in linked mode.
8
+
3
9
  ## 1.3.0
4
10
 
5
11
  ### Minor Changes
package/README.md CHANGED
@@ -194,3 +194,54 @@ const markdown = await createMarkdownFromOpenApi(document, {
194
194
 
195
195
  Use the default entry point for raw JSON, YAML, URLs, or file paths that still need
196
196
  loading, migration, and reference resolution.
197
+
198
+ ### Link shared schemas on individual pages
199
+
200
+ The default renderer expands shared schemas and includes the schemas needed by a
201
+ selected page. For large API descriptions, opt into `schemaReferences.mode:
202
+ 'linked'` to expand the root schema of each parameter, request, response, or model
203
+ and replace nested `$ref` occurrences with links. Inline schemas continue to
204
+ render, including composition branches and reference siblings. Operation and
205
+ webhook pages do not collect or append transitive models; a model page includes
206
+ only the selected model.
207
+
208
+ The documentation generator supplies published URLs. The renderer does not assume
209
+ any routing convention:
210
+
211
+ ```ts
212
+ import { createOpenApiMarkdownRenderer } from '@scalar/openapi-to-markdown'
213
+
214
+ const renderer = await createOpenApiMarkdownRenderer(apiDescription)
215
+ // Build this map from the pages your generator actually publishes.
216
+ const modelUrls = new Map([
217
+ ['account', '/reference/models/account'],
218
+ ['customer', '/reference/models/customer'],
219
+ ])
220
+ const markdown = await renderer.render({
221
+ operation: { path: '/v1/account', method: 'get' },
222
+ schemaReferences: {
223
+ mode: 'linked',
224
+ resolveUrl: ({ name }) => modelUrls.get(name),
225
+ },
226
+ })
227
+ ```
228
+
229
+ The callback receives the original reference string (`ref`) and its decoded
230
+ component name (`name`). For references outside `#/components/schemas/{name}`,
231
+ `name` is the reference string. Returning `undefined`, an empty URL, or an unsafe
232
+ URL retains the schema name as text. Omitting the callback has the same fallback.
233
+ References remain visible even when no destination page exists.
234
+
235
+ Use the same option with `{ model: 'account' }`, `{ webhook: { name: 'event',
236
+ method: 'post' } }`, the one-shot `createMarkdownFromOpenApi`, or the browser entry
237
+ point. The browser entry point still requires a workspace-resolved document.
238
+ Options and URL callbacks are isolated per render, including concurrent renders.
239
+
240
+ Linked mode omits schema-generated examples with an explicit note, avoiding
241
+ expansion through the example generator. Authored media-type and schema examples
242
+ remain available. Their size is not capped. Inline schema content and authored
243
+ text also remain proportional to the source; this mode bounds traversal across
244
+ shared references, not the byte size of arbitrary authored content. Root
245
+ composition branches that contain references link to those schemas rather than
246
+ flattening their constraints. Full-document exports still include every model
247
+ section; use a page selector for individual exports.
@@ -1 +1 @@
1
- {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAA;AAGnG,OAAO,EAAE,KAAK,oBAAoB,EAAkB,MAAM,mBAAmB,CAAA;AAE7E;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,GACpC,UAAU,eAAe,EACzB,UAAU,oBAAoB,KAC7B,OAAO,CAAC,MAAM,CAAsE,CAAA"}
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAA;AAGnG,OAAO,EAAE,KAAK,oBAAoB,EAAkB,MAAM,mBAAmB,CAAA;AAE7E;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,GACpC,UAAU,eAAe,EACzB,UAAU,oBAAoB,KAC7B,OAAO,CAAC,MAAM,CAA+E,CAAA"}
package/dist/browser.js CHANGED
@@ -5,4 +5,4 @@ import { selectDocument } from './select-document.js';
5
5
  * References must already be resolved by the store. This entry point does not load
6
6
  * files, fetch URLs, or migrate raw API descriptions.
7
7
  */
8
- export const createMarkdownFromOpenApi = async (document, options) => await createDocumentRenderer()(selectDocument(document, options));
8
+ export const createMarkdownFromOpenApi = async (document, options) => await createDocumentRenderer()(selectDocument(document, options), options);
@@ -8,7 +8,7 @@ import { selectDocument } from './select-document.js';
8
8
  export const createOpenApiMarkdownRenderer = async (input) => {
9
9
  const content = await loadDocument(input);
10
10
  const renderDocument = createDocumentRenderer();
11
- const render = async (options) => await renderDocument(selectDocument(content, options));
11
+ const render = async (options) => await renderDocument(selectDocument(content, options), options);
12
12
  return { render };
13
13
  };
14
14
  /** Generate Markdown from an API description, optionally scoped to a single page. */
@@ -28,6 +28,6 @@ type MarkdownExample = {
28
28
  */
29
29
  export declare const countGeneratedExampleValues: (root: unknown, limit?: number) => number;
30
30
  /** Preserve supplied values; generate a fallback only when examples are not supplied. */
31
- export declare const getMarkdownExamples: (source: ExampleSource, mediaType: string, mode?: "read" | "write", openapiVersion?: string, schemaOpenapiVersion?: string) => MarkdownExample[];
31
+ export declare const getMarkdownExamples: (source: ExampleSource, mediaType: string, mode?: "read" | "write", openapiVersion?: string, schemaOpenapiVersion?: string, linked?: boolean) => MarkdownExample[];
32
32
  export {};
33
33
  //# sourceMappingURL=get-markdown-examples.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-markdown-examples.d.ts","sourceRoot":"","sources":["../src/get-markdown-examples.ts"],"names":[],"mappings":"AAMA,4FAA4F;AAC5F,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC,CAAA;AAED,gFAAgF;AAChF,KAAK,eAAe,GAAG;IACrB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,CACA;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAClB;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,eAAe,EAAE,MAAM,CAAA;CAAE,GAC3B;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,GACtB;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CACpB,CAAA;AAYD;;;GAGG;AACH,eAAO,MAAM,2BAA2B,GAAI,MAAM,OAAO,EAAE,cAAoC,KAAG,MA2CjG,CAAA;AAED,yFAAyF;AACzF,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,aAAa,EACrB,WAAW,MAAM,EACjB,OAAO,MAAM,GAAG,OAAO,EACvB,uBAAwB,EAExB,6BAAqC,KACpC,eAAe,EAoCjB,CAAA"}
1
+ {"version":3,"file":"get-markdown-examples.d.ts","sourceRoot":"","sources":["../src/get-markdown-examples.ts"],"names":[],"mappings":"AAMA,4FAA4F;AAC5F,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC,CAAA;AAED,gFAAgF;AAChF,KAAK,eAAe,GAAG;IACrB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,CACA;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAClB;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,eAAe,EAAE,MAAM,CAAA;CAAE,GAC3B;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,GACtB;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CACpB,CAAA;AAYD;;;GAGG;AACH,eAAO,MAAM,2BAA2B,GAAI,MAAM,OAAO,EAAE,cAAoC,KAAG,MA2CjG,CAAA;AAED,yFAAyF;AACzF,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,aAAa,EACrB,WAAW,MAAM,EACjB,OAAO,MAAM,GAAG,OAAO,EACvB,uBAAwB,EAExB,6BAAqC,EACrC,gBAAc,KACb,eAAe,EA2CjB,CAAA"}
@@ -71,7 +71,7 @@ export const countGeneratedExampleValues = (root, limit = MAX_GENERATED_EXAMPLE_
71
71
  /** Preserve supplied values; generate a fallback only when examples are not supplied. */
72
72
  export const getMarkdownExamples = (source, mediaType, mode, openapiVersion = '3.2.0',
73
73
  // Schema metadata can be upgraded while example fields still follow the original version.
74
- schemaOpenapiVersion = openapiVersion) => {
74
+ schemaOpenapiVersion = openapiVersion, linked = false) => {
75
75
  if (source.example !== undefined)
76
76
  return [{ value: source.example }];
77
77
  if (source.examples && Object.keys(source.examples).length) {
@@ -95,9 +95,18 @@ schemaOpenapiVersion = openapiVersion) => {
95
95
  return [];
96
96
  });
97
97
  }
98
- const schema = getResolvedRef(source.schema);
98
+ const schema = linked
99
+ ? getResolvedRef(source.schema, mergeSiblingReferences)
100
+ : getResolvedRef(source.schema);
99
101
  if (!isObject(schema))
100
102
  return [];
103
+ if (linked) {
104
+ if (schema.example !== undefined)
105
+ return [{ value: schema.example }];
106
+ if (Array.isArray(schema.examples) && schema.examples.length)
107
+ return schema.examples.map((value) => ({ value }));
108
+ return [{ omitted: true }];
109
+ }
101
110
  if (countGeneratedExampleValues(source.schema) > MAX_GENERATED_EXAMPLE_VALUES)
102
111
  return [{ omitted: true }];
103
112
  if (isXmlMediaType(mediaType)) {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export type { HttpMethod } from '@scalar/helpers/http/http-methods';
2
2
  export type { OpenApiMarkdownRenderer } from './create-markdown-from-openapi.js';
3
3
  export { createMarkdownFromOpenApi, createOpenApiMarkdownRenderer, } from './create-markdown-from-openapi.js';
4
- export type { OpenApiRenderOptions, OperationSelector } from './select-document.js';
4
+ export type { OpenApiRenderOptions, OperationSelector, SchemaReferenceOptions } from './select-document.js';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAEnE,YAAY,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAA;AAC7E,OAAO,EACL,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,gCAAgC,CAAA;AACvC,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAEnE,YAAY,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAA;AAC7E,OAAO,EACL,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,gCAAgC,CAAA;AACvC,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import type { OpenApiDocument } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document';
2
+ import type { SchemaReferenceOptions } from './select-document.js';
2
3
  /** Build Markdown directly, retaining caches only for this immutable document snapshot. */
3
- export declare const createDocumentRenderer: () => ((document: OpenApiDocument) => Promise<string>);
4
+ export declare const createDocumentRenderer: () => ((document: OpenApiDocument, options?: SchemaReferenceOptions) => Promise<string>);
4
5
  //# sourceMappingURL=render-document.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render-document.d.ts","sourceRoot":"","sources":["../src/render-document.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,8DAA8D,CAAA;AAepH,2FAA2F;AAC3F,eAAO,MAAM,sBAAsB,QAAO,CAAC,CAAC,QAAQ,EAAE,eAAe,KAAK,OAAO,CAAC,MAAM,CAAC,CA6IxF,CAAA"}
1
+ {"version":3,"file":"render-document.d.ts","sourceRoot":"","sources":["../src/render-document.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,8DAA8D,CAAA;AAYpH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAI/D,2FAA2F;AAC3F,eAAO,MAAM,sBAAsB,QAAO,CAAC,CACzC,QAAQ,EAAE,eAAe,EACzB,OAAO,CAAC,EAAE,sBAAsB,KAC7B,OAAO,CAAC,MAAM,CAAC,CA+InB,CAAA"}
@@ -14,10 +14,10 @@ const serializer = unified().use(remarkGfm).use(remarkStringify, { bullet: '-' }
14
14
  export const createDocumentRenderer = () => {
15
15
  const descriptions = createDescriptionParser();
16
16
  const schemaRenderer = createSchemaRenderer();
17
- return async (document) => {
17
+ return async (document, options) => {
18
18
  const description = descriptions();
19
19
  // Each page expands a shared schema once, then refers back to it.
20
- const schemas = schemaRenderer.forDocument(document.components?.schemas);
20
+ const schemas = schemaRenderer.forDocument(document.components?.schemas, options);
21
21
  const { info } = document;
22
22
  const metadata = [
23
23
  field('OpenAPI Version', inlineCode(document.openapi)),
@@ -108,7 +108,7 @@ export const createDocumentRenderer = () => {
108
108
  : item(paragraph(strong(text('Type:')))),
109
109
  ]), ...(await description(view.description)), ...schemas.render(schema, 0, [], { hideDescription: true, name }));
110
110
  if (view.type === 'object')
111
- nodes.push(...(await renderExamples({ schema }, description, 'application/json', undefined, document['x-original-oas-version'] ?? document.openapi)));
111
+ nodes.push(...(await renderExamples({ schema }, description, 'application/json', undefined, document['x-original-oas-version'] ?? document.openapi, document.openapi, schemas.linked)));
112
112
  flush();
113
113
  }
114
114
  flush();
@@ -2,5 +2,5 @@ import type { RootContent } from 'mdast';
2
2
  import { type ExampleSource } from './get-markdown-examples.js';
3
3
  import type { DescriptionParser } from './parse-description.js';
4
4
  /** Render supplied examples before considering a schema-generated fallback. */
5
- export declare const renderExamples: (source: ExampleSource, description: DescriptionParser, mediaType?: string, mode?: "read" | "write", openapiVersion?: string, schemaOpenapiVersion?: string) => Promise<RootContent[]>;
5
+ export declare const renderExamples: (source: ExampleSource, description: DescriptionParser, mediaType?: string, mode?: "read" | "write", openapiVersion?: string, schemaOpenapiVersion?: string, linked?: boolean) => Promise<RootContent[]>;
6
6
  //# sourceMappingURL=render-examples.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render-examples.d.ts","sourceRoot":"","sources":["../src/render-examples.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAExC,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,KACpC,OAAO,CAAC,WAAW,EAAE,CAmDvB,CAAA"}
1
+ {"version":3,"file":"render-examples.d.ts","sourceRoot":"","sources":["../src/render-examples.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAExC,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,gBAAc,KACb,OAAO,CAAC,WAAW,EAAE,CAyDvB,CAAA"}
@@ -5,12 +5,12 @@ import { link, paragraph, strong, text } from './markdown-nodes.js';
5
5
  /** Render supplied examples before considering a schema-generated fallback. */
6
6
  export const renderExamples = async (source, description, mediaType = 'application/json', mode, openapiVersion = '3.2.0',
7
7
  // Schema metadata can be upgraded while example fields still follow the original version.
8
- schemaOpenapiVersion = openapiVersion) => {
8
+ schemaOpenapiVersion = openapiVersion, linked = false) => {
9
9
  const nodes = [];
10
- for (const example of getMarkdownExamples(source, mediaType, mode, openapiVersion, schemaOpenapiVersion)) {
10
+ for (const example of getMarkdownExamples(source, mediaType, mode, openapiVersion, schemaOpenapiVersion, linked)) {
11
11
  nodes.push(paragraph(strong(text(example.name ? `Example: ${example.name}` : 'Example:'))));
12
12
  if ('omitted' in example) {
13
- nodes.push(paragraph(text('[Generated example omitted because it is too large]')));
13
+ nodes.push(paragraph(text(`${linked ? '[Generated example omitted in linked schema mode; see the schema documentation]' : '[Generated example omitted because it is too large]'}`)));
14
14
  continue;
15
15
  }
16
16
  if (example.summary)
@@ -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;AAGlD,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,KACpC,OAAO,CAAC,WAAW,EAAE,CA0CvB,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,KACpC,OAAO,CAAC,WAAW,EAAE,CA6BvB,CAAA;AAID,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,GAC9B,OAAO,cAAc,CAAC,OAAO,CAAC,EAC9B,aAAa,iBAAiB,KAC7B,OAAO,CAAC,WAAW,EAAE,CA2BvB,CAAA"}
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;AAGlD,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,KACpC,OAAO,CAAC,WAAW,EAAE,CA4CvB,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,KACpC,OAAO,CAAC,WAAW,EAAE,CA6BvB,CAAA;AAID,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,GAC9B,OAAO,cAAc,CAAC,OAAO,CAAC,EAC9B,aAAa,iBAAiB,KAC7B,OAAO,CAAC,WAAW,EAAE,CA2BvB,CAAA"}
@@ -18,13 +18,13 @@ export const renderHeaders = async (headers, description, schemas, openapiVersio
18
18
  if ('schema' in header && header.schema !== undefined)
19
19
  blocks.push(...schemas.render(header.schema));
20
20
  if ('example' in header || 'examples' in header) {
21
- blocks.push(...(await renderExamples({ example: header.example, examples: header.examples }, description, 'application/json', undefined, openapiVersion, schemaOpenapiVersion)));
21
+ blocks.push(...(await renderExamples({ example: header.example, examples: header.examples }, description, 'application/json', undefined, openapiVersion, schemaOpenapiVersion, schemas.linked)));
22
22
  }
23
23
  for (const [mediaType, content] of Object.entries('content' in header ? (header.content ?? {}) : {})) {
24
24
  blocks.push(paragraph(strong(text('Content-Type:')), text(` ${mediaType}`)));
25
25
  if (content.schema !== undefined)
26
26
  blocks.push(...schemas.render(content.schema));
27
- blocks.push(...(await renderExamples(content, description, mediaType, undefined, openapiVersion, schemaOpenapiVersion)));
27
+ blocks.push(...(await renderExamples(content, description, mediaType, undefined, openapiVersion, schemaOpenapiVersion, schemas.linked)));
28
28
  }
29
29
  entries.push(item(...blocks));
30
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"render-operation.d.ts","sourceRoot":"","sources":["../src/render-operation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EAEf,cAAc,EAGf,MAAM,8DAA8D,CAAA;AACrE,OAAO,KAAK,EAAY,WAAW,EAAE,MAAM,OAAO,CAAA;AAGlD,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;CACxB,CAAA;AAED,iFAAiF;AACjF,eAAO,MAAM,eAAe,GAC1B,UAAU,eAAe,EACzB,MAAM,MAAM,EACZ,QAAQ,MAAM,EACd,UAAU,cAAc,EACxB,WAAW,eAAe,EAC1B,SAAS,OAAO,EAChB,0BAA0B,aAAa,KACtC,OAAO,CAAC,WAAW,EAAE,CA4GvB,CAAA"}
1
+ {"version":3,"file":"render-operation.d.ts","sourceRoot":"","sources":["../src/render-operation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EAEf,cAAc,EAGf,MAAM,8DAA8D,CAAA;AACrE,OAAO,KAAK,EAAY,WAAW,EAAE,MAAM,OAAO,CAAA;AAGlD,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;CACxB,CAAA;AAED,iFAAiF;AACjF,eAAO,MAAM,eAAe,GAC1B,UAAU,eAAe,EACzB,MAAM,MAAM,EACZ,QAAQ,MAAM,EACd,UAAU,cAAc,EACxB,WAAW,eAAe,EAC1B,SAAS,OAAO,EAChB,0BAA0B,aAAa,KACtC,OAAO,CAAC,WAAW,EAAE,CA0IvB,CAAA"}
@@ -64,7 +64,7 @@ export const renderOperation = async (document, path, method, pathItem, operatio
64
64
  nodes.push(heading(6, text(`Content-Type: ${mediaType}`)));
65
65
  if (content.schema !== undefined)
66
66
  nodes.push(...schemas.render(content.schema));
67
- nodes.push(...(await renderExamples(content, description, mediaType, 'write', openapiVersion, document.openapi)));
67
+ nodes.push(...(await renderExamples(content, description, mediaType, 'write', openapiVersion, document.openapi, schemas.linked)));
68
68
  }
69
69
  }
70
70
  const body = getResolvedRef(operation.requestBody, mergeSiblingReferences);
@@ -76,7 +76,7 @@ export const renderOperation = async (document, path, method, pathItem, operatio
76
76
  nodes.push(heading(5, text(`Content-Type: ${mediaType}`)));
77
77
  if (content.schema !== undefined)
78
78
  nodes.push(...schemas.render(content.schema));
79
- nodes.push(...(await renderExamples(content, description, mediaType, 'write', openapiVersion, document.openapi)));
79
+ nodes.push(...(await renderExamples(content, description, mediaType, 'write', openapiVersion, document.openapi, schemas.linked)));
80
80
  nodes.push(...(await renderEncoding(content.encoding, mediaType, description, schemas, openapiVersion, document.openapi)));
81
81
  }
82
82
  }
@@ -93,7 +93,7 @@ export const renderOperation = async (document, path, method, pathItem, operatio
93
93
  nodes.push(heading(6, text(`Content-Type: ${mediaType}`)));
94
94
  if (content.schema !== undefined)
95
95
  nodes.push(...schemas.render(content.schema));
96
- nodes.push(...(await renderExamples(content, description, mediaType, 'read', openapiVersion, document.openapi)));
96
+ nodes.push(...(await renderExamples(content, description, mediaType, 'read', openapiVersion, document.openapi, schemas.linked)));
97
97
  }
98
98
  }
99
99
  return nodes;
@@ -1,5 +1,6 @@
1
1
  import type { MaybeRefSchemaObject, SchemaObject } from '@scalar/workspace-store/schemas/v3.2/strict/schema';
2
2
  import type { RootContent } from 'mdast';
3
+ import type { SchemaReferenceOptions } from './select-document.js';
3
4
  /** Boolean schemas must survive rendering without being coerced into empty objects. */
4
5
  type MarkdownSchema = MaybeRefSchemaObject | boolean;
5
6
  type SchemaView = {
@@ -56,12 +57,13 @@ type RenderOptions = {
56
57
  * run concurrently, and each needs its own record.
57
58
  */
58
59
  export type SchemaRenderer = {
60
+ linked: boolean;
59
61
  view: (schema: MarkdownSchema) => SchemaView;
60
62
  render: (schema: MarkdownSchema, depth?: number, ancestors?: readonly unknown[], options?: RenderOptions) => RootContent[];
61
63
  /** Restore the node budget, for example for each operation or model section. */
62
64
  beginSection: () => void;
63
65
  /** Start a document that shares normalized views, given the models it renders in its own sections. */
64
- forDocument: (models?: Record<string, MarkdownSchema>) => SchemaRenderer;
66
+ forDocument: (models?: Record<string, MarkdownSchema>, options?: SchemaReferenceOptions) => SchemaRenderer;
65
67
  };
66
68
  type SchemaRendererOptions = {
67
69
  /** Upper bound on expanded schema nodes per section, so no description can make a page unbounded. */
@@ -1 +1 @@
1
- {"version":3,"file":"render-schema.d.ts","sourceRoot":"","sources":["../src/render-schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"render-schema.d.ts","sourceRoot":"","sources":["../src/render-schema.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,6 @@
1
- import { unescapeJsonPointer } from '@scalar/helpers/json/unescape-json-pointer';
2
1
  import { isObject } from '@scalar/helpers/object/is-object';
3
2
  import { getResolvedRef, mergeSiblingReferences } from '@scalar/workspace-store/helpers/get-resolved-ref';
4
- import { inlineCode, item, list, paragraph, strong, text } from './markdown-nodes.js';
3
+ import { inlineCode, item, link, list, paragraph, safeUrl, strong, text } from './markdown-nodes.js';
5
4
  /** Guards against stack exhaustion. Past it, references to models point to their own section instead. */
6
5
  const MAX_DEPTH = 64;
7
6
  /**
@@ -29,11 +28,10 @@ const referenceKeys = new Set(['$ref', '$ref-value', '$global', '$status']);
29
28
  const emphasis = (...children) => ({ type: 'emphasis', children });
30
29
  /** Prefer the component name, which is how model sections and other references identify the schema. */
31
30
  const getReferenceName = (ref) => {
32
- const match = /^#\/components\/schemas\/([^/]+)$/.exec(ref);
33
- if (!match)
34
- return ref;
35
31
  try {
36
- return unescapeJsonPointer(match[1]);
32
+ // URI fragments are decoded before JSON Pointer segments and escapes, exactly once.
33
+ const match = /^#\/components\/schemas\/([^/]+)$/.exec(decodeURIComponent(ref));
34
+ return match ? match[1].replaceAll('~1', '/').replaceAll('~0', '~') : ref;
37
35
  }
38
36
  catch {
39
37
  return ref;
@@ -133,7 +131,8 @@ export const createSchemaRenderer = ({ maxNodes = MAX_NODES } = {}) => {
133
131
  nodes.push(text(`${nodes.length ? ' — ' : ''}${value.description}`));
134
132
  return nodes;
135
133
  };
136
- const forDocument = (models = {}) => {
134
+ const forDocument = (models = {}, settings = {}) => {
135
+ const linked = settings.schemaReferences?.mode === 'linked';
137
136
  /** Shared schemas this document already expanded, with the name later references use. */
138
137
  const shown = new Map();
139
138
  /** Models that the document renders in their own sections after the operations. */
@@ -152,6 +151,31 @@ export const createSchemaRenderer = ({ maxNodes = MAX_NODES } = {}) => {
152
151
  return nodes;
153
152
  };
154
153
  const render = (input, depth = 0, ancestors = [], options = {}) => {
154
+ if (linked && isObject(input) && '$ref' in input && typeof input.$ref === 'string') {
155
+ const target = getResolvedRef(input);
156
+ // Reference siblings are independent constraints, not replacements for target keywords.
157
+ const siblings = Object.fromEntries(Object.entries(input).filter(([key]) => !referenceKeys.has(key)));
158
+ const hasSiblings = Object.keys(siblings).length > 0;
159
+ if (depth > 0 || target === undefined) {
160
+ const name = getReferenceName(input.$ref);
161
+ const url = settings.schemaReferences?.resolveUrl?.({ ref: input.$ref, name });
162
+ const nodes = [
163
+ paragraph(text('Schema: '), url && safeUrl(url) ? link(url, name) : inlineCode(name)),
164
+ ];
165
+ if (hasSiblings)
166
+ nodes.push(...render(siblings, depth, ancestors));
167
+ return nodes;
168
+ }
169
+ // An alias with siblings is another reference boundary. Keep its reference visible
170
+ // instead of overwriting it with the outer reference during normalization.
171
+ if (hasSiblings || (isObject(target) && '$ref' in target)) {
172
+ return [
173
+ ...(hasSiblings ? [paragraph(strong(text('All of:')))] : []),
174
+ ...render(target, depth + 1, ancestors),
175
+ ...(hasSiblings ? render(siblings, depth, ancestors) : []),
176
+ ];
177
+ }
178
+ }
155
179
  // Follow the original target: merging reference siblings creates fresh objects.
156
180
  const identity = getResolvedRef(input) ?? input;
157
181
  if (typeof identity === 'object' && ancestors.includes(identity)) {
@@ -206,6 +230,13 @@ export const createSchemaRenderer = ({ maxNodes = MAX_NODES } = {}) => {
206
230
  if (annotations.length)
207
231
  nodes.push(paragraph(...annotations));
208
232
  }
233
+ if (linked) {
234
+ // A reference sibling may require a field declared only in the target schema.
235
+ const declared = new Set(value.properties.map(([name]) => name));
236
+ const required = [...value.required].filter((name) => !declared.has(name));
237
+ if (required.length)
238
+ nodes.push(paragraph(strong(text('Required fields:')), text(' '), inlineCode(required.join(', '))));
239
+ }
209
240
  if (value.properties.length) {
210
241
  const properties = value.properties.map(([name, schema]) => {
211
242
  const child = view(schema);
@@ -244,6 +275,7 @@ export const createSchemaRenderer = ({ maxNodes = MAX_NODES } = {}) => {
244
275
  return nodes;
245
276
  };
246
277
  return {
278
+ linked,
247
279
  view,
248
280
  render,
249
281
  beginSection: () => {
@@ -10,9 +10,21 @@ 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
+ };
16
28
  type PageSelectors = {
17
29
  operation: OperationSelector;
18
30
  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,GAC5B;KACG,GAAG,IAAI,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,aAAa,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC;CACnH,CAAC,MAAM,aAAa,CAAC,GACtB,OAAO,CAAC,MAAM,CAAC,MAAM,aAAa,EAAE,KAAK,CAAC,CAAC,CAAA;AAE/C,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,eAuN9F,CAAA"}
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;KAC9E,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,eA2N9F,CAAA"}
@@ -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
  }
@@ -320,9 +320,11 @@ export const selectDocument = (document, options = {}) => {
320
320
  }
321
321
  }
322
322
  };
323
- visit({ paths: selected.paths, webhooks: selected.webhooks });
324
- for (const root of modelRoots) {
325
- visit(root);
323
+ if (options.schemaReferences?.mode !== 'linked') {
324
+ visit({ paths: selected.paths, webhooks: selected.webhooks });
325
+ for (const root of modelRoots) {
326
+ visit(root);
327
+ }
326
328
  }
327
329
  selected.components = {
328
330
  ...document.components,
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "llm",
17
17
  "swagger"
18
18
  ],
19
- "version": "1.3.0",
19
+ "version": "1.4.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.15.0",
45
- "@scalar/json-magic": "0.15.2",
46
- "@scalar/openapi-upgrader": "0.4.0",
47
- "@scalar/workspace-store": "0.67.0",
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.1",
48
48
  "rehype-parse": "^9.0.1",
49
49
  "rehype-remark": "^10.0.1",
50
50
  "rehype-sanitize": "^6.0.0",