@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.
Files changed (43) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +27 -1
  3. package/dist/create-markdown-from-openapi.d.ts +5 -2
  4. package/dist/create-markdown-from-openapi.d.ts.map +1 -1
  5. package/dist/create-markdown-from-openapi.js +7 -3
  6. package/dist/document-anchors.d.ts.map +1 -1
  7. package/dist/document-anchors.js +4 -2
  8. package/dist/document-examples.d.ts.map +1 -1
  9. package/dist/document-examples.js +10 -5
  10. package/dist/get-markdown-examples.d.ts.map +1 -1
  11. package/dist/get-markdown-examples.js +48 -24
  12. package/dist/index.d.ts +1 -0
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/load-document.d.ts +8 -1
  15. package/dist/load-document.d.ts.map +1 -1
  16. package/dist/load-document.js +34 -23
  17. package/dist/markdown/index.d.ts +5 -0
  18. package/dist/markdown/index.d.ts.map +1 -0
  19. package/dist/markdown/index.js +4 -0
  20. package/dist/markdown-nodes.d.ts.map +1 -1
  21. package/dist/markdown-nodes.js +1 -0
  22. package/dist/parse-description.d.ts.map +1 -1
  23. package/dist/parse-description.js +36 -18
  24. package/dist/render-document.d.ts.map +1 -1
  25. package/dist/render-document.js +50 -26
  26. package/dist/render-examples.d.ts.map +1 -1
  27. package/dist/render-examples.js +8 -4
  28. package/dist/render-operation-details.d.ts.map +1 -1
  29. package/dist/render-operation-details.js +28 -14
  30. package/dist/render-operation.d.ts.map +1 -1
  31. package/dist/render-operation.js +60 -31
  32. package/dist/render-schema.d.ts.map +1 -1
  33. package/dist/render-schema.js +145 -77
  34. package/dist/render-security.d.ts.map +1 -1
  35. package/dist/render-security.js +12 -6
  36. package/dist/render-tags.d.ts +7 -0
  37. package/dist/render-tags.d.ts.map +1 -0
  38. package/dist/render-tags.js +73 -0
  39. package/dist/restore-boolean-schemas.d.ts.map +1 -1
  40. package/dist/restore-boolean-schemas.js +22 -11
  41. package/dist/select-document.d.ts.map +1 -1
  42. package/dist/select-document.js +5 -1
  43. package/package.json +14 -9
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # @scalar/openapi-to-markdown
2
2
 
3
+ ## 1.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#10586](https://github.com/scalar/scalar/pull/10586): Add AsyncAPI Markdown conversion with reusable renderers and individual reference pages. Share Markdown description parsing between the OpenAPI and AsyncAPI converters.
8
+
9
+ Include shared model links, contents navigation, tag pages, generated examples, and an interactive playground.
10
+
11
+ Preserve discriminators and linked schema descriptions, generate examples from primitive aliases, and compact property annotations.
12
+
13
+ Include full-export tag documentation, preserve XML schema examples, and normalize annotated primitive aliases.
14
+
15
+ Infer enum and const type labels and honor primitive-link settings in generated model examples.
16
+
17
+ Preserve AsyncAPI application and schema metadata, explain security alternatives, and render reply and unknown-address semantics accurately.
18
+
19
+ ### Patch Changes
20
+
21
+ - [#10606](https://github.com/scalar/scalar/pull/10606): Block private-network document requests by default and require an explicit basePath for local files. Apply the same permissions to external references, with an opt-in for trusted private-network inputs.
22
+ - [#10598](https://github.com/scalar/scalar/pull/10598): Preserve OpenAPI 3.2 tag ancestry in Markdown exports with parent-first breadcrumb headings.
23
+ - [#10614](https://github.com/scalar/scalar/pull/10614): Clean up lint warnings while preserving runtime behavior, and document intentional schema and type syntax.
24
+
25
+ ## 1.5.4
26
+
27
+ ### Patch Changes
28
+
29
+ - [#10559](https://github.com/scalar/scalar/pull/10559): Clean up Biome warnings in package code and tests. Handle rejected debounced callbacks and await streaming writes.
30
+ - [#10505](https://github.com/scalar/scalar/pull/10505): Apply formatting and lint compatibility changes for Biome 2.5.15.
31
+
3
32
  ## 1.5.3
4
33
 
5
34
  ### Patch Changes
package/README.md CHANGED
@@ -68,6 +68,27 @@ const operationMarkdownByPointer = await createMarkdownFromOpenApi(content, {
68
68
  })
69
69
  ```
70
70
 
71
+ ### Document loading permissions
72
+
73
+ URL inputs and external references block private, loopback, and link-local addresses by default.
74
+ Protected requests also reject redirects. File access is disabled unless you provide an approved
75
+ `basePath`; paths and symlinks outside that directory are rejected.
76
+
77
+ ```ts
78
+ const markdown = await createMarkdownFromOpenApi('./descriptions/openapi.yaml', {
79
+ documentLoading: { basePath: './descriptions' },
80
+ })
81
+
82
+ const renderer = await createOpenApiMarkdownRenderer('./descriptions/openapi.yaml', {
83
+ basePath: './descriptions',
84
+ })
85
+ ```
86
+
87
+ For trusted local development inputs, set `allowPrivateNetworks: true` in the same loading options.
88
+ This also permits redirects. Keep these permissions under application control, rather than taking
89
+ them from uploaded API descriptions or request parameters. An approved directory applies to all
90
+ files loaded during that call, including references in remote documents.
91
+
71
92
  ### Render multiple pages
72
93
 
73
94
  Create a reusable renderer when exporting several pages from the same API description.
@@ -144,7 +165,12 @@ schema expansion still tracks ancestors and stops at a depth of ten. Output may
144
165
  list spacing and normalized Markdown escaping compared with earlier versions.
145
166
 
146
167
  For OpenAPI 3.2 descriptions, tag headings use `summary` when present and otherwise
147
- use `name`. Tag selectors and operation tag metadata continue to use `name`.
168
+ use `name`. Nested tags appear parent-first with breadcrumb headings such as
169
+ `### Accounts › Billing › Invoices`. Every tag uses the same heading level, including
170
+ deeply nested tags. Parent relationships use tag names, while breadcrumb labels use
171
+ summaries when available. Missing parents and circular relationships fall back to flat
172
+ headings. Tag selectors and operation tag metadata continue to use `name`; selecting
173
+ one tag still exports only that tag and its directly tagged operations.
148
174
 
149
175
  The package only generates Markdown. To produce HTML, pass the Markdown output to a
150
176
  Markdown renderer in your application.
@@ -1,4 +1,5 @@
1
1
  import type { OpenApiDocument } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document';
2
+ import { type DocumentLoadOptions } from './load-document.js';
2
3
  import { type OpenApiRenderOptions } from './select-document.js';
3
4
  type AnyDocument = OpenApiDocument | Record<string, unknown> | string;
4
5
  /** A resolved API description that can render multiple pages without loading it again. */
@@ -9,8 +10,10 @@ export type OpenApiMarkdownRenderer = {
9
10
  * Load and resolve an API description once, then render any number of selections.
10
11
  * Each renderer owns its document; create a new renderer to pick up source changes.
11
12
  */
12
- export declare const createOpenApiMarkdownRenderer: (input: AnyDocument) => Promise<OpenApiMarkdownRenderer>;
13
+ export declare const createOpenApiMarkdownRenderer: (input: AnyDocument, options?: DocumentLoadOptions) => Promise<OpenApiMarkdownRenderer>;
13
14
  /** Generate Markdown from an API description, optionally scoped to a single page. */
14
- export declare const createMarkdownFromOpenApi: (input: AnyDocument, options?: OpenApiRenderOptions) => Promise<string>;
15
+ export declare const createMarkdownFromOpenApi: (input: AnyDocument, options?: OpenApiRenderOptions & {
16
+ documentLoading?: DocumentLoadOptions;
17
+ }) => Promise<string>;
15
18
  export {};
16
19
  //# sourceMappingURL=create-markdown-from-openapi.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-markdown-from-openapi.d.ts","sourceRoot":"","sources":["../src/create-markdown-from-openapi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAA;AAInG,OAAO,EAAE,KAAK,oBAAoB,EAAwC,MAAM,mBAAmB,CAAA;AAEnG,KAAK,WAAW,GAAG,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAA;AACrE,0FAA0F;AAC1F,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CAC5D,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,6BAA6B,GAAU,OAAO,WAAW,KAAG,OAAO,CAAC,uBAAuB,CAQvG,CAAA;AAED,qFAAqF;AACrF,eAAO,MAAM,yBAAyB,GACpC,OAAO,WAAW,EAClB,UAAU,oBAAoB,KAC7B,OAAO,CAAC,MAAM,CAGhB,CAAA"}
1
+ {"version":3,"file":"create-markdown-from-openapi.d.ts","sourceRoot":"","sources":["../src/create-markdown-from-openapi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAA;AAEnG,OAAO,EAAE,KAAK,mBAAmB,EAAgB,MAAM,iBAAiB,CAAA;AAExE,OAAO,EAAE,KAAK,oBAAoB,EAAwC,MAAM,mBAAmB,CAAA;AAEnG,KAAK,WAAW,GAAG,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAA;AACrE,0FAA0F;AAC1F,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CAC5D,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,6BAA6B,GACxC,OAAO,WAAW,EAClB,UAAU,mBAAmB,KAC5B,OAAO,CAAC,uBAAuB,CAQjC,CAAA;AAED,qFAAqF;AACrF,eAAO,MAAM,yBAAyB,GACpC,OAAO,WAAW,EAClB,UAAU,oBAAoB,GAAG;IAAE,eAAe,CAAC,EAAE,mBAAmB,CAAA;CAAE,KACzE,OAAO,CAAC,MAAM,CAOhB,CAAA"}
@@ -5,8 +5,8 @@ import { createDocumentLookup, selectDocument } from './select-document.js';
5
5
  * Load and resolve an API description once, then render any number of selections.
6
6
  * Each renderer owns its document; create a new renderer to pick up source changes.
7
7
  */
8
- export const createOpenApiMarkdownRenderer = async (input) => {
9
- const content = await loadDocument(input);
8
+ export const createOpenApiMarkdownRenderer = async (input, options) => {
9
+ const content = await loadDocument(input, options);
10
10
  const renderDocument = createDocumentRenderer();
11
11
  const lookup = createDocumentLookup(content);
12
12
  const render = async (options) => await renderDocument(selectDocument(content, options, lookup), options);
@@ -14,6 +14,10 @@ export const createOpenApiMarkdownRenderer = async (input) => {
14
14
  };
15
15
  /** Generate Markdown from an API description, optionally scoped to a single page. */
16
16
  export const createMarkdownFromOpenApi = async (input, options) => {
17
- const renderer = await createOpenApiMarkdownRenderer(input);
17
+ const renderer = await createOpenApiMarkdownRenderer(input, options?.documentLoading);
18
+ if (options && 'documentLoading' in options) {
19
+ const { documentLoading: _, ...renderOptions } = options;
20
+ return renderer.render(renderOptions);
21
+ }
18
22
  return renderer.render(options);
19
23
  };
@@ -1 +1 @@
1
- {"version":3,"file":"document-anchors.d.ts","sourceRoot":"","sources":["../src/document-anchors.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAEjC,kGAAkG;AAClG,eAAO,MAAM,qBAAqB,QAAO;IACvC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAmBhE,CAAA;AAED,qFAAqF;AACrF,eAAO,MAAM,MAAM,GAAI,IAAI,MAAM,KAAG,IAAuD,CAAA"}
1
+ {"version":3,"file":"document-anchors.d.ts","sourceRoot":"","sources":["../src/document-anchors.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAEjC,kGAAkG;AAClG,eAAO,MAAM,qBAAqB,QAAO;IACvC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAuBhE,CAAA;AAED,qFAAqF;AACrF,eAAO,MAAM,MAAM,GAAI,IAAI,MAAM,KAAG,IAAuD,CAAA"}
@@ -8,13 +8,15 @@ export const createDocumentAnchors = () => {
8
8
  get: (kind, identity, label = identity) => {
9
9
  const key = JSON.stringify([kind, identity]);
10
10
  const previous = ids.get(key);
11
- if (previous !== undefined)
11
+ if (previous !== undefined) {
12
12
  return previous;
13
+ }
13
14
  const base = `scalar-${kind}-${label}`;
14
15
  let id = slugs.slug(base);
15
16
  // A literal suffix in a later name can collide with the slugger's numeric suffix.
16
- while (used.has(id))
17
+ while (used.has(id)) {
17
18
  id = slugs.slug(base);
19
+ }
18
20
  used.add(id);
19
21
  ids.set(key, id);
20
22
  return id;
@@ -1 +1 @@
1
- {"version":3,"file":"document-examples.d.ts","sourceRoot":"","sources":["../src/document-examples.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAEjC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAC/D,OAAO,EAAE,KAAK,aAAa,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAEjF,oFAAoF;AACpF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,OAAO,mBAAmB,CAAA;IAC/B,IAAI,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,KAAK;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAA;CAC9F,CAAA;AAaD,uGAAuG;AACvG,eAAO,MAAM,sBAAsB,GAAI,SAAS,UAAU,CAAC,OAAO,qBAAqB,CAAC,KAAG,gBAqC1F,CAAA"}
1
+ {"version":3,"file":"document-examples.d.ts","sourceRoot":"","sources":["../src/document-examples.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAEjC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAC/D,OAAO,EAAE,KAAK,aAAa,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAEjF,oFAAoF;AACpF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,OAAO,mBAAmB,CAAA;IAC/B,IAAI,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,KAAK;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAA;CAC9F,CAAA;AAeD,uGAAuG;AACvG,eAAO,MAAM,sBAAsB,GAAI,SAAS,UAAU,CAAC,OAAO,qBAAqB,CAAC,KAAG,gBA4C1F,CAAA"}
@@ -4,8 +4,9 @@ import { getMarkdownExamples } from './get-markdown-examples.js';
4
4
  const bookkeeping = new Set(['$ref', '$ref-value', '$global', '$status', '__scalar_']);
5
5
  /** Sibling constraints make a reference a different example source from its target. */
6
6
  const identity = (source) => {
7
- if (!isObject(source.schema))
7
+ if (!isObject(source.schema)) {
8
8
  return undefined;
9
+ }
9
10
  const schema = source.schema;
10
11
  const target = '$ref' in schema && Object.keys(schema).every((key) => bookkeeping.has(key)) ? getResolvedRef(schema) : schema;
11
12
  return isObject(target) ? target : schema;
@@ -20,12 +21,14 @@ export const createDocumentExamples = (anchors) => {
20
21
  get: (...args) => {
21
22
  const [source, ...settings] = args;
22
23
  const schema = identity(source);
23
- if (!schema || source.example !== undefined || Object.keys(source.examples ?? {}).length)
24
+ if (!schema || source.example !== undefined || Object.keys(source.examples ?? {}).length) {
24
25
  return getMarkdownExamples(...args);
26
+ }
25
27
  const scope = JSON.stringify(settings);
26
28
  const previous = cache.get(schema)?.get(scope);
27
- if (previous)
29
+ if (previous) {
28
30
  return previous;
31
+ }
29
32
  // Large APIs must not retain every generated object until the export finishes.
30
33
  if (cachedCount >= 256) {
31
34
  cache.clear();
@@ -42,12 +45,14 @@ export const createDocumentExamples = (anchors) => {
42
45
  const schema = identity(source);
43
46
  const entries = schema ? (shown.get(schema) ?? new Map()) : new Map();
44
47
  const previous = entries.get(scope);
45
- if (previous?.value === code.value)
48
+ if (previous?.value === code.value) {
46
49
  return { id: previous.id, previous: true };
50
+ }
47
51
  const id = anchors.get('example', String(++nextId));
48
52
  entries.set(scope, { id, value: code.value });
49
- if (schema)
53
+ if (schema) {
50
54
  shown.set(schema, entries);
55
+ }
51
56
  return { id, previous: false };
52
57
  },
53
58
  };
@@ -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;IACpB,oFAAoF;IACpF,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,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,EAyCjB,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;IACpB,oFAAoF;IACpF,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,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,MAmEjG,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,EA6DjB,CAAA"}
@@ -17,35 +17,47 @@ const MAX_GENERATED_EXAMPLE_VALUES = 10_000;
17
17
  export const countGeneratedExampleValues = (root, limit = MAX_GENERATED_EXAMPLE_VALUES) => {
18
18
  const counts = new WeakMap();
19
19
  const count = (input, level) => {
20
- if (level > EXAMPLE_DEPTH || !isObject(input))
20
+ if (level > EXAMPLE_DEPTH || !isObject(input)) {
21
21
  return 1;
22
+ }
22
23
  const cached = counts.get(input)?.get(level);
23
- if (cached !== undefined)
24
+ if (cached !== undefined) {
24
25
  return cached;
26
+ }
25
27
  const schema = getResolvedRef(input, mergeSiblingReferences);
26
- if (!isObject(schema))
28
+ if (!isObject(schema)) {
27
29
  return 1;
30
+ }
28
31
  // Supplied examples bypass schema expansion in the generator too.
29
- if (schema.example !== undefined || (Array.isArray(schema.examples) && schema.examples.length > 0))
32
+ if (schema.example !== undefined || (Array.isArray(schema.examples) && schema.examples.length > 0)) {
30
33
  return 1;
34
+ }
31
35
  let total = 1;
32
36
  const add = (child) => {
33
- if (total <= limit)
37
+ if (total <= limit) {
34
38
  total += count(child, level + 1);
39
+ }
35
40
  };
36
- if (isObject(schema.properties))
41
+ if (isObject(schema.properties)) {
37
42
  Object.values(schema.properties).forEach(add);
38
- if (isObject(schema.patternProperties))
43
+ }
44
+ if (isObject(schema.patternProperties)) {
39
45
  Object.values(schema.patternProperties).forEach(add);
40
- if (isObject(schema.additionalProperties))
46
+ }
47
+ if (isObject(schema.additionalProperties)) {
41
48
  add(schema.additionalProperties);
42
- if (schema.items !== undefined)
49
+ }
50
+ if (schema.items !== undefined) {
43
51
  add(schema.items);
44
- if (Array.isArray(schema.prefixItems))
52
+ }
53
+ if (Array.isArray(schema.prefixItems)) {
45
54
  schema.prefixItems.forEach(add);
46
- if (Array.isArray(schema.allOf))
55
+ }
56
+ if (Array.isArray(schema.allOf)) {
47
57
  schema.allOf.forEach(add);
48
- const variants = Array.isArray(schema.oneOf) ? schema.oneOf : Array.isArray(schema.anyOf) ? schema.anyOf : [];
58
+ }
59
+ const anyOf = Array.isArray(schema.anyOf) ? schema.anyOf : [];
60
+ const variants = Array.isArray(schema.oneOf) ? schema.oneOf : anyOf;
49
61
  // Object and array generation can use the first variant, while other unions skip null.
50
62
  // A discriminator can choose any variant, so bound the largest candidate in that case.
51
63
  const nonNull = variants.find((variant) => {
@@ -57,8 +69,9 @@ export const countGeneratedExampleValues = (root, limit = MAX_GENERATED_EXAMPLE_
57
69
  : [variants[0], nonNull];
58
70
  let variantCount = 0;
59
71
  for (const candidate of candidates) {
60
- if (candidate !== undefined && total <= limit && variantCount <= limit)
72
+ if (candidate !== undefined && total <= limit && variantCount <= limit) {
61
73
  variantCount = Math.max(variantCount, count(candidate, level + 1));
74
+ }
62
75
  }
63
76
  total += variantCount;
64
77
  const levels = counts.get(input) ?? new Map();
@@ -72,40 +85,51 @@ export const countGeneratedExampleValues = (root, limit = MAX_GENERATED_EXAMPLE_
72
85
  export const getMarkdownExamples = (source, mediaType, mode, openapiVersion = '3.2.0',
73
86
  // Schema metadata can be upgraded while example fields still follow the original version.
74
87
  schemaOpenapiVersion = openapiVersion, linked = false) => {
75
- if (source.example !== undefined)
88
+ if (source.example !== undefined) {
76
89
  return [{ value: source.example }];
90
+ }
77
91
  if (source.examples && Object.keys(source.examples).length) {
78
92
  return Object.entries(source.examples).flatMap(([name, reference]) => {
79
93
  const example = getResolvedRef(reference);
80
- if (!isObject(example))
94
+ if (!isObject(example)) {
81
95
  return [];
96
+ }
82
97
  const metadata = {
83
98
  name,
84
99
  summary: typeof example.summary === 'string' ? example.summary : undefined,
85
100
  description: typeof example.description === 'string' ? example.description : undefined,
86
101
  };
87
- if (example.value !== undefined)
102
+ if (example.value !== undefined) {
88
103
  return [{ ...metadata, value: example.value }];
89
- if (/^3\.2\./.test(openapiVersion) && typeof example.serializedValue === 'string')
104
+ }
105
+ if (/^3\.2\./.test(openapiVersion) && typeof example.serializedValue === 'string') {
90
106
  return [{ ...metadata, serializedValue: example.serializedValue }];
91
- if (typeof example.externalValue === 'string')
107
+ }
108
+ if (typeof example.externalValue === 'string') {
92
109
  return [{ ...metadata, externalValue: example.externalValue }];
93
- if (/^3\.2\./.test(openapiVersion) && example.dataValue !== undefined)
110
+ }
111
+ if (/^3\.2\./.test(openapiVersion) && example.dataValue !== undefined) {
94
112
  return [{ ...metadata, dataValue: example.dataValue }];
113
+ }
95
114
  return [];
96
115
  });
97
116
  }
98
117
  const schema = getResolvedRef(source.schema, mergeSiblingReferences);
99
- if (!isObject(schema))
118
+ if (!isObject(schema)) {
100
119
  return [];
101
- if (schema.example !== undefined)
120
+ }
121
+ if (schema.example !== undefined) {
102
122
  return [{ value: schema.example }];
103
- if (Array.isArray(schema.examples) && schema.examples.length)
123
+ }
124
+ if (Array.isArray(schema.examples) && schema.examples.length) {
104
125
  return schema.examples.map((value) => ({ value }));
105
- if (linked)
126
+ }
127
+ if (linked) {
106
128
  return [];
107
- if (countGeneratedExampleValues(source.schema) > MAX_GENERATED_EXAMPLE_VALUES)
129
+ }
130
+ if (countGeneratedExampleValues(source.schema) > MAX_GENERATED_EXAMPLE_VALUES) {
108
131
  return [{ omitted: true }];
132
+ }
109
133
  if (isXmlMediaType(mediaType)) {
110
134
  const result = getXmlBodyExample(source.schema, undefined, {
111
135
  mode,
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
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 { DocumentLoadOptions } from './load-document.js';
4
5
  export type { OpenApiRenderOptions, OperationSelector, SchemaReferenceOptions } from './select-document.js';
5
6
  //# 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,sBAAsB,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,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAC1D,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA"}
@@ -1,4 +1,11 @@
1
1
  import { type OpenApiDocument } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document';
2
+ /** Permissions for loading an API description and its external references. */
3
+ export type DocumentLoadOptions = {
4
+ /** Allow private-network requests only for trusted input. Defaults to false. */
5
+ allowPrivateNetworks?: boolean;
6
+ /** Approved directory for local files and references. File access is disabled when omitted. */
7
+ basePath?: string;
8
+ };
2
9
  /** Coerce one plain document and keep references linked to shared targets. */
3
- export declare const loadDocument: (input: OpenApiDocument | Record<string, unknown> | string) => Promise<OpenApiDocument>;
10
+ export declare const loadDocument: (input: OpenApiDocument | Record<string, unknown> | string, options?: DocumentLoadOptions) => Promise<OpenApiDocument>;
4
11
  //# sourceMappingURL=load-document.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"load-document.d.ts","sourceRoot":"","sources":["../src/load-document.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,8DAA8D,CAAA;AA6LrE,8EAA8E;AAC9E,eAAO,MAAM,YAAY,GACvB,OAAO,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,KACxD,OAAO,CAAC,eAAe,CAgGzB,CAAA"}
1
+ {"version":3,"file":"load-document.d.ts","sourceRoot":"","sources":["../src/load-document.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,8DAA8D,CAAA;AAiMrE,8EAA8E;AAC9E,MAAM,MAAM,mBAAmB,GAAG;IAChC,gFAAgF;IAChF,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,+FAA+F;IAC/F,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,8EAA8E;AAC9E,eAAO,MAAM,YAAY,GACvB,OAAO,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EACzD,UAAS,mBAAwB,KAChC,OAAO,CAAC,eAAe,CAoGzB,CAAA"}
@@ -40,8 +40,9 @@ const attachRefValues = (document, schemas = getSchemas(document), { detectOnly
40
40
  kind = kind && getChildKind(kind, key);
41
41
  position = Array.isArray(parent) ? position : position && getChildPosition(position, key);
42
42
  // Arbitrary extension and example data has not passed an OpenAPI object schema.
43
- if (position === 'document' && kind === undefined)
43
+ if (position === 'document' && kind === undefined) {
44
44
  position = undefined;
45
+ }
45
46
  parent = getValueByPath(parent, [key]).value;
46
47
  }
47
48
  const schema = getTargetSchema(position, kind);
@@ -78,15 +79,20 @@ const attachRefValues = (document, schemas = getSchemas(document), { detectOnly
78
79
  // support summary and description; casting them as their targets would add defaults.
79
80
  // Path Item Objects declare their own $ref field, so their siblings are cast normally.
80
81
  const reference = typeof value.$ref === 'string' ? value.$ref : undefined;
81
- const cast = reference === undefined || schema === referenceTargetSchemas.pathItem
82
- ? coerceValue(schema, value)
83
- : position === 'schema'
84
- ? { ...coerceValue(SchemaObjectSchema, value), $ref: reference }
85
- : {
86
- $ref: reference,
87
- ...(typeof value.summary === 'string' ? { summary: value.summary } : {}),
88
- ...(typeof value.description === 'string' ? { description: value.description } : {}),
89
- };
82
+ let cast;
83
+ if (reference === undefined || schema === referenceTargetSchemas.pathItem) {
84
+ cast = coerceValue(schema, value);
85
+ }
86
+ else if (position === 'schema') {
87
+ cast = { ...coerceValue(SchemaObjectSchema, value), $ref: reference };
88
+ }
89
+ else {
90
+ cast = {
91
+ $ref: reference,
92
+ ...(typeof value.summary === 'string' ? { summary: value.summary } : {}),
93
+ ...(typeof value.description === 'string' ? { description: value.description } : {}),
94
+ };
95
+ }
90
96
  if (fallback?.booleanSchemas) {
91
97
  restoreBooleanSchemas(value, cast, position);
92
98
  }
@@ -147,9 +153,12 @@ const attachRefValues = (document, schemas = getSchemas(document), { detectOnly
147
153
  return hasExternalReferences;
148
154
  };
149
155
  /** Coerce one plain document and keep references linked to shared targets. */
150
- export const loadDocument = async (input) => {
156
+ export const loadDocument = async (input, options = {}) => {
151
157
  let raw;
152
158
  let origin;
159
+ const { fetchUrls, readFiles } = await import('@scalar/json-magic/bundle/plugins/node');
160
+ const urlLoader = fetchUrls({ blockPrivateNetworks: !options.allowPrivateNetworks });
161
+ const fileLoader = options.basePath === undefined ? undefined : readFiles({ basePath: options.basePath });
153
162
  // Reference links are attached below, so never mutate the caller's document.
154
163
  if (typeof input !== 'string') {
155
164
  raw = deepClone(getRaw(input));
@@ -161,17 +170,24 @@ export const loadDocument = async (input) => {
161
170
  raw = normalized;
162
171
  }
163
172
  else if (/^https?:\/\//i.test(input)) {
164
- const response = await fetch(input);
165
- if (!response.ok) {
166
- throw new Error(`Failed to load OpenAPI document (HTTP ${response.status})`);
173
+ const result = await urlLoader.exec(input);
174
+ if (!result.ok) {
175
+ throw new Error('Failed to load OpenAPI document');
167
176
  }
168
- raw = normalize(await response.text());
177
+ raw = result.data;
169
178
  origin = input;
170
179
  }
171
180
  else {
172
- const [{ resolve }, { readFile }] = await Promise.all([import('node:path'), import('node:fs/promises')]);
181
+ if (!fileLoader) {
182
+ throw new Error('Local file access requires an explicit basePath');
183
+ }
184
+ const { resolve } = await import('node:path');
173
185
  origin = resolve(input);
174
- raw = normalize(await readFile(origin, 'utf8'));
186
+ const result = await fileLoader.exec(origin);
187
+ if (!result.ok) {
188
+ throw new Error('Failed to load OpenAPI document');
189
+ }
190
+ raw = result.data;
175
191
  }
176
192
  }
177
193
  if (!isObject(raw)) {
@@ -187,12 +203,7 @@ export const loadDocument = async (input) => {
187
203
  // Resolve external targets only when the initial local-reference pass finds them.
188
204
  if (hasExternalReferences) {
189
205
  const errors = [];
190
- const plugins = typeof process === 'undefined'
191
- ? [(await import('@scalar/json-magic/bundle/plugins/browser')).fetchUrls()]
192
- : [
193
- (await import('@scalar/json-magic/bundle/plugins/node')).fetchUrls(),
194
- (await import('@scalar/json-magic/bundle/plugins/node')).readFiles(),
195
- ];
206
+ const plugins = fileLoader ? [urlLoader, fileLoader] : [urlLoader];
196
207
  document = await bundle(upgraded, {
197
208
  plugins,
198
209
  origin,
@@ -0,0 +1,5 @@
1
+ /** Format-neutral Markdown building blocks shared by API description renderers. */
2
+ export { anchor, createDocumentAnchors } from '../document-anchors.js';
3
+ export { describe, field, heading, inlineCode, item, link, list, paragraph, strong, text } from '../markdown-nodes.js';
4
+ export { createDescriptionParser, expandDescriptions } from '../parse-description.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/markdown/index.ts"],"names":[],"mappings":"AAAA,mFAAmF;AAEnF,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AACnE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AACnH,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA"}
@@ -0,0 +1,4 @@
1
+ /** Format-neutral Markdown building blocks shared by API description renderers. */
2
+ export { anchor, createDocumentAnchors } from '../document-anchors.js';
3
+ export { describe, field, heading, inlineCode, item, link, list, paragraph, strong, text } from '../markdown-nodes.js';
4
+ export { createDescriptionParser, expandDescriptions } from '../parse-description.js';
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-nodes.d.ts","sourceRoot":"","sources":["../src/markdown-nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,OAAO,EACP,UAAU,EACV,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,IAAI,EACJ,SAAS,EACT,eAAe,EACf,MAAM,EACN,IAAI,EACL,MAAM,OAAO,CAAA;AAEd;;;GAGG;AACH,KAAK,sBAAsB,GAAG,IAAI,GAAG;IAAE,IAAI,EAAE,wBAAwB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtF,OAAO,QAAQ,OAAO,CAAC;IACrB,UAAU,eAAe;QACvB,sBAAsB,EAAE,sBAAsB,CAAA;KAC/C;IACD,UAAU,cAAc;QACtB,sBAAsB,EAAE,sBAAsB,CAAA;KAC/C;CACF;AAED,gGAAgG;AAChG,eAAO,MAAM,IAAI,GAAI,OAAO,OAAO,KAAG,IAGpC,CAAA;AACF,uDAAuD;AACvD,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,UAAkE,CAAA;AAC9G,iDAAiD;AACjD,eAAO,MAAM,SAAS,GAAI,GAAG,UAAU,eAAe,EAAE,KAAG,SAA8C,CAAA;AACzG,qCAAqC;AACrC,eAAO,MAAM,MAAM,GAAI,GAAG,UAAU,eAAe,EAAE,KAAG,MAAwC,CAAA;AAChG,oEAAoE;AACpE,eAAO,MAAM,QAAQ,GAAI,GAAG,UAAU,eAAe,EAAE,KAAG,QAA4C,CAAA;AACtG,mCAAmC;AACnC,eAAO,MAAM,OAAO,GAAI,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,GAAG,UAAU,eAAe,EAAE,KAAG,OAIhF,CAAA;AACF,4DAA4D;AAC5D,eAAO,MAAM,IAAI,GAAI,GAAG,UAAU,QAAQ,CAAC,UAAU,CAAC,KAAG,QAA2D,CAAA;AACpH,mCAAmC;AACnC,eAAO,MAAM,IAAI,GAAI,UAAU,QAAQ,EAAE,KAAG,IAAmE,CAAA;AAC/G;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,KAAG,MAIrC,CAAA;AACD,8EAA8E;AAC9E,eAAO,MAAM,IAAI,GAAI,KAAK,MAAM,EAAE,OAAO,MAAM,KAAG,IAAsE,CAAA;AACxH,oFAAoF;AACpF,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,EAAE,OAAO,eAAe,KAAG,QACK,CAAA;AACnE,0FAA0F;AAC1F,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,sBAAsB,EAC8B,CAAA"}
1
+ {"version":3,"file":"markdown-nodes.d.ts","sourceRoot":"","sources":["../src/markdown-nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,OAAO,EACP,UAAU,EACV,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,IAAI,EACJ,SAAS,EACT,eAAe,EACf,MAAM,EACN,IAAI,EACL,MAAM,OAAO,CAAA;AAEd;;;GAGG;AACH,KAAK,sBAAsB,GAAG,IAAI,GAAG;IAAE,IAAI,EAAE,wBAAwB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtF,OAAO,QAAQ,OAAO,CAAC;IACrB,UAAU,eAAe;QACvB,sBAAsB,EAAE,sBAAsB,CAAA;KAC/C;IACD,UAAU,cAAc;QACtB,sBAAsB,EAAE,sBAAsB,CAAA;KAC/C;CACF;AAED,gGAAgG;AAChG,eAAO,MAAM,IAAI,GAAI,OAAO,OAAO,KAAG,IAGpC,CAAA;AACF,uDAAuD;AACvD,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,UAAkE,CAAA;AAC9G,iDAAiD;AACjD,eAAO,MAAM,SAAS,GAAI,GAAG,UAAU,eAAe,EAAE,KAAG,SAA8C,CAAA;AACzG,qCAAqC;AACrC,eAAO,MAAM,MAAM,GAAI,GAAG,UAAU,eAAe,EAAE,KAAG,MAAwC,CAAA;AAChG,oEAAoE;AACpE,eAAO,MAAM,QAAQ,GAAI,GAAG,UAAU,eAAe,EAAE,KAAG,QAA4C,CAAA;AACtG,mCAAmC;AACnC,eAAO,MAAM,OAAO,GAAI,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,GAAG,UAAU,eAAe,EAAE,KAAG,OAIhF,CAAA;AACF,4DAA4D;AAC5D,eAAO,MAAM,IAAI,GAAI,GAAG,UAAU,QAAQ,CAAC,UAAU,CAAC,KAAG,QAA2D,CAAA;AACpH,mCAAmC;AACnC,eAAO,MAAM,IAAI,GAAI,UAAU,QAAQ,EAAE,KAAG,IAAmE,CAAA;AAC/G;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,KAAG,MAKrC,CAAA;AACD,8EAA8E;AAC9E,eAAO,MAAM,IAAI,GAAI,KAAK,MAAM,EAAE,OAAO,MAAM,KAAG,IAAsE,CAAA;AACxH,oFAAoF;AACpF,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,EAAE,OAAO,eAAe,KAAG,QACK,CAAA;AACnE,0FAA0F;AAC1F,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,sBAAsB,EAC8B,CAAA"}
@@ -26,6 +26,7 @@ export const list = (children) => ({ type: 'list', ordered: false, spread: false
26
26
  * additional schemes and excludes IRC/XMPP, so it is not compatible here.
27
27
  */
28
28
  export const safeUrl = (url) => {
29
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: Control characters are intentionally matched to validate or sanitize input.
29
30
  const normalized = url.replace(/[\u0000-\u0020\u007f-\u009f]/g, '');
30
31
  const protocol = /^([^/?#]*):/.exec(normalized)?.[1];
31
32
  return protocol && !['http', 'https', 'irc', 'ircs', 'mailto', 'xmpp'].includes(protocol.toLowerCase()) ? '' : url;
@@ -1 +1 @@
1
- {"version":3,"file":"parse-description.d.ts","sourceRoot":"","sources":["../src/parse-description.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,WAAW,EAAE,MAAM,OAAO,CAAA;AAkF7D,0FAA0F;AAC1F,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAA;AAE1E,mGAAmG;AACnG,eAAO,MAAM,uBAAuB,QAAO,CAAC,MAAM,iBAAiB,CA4ClE,CAAA;AAED,6FAA6F;AAC7F,eAAO,MAAM,kBAAkB,GAAU,OAAO,WAAW,EAAE,EAAE,aAAa,iBAAiB,KAAG,OAAO,CAAC,IAAI,CAe3G,CAAA"}
1
+ {"version":3,"file":"parse-description.d.ts","sourceRoot":"","sources":["../src/parse-description.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,WAAW,EAAE,MAAM,OAAO,CAAA;AAsG7D,0FAA0F;AAC1F,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAA;AAE1E,mGAAmG;AACnG,eAAO,MAAM,uBAAuB,QAAO,CAAC,MAAM,iBAAiB,CAuDlE,CAAA;AAED,6FAA6F;AAC7F,eAAO,MAAM,kBAAkB,GAAU,OAAO,WAAW,EAAE,EAAE,aAAa,iBAAiB,KAAG,OAAO,CAAC,IAAI,CAkB3G,CAAA"}