@scalar/api-reference 1.60.0 → 1.61.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 (179) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/browser/chunks/{AgentScalarChatInterface-CesFQ_Ax.js → AgentScalarChatInterface-BhUn0w1j.js} +2 -2
  3. package/dist/browser/chunks/{ScalarTextInput.vue-C14zmVNI.js → ScalarTextInput.vue-BUzf4Z_k.js} +2 -2
  4. package/dist/browser/chunks/basic-shape-diamond.svg-BTEOT1FL.js +1 -1
  5. package/dist/browser/chunks/basic-shape-hexagon.svg-BSPzaCgF.js +1 -1
  6. package/dist/browser/chunks/basic-shape-primary-circle-ellipse-round.svg-DKmZ8UUU.js +1 -1
  7. package/dist/browser/chunks/basic-shape-primary-square-rectangle.svg-n2YRykHD.js +1 -1
  8. package/dist/browser/chunks/basic-shape-shield.svg-Bec9cJDA.js +1 -1
  9. package/dist/browser/chunks/browser-67K6wmG9.js +1 -1
  10. package/dist/browser/chunks/computer-device-desktop-monitor.svg-m6j893Hb.js +1 -1
  11. package/dist/browser/chunks/computer-device-desktop.svg-Dk1VVO7k.js +1 -1
  12. package/dist/browser/chunks/computer-device-laptop.svg-BNGVUCYS.js +1 -1
  13. package/dist/browser/chunks/computer-device-mobile-phone-android-samsung-back.svg-CC4UUTFw.js +1 -1
  14. package/dist/browser/chunks/computer-device-mobile-phone-android-samsung.svg-D8ExpMpL.js +1 -1
  15. package/dist/browser/chunks/computer-device-mobile-phone-iphone-x-back.svg-CLm7sgMM.js +1 -1
  16. package/dist/browser/chunks/computer-device-mobile-phone-iphone-x.svg-Xrttg6_7.js +1 -1
  17. package/dist/browser/chunks/computer-device-mobile-tablet-touch.svg-DQ2oTvOG.js +1 -1
  18. package/dist/browser/chunks/computer-device-mobile-tablet.svg-DCr0XlRc.js +1 -1
  19. package/dist/browser/chunks/computer-device-network-ethernet-cat6.svg-AK9l0iOl.js +1 -1
  20. package/dist/browser/chunks/computer-device-network-lan-www.svg-gUIdFBlE.js +1 -1
  21. package/dist/browser/chunks/computer-device-network-wifi-connection.svg-Be-EMm4e.js +1 -1
  22. package/dist/browser/chunks/computer-device-network-wifi-router.svg-Dc2VzyqK.js +1 -1
  23. package/dist/browser/chunks/ecology-science-erlenmeyer-flask.svg-DHgy7Jfd.js +1 -1
  24. package/dist/browser/chunks/image-flash-lightning.svg-EETR_y1q.js +1 -1
  25. package/dist/browser/chunks/image-picture-flower.svg-DN1AYzJU.js +1 -1
  26. package/dist/browser/chunks/interface-alert-exclamation-diamond.svg-C5NozMV_.js +1 -1
  27. package/dist/browser/chunks/interface-alert-exclamation-triangle-warning.svg-DaAg2fF5.js +1 -1
  28. package/dist/browser/chunks/interface-alert-information-circle.svg-ckkkt9Mv.js +1 -1
  29. package/dist/browser/chunks/interface-award-crown.svg-pjvn9hY-.js +1 -1
  30. package/dist/browser/chunks/interface-bookmark-tag.svg-r2r-lQq4.js +1 -1
  31. package/dist/browser/chunks/interface-bookmark.svg-BK9HKQBT.js +1 -1
  32. package/dist/browser/chunks/interface-calendar-date-one.svg-DNnF0M1I.js +1 -1
  33. package/dist/browser/chunks/interface-content-book-open-pages.svg-CQj_w9Vp.js +1 -1
  34. package/dist/browser/chunks/interface-content-book-page.svg-DppoeJRe.js +1 -1
  35. package/dist/browser/chunks/interface-content-file.svg-CvcD7OiY.js +1 -1
  36. package/dist/browser/chunks/interface-content-folder.svg-BmtS5I9A.js +1 -1
  37. package/dist/browser/chunks/interface-copy-clipboard.svg-Be6EI50X.js +1 -1
  38. package/dist/browser/chunks/interface-edit-attachment.svg-G5TKzpWX.js +1 -1
  39. package/dist/browser/chunks/interface-edit-binocular.svg-jzL-DvGB.js +1 -1
  40. package/dist/browser/chunks/interface-edit-magic-wand.svg-BOTlymvp.js +1 -1
  41. package/dist/browser/chunks/interface-edit-tool-paint-roller.svg-s9dwryx7.js +1 -1
  42. package/dist/browser/chunks/interface-edit-tool-pencil.svg-C7v0dbB3.js +1 -1
  43. package/dist/browser/chunks/interface-favorite-award.svg-CYHUgUG0.js +1 -1
  44. package/dist/browser/chunks/interface-favorite-flag.svg-C10zlKOb.js +1 -1
  45. package/dist/browser/chunks/interface-favorite-heart.svg-eoduXxlz.js +1 -1
  46. package/dist/browser/chunks/interface-favorite-star.svg-BSmxJetr.js +1 -1
  47. package/dist/browser/chunks/interface-favorite-stars-sparkles.svg-JTFLj3Ls.js +1 -1
  48. package/dist/browser/chunks/interface-hierarchy-flowchart.svg-Cg_Wy0kN.js +1 -1
  49. package/dist/browser/chunks/interface-home-house.svg-DytoGRnv.js +1 -1
  50. package/dist/browser/chunks/interface-hyperlink.svg-CuEfmmQI.js +1 -1
  51. package/dist/browser/chunks/interface-lighting-brightness.svg-DSK0h_Pa.js +1 -1
  52. package/dist/browser/chunks/interface-lock-closed.svg-Cn6TaLYv.js +1 -1
  53. package/dist/browser/chunks/interface-lock-open-unlock.svg-CVkG5-9W.js +1 -1
  54. package/dist/browser/chunks/interface-login-key.svg-y-cwwXjN.js +1 -1
  55. package/dist/browser/chunks/interface-search.svg-S-puVFJB.js +1 -1
  56. package/dist/browser/chunks/interface-setting-cog.svg-CTH4_lLg.js +1 -1
  57. package/dist/browser/chunks/interface-share-megaphone-bullhorn.svg-Pbp39MyC.js +1 -1
  58. package/dist/browser/chunks/interface-share-rocket.svg-BgCsIRZO.js +1 -1
  59. package/dist/browser/chunks/interface-share-satellite.svg-DAMN9d5G.js +1 -1
  60. package/dist/browser/chunks/interface-share-space-ship.svg-Dt-Mejxk.js +1 -1
  61. package/dist/browser/chunks/interface-share.svg-vFYTXSti.js +1 -1
  62. package/dist/browser/chunks/interface-signal-square.svg-DNG4LpAe.js +1 -1
  63. package/dist/browser/chunks/interface-time-clock-circle.svg-Bpz-nLxo.js +1 -1
  64. package/dist/browser/chunks/interface-time-hour-glass.svg-D7agfKsH.js +1 -1
  65. package/dist/browser/chunks/interface-users-multiple.svg-CkPJBBnG.js +1 -1
  66. package/dist/browser/chunks/interface-weather-moon.svg-CaTZFMPO.js +1 -1
  67. package/dist/browser/chunks/mail-chat-bubble-square.svg-DC8RIihp.js +1 -1
  68. package/dist/browser/chunks/mail-send-email-paper-airplane.svg-D8OLs9jz.js +1 -1
  69. package/dist/browser/chunks/mail-send-envelope.svg-CV33h5Sx.js +1 -1
  70. package/dist/browser/chunks/{modal-LBDjZSmM.js → modal-CKthJJWy.js} +2 -2
  71. package/dist/browser/chunks/{modal-BZzcBkVp.js → modal-CZI71Aau.js} +19 -19
  72. package/dist/browser/chunks/money-cashier-receipt.svg-CJL8C2gs.js +1 -1
  73. package/dist/browser/chunks/money-currency-dollar-pay.svg-VdBplCTx.js +1 -1
  74. package/dist/browser/chunks/money-graph-arrow-increase.svg-DcRov3zk.js +1 -1
  75. package/dist/browser/chunks/money-graph-bar-chart-increase.svg-Cc7KxjX-.js +1 -1
  76. package/dist/browser/chunks/nature-ecology-leaf.svg-DR3cTZxt.js +1 -1
  77. package/dist/browser/chunks/phone-telephone.svg-DyY0gUlk.js +1 -1
  78. package/dist/browser/chunks/programming-bug.svg-BHLT-Qhp.js +1 -1
  79. package/dist/browser/chunks/programming-cloud.svg-B6YW33ba.js +1 -1
  80. package/dist/browser/chunks/programming-computer-database-server.svg-B6o5Sdn-.js +1 -1
  81. package/dist/browser/chunks/programming-computer-database.svg-Cl7OVtpJ.js +1 -1
  82. package/dist/browser/chunks/programming-module-four-layout.svg-BQrerL1x.js +1 -1
  83. package/dist/browser/chunks/programming-module-three.svg-B2KTQzBM.js +1 -1
  84. package/dist/browser/chunks/programming-module.svg-CiID7kPm.js +1 -1
  85. package/dist/browser/chunks/programming-script-code.svg-D1M5rtkN.js +1 -1
  86. package/dist/browser/chunks/runtime-core.esm-bundler-Byrbbu5Q.js +1 -1
  87. package/dist/browser/chunks/shopping-cart.svg-BEegiIR9.js +1 -1
  88. package/dist/browser/chunks/shopping-gift-present.svg-BUHwuLix.js +1 -1
  89. package/dist/browser/chunks/shopping-shipping-box-parcel-package.svg-D6fxWdYx.js +1 -1
  90. package/dist/browser/chunks/tag-new-circle.svg-jsg1bGs0.js +1 -1
  91. package/dist/browser/chunks/travel-map-earth-globe.svg-ClbMiU-f.js +1 -1
  92. package/dist/browser/chunks/{vendor-wW8jg8wN.js → vendor-BeJNu9KM.js} +2 -2
  93. package/dist/browser/standalone.esm.js +6 -6
  94. package/dist/browser/standalone.js +248 -248
  95. package/dist/components/ApiReference.vue.d.ts.map +1 -1
  96. package/dist/components/ApiReference.vue.js +1 -1
  97. package/dist/components/ApiReference.vue.js.map +1 -1
  98. package/dist/components/ApiReference.vue.script.js +12 -6
  99. package/dist/components/ApiReference.vue.script.js.map +1 -1
  100. package/dist/components/Content/AsyncApi/AsyncApiLabels.vue.d.ts +10 -0
  101. package/dist/components/Content/AsyncApi/AsyncApiLabels.vue.d.ts.map +1 -0
  102. package/dist/components/Content/AsyncApi/AsyncApiLabels.vue.js +9 -0
  103. package/dist/components/Content/AsyncApi/AsyncApiLabels.vue.js.map +1 -0
  104. package/dist/components/Content/AsyncApi/AsyncApiLabels.vue.script.js +43 -0
  105. package/dist/components/Content/AsyncApi/AsyncApiLabels.vue.script.js.map +1 -0
  106. package/dist/components/Content/AsyncApi/AsyncApiTraversedEntry.vue.d.ts.map +1 -1
  107. package/dist/components/Content/AsyncApi/AsyncApiTraversedEntry.vue.js.map +1 -1
  108. package/dist/components/Content/AsyncApi/AsyncApiTraversedEntry.vue.script.js +2 -0
  109. package/dist/components/Content/AsyncApi/AsyncApiTraversedEntry.vue.script.js.map +1 -1
  110. package/dist/components/Content/AsyncApi/Channel.vue.d.ts +4 -1
  111. package/dist/components/Content/AsyncApi/Channel.vue.d.ts.map +1 -1
  112. package/dist/components/Content/AsyncApi/Channel.vue.js +1 -1
  113. package/dist/components/Content/AsyncApi/Channel.vue.js.map +1 -1
  114. package/dist/components/Content/AsyncApi/Channel.vue.script.js +98 -44
  115. package/dist/components/Content/AsyncApi/Channel.vue.script.js.map +1 -1
  116. package/dist/components/Content/AsyncApi/Message.vue.d.ts +18 -0
  117. package/dist/components/Content/AsyncApi/Message.vue.d.ts.map +1 -0
  118. package/dist/components/Content/AsyncApi/Message.vue.js +9 -0
  119. package/dist/components/Content/AsyncApi/Message.vue.js.map +1 -0
  120. package/dist/components/Content/AsyncApi/Message.vue.script.js +159 -0
  121. package/dist/components/Content/AsyncApi/Message.vue.script.js.map +1 -0
  122. package/dist/components/Content/AsyncApi/Operation.vue.d.ts +18 -0
  123. package/dist/components/Content/AsyncApi/Operation.vue.d.ts.map +1 -0
  124. package/dist/components/Content/AsyncApi/Operation.vue.js +9 -0
  125. package/dist/components/Content/AsyncApi/Operation.vue.js.map +1 -0
  126. package/dist/components/Content/AsyncApi/Operation.vue.script.js +84 -0
  127. package/dist/components/Content/AsyncApi/Operation.vue.script.js.map +1 -0
  128. package/dist/components/Content/AsyncApi/helpers/async-api-render-options.d.ts +14 -0
  129. package/dist/components/Content/AsyncApi/helpers/async-api-render-options.d.ts.map +1 -0
  130. package/dist/components/Content/AsyncApi/helpers/async-api-render-options.js +14 -0
  131. package/dist/components/Content/AsyncApi/helpers/async-api-render-options.js.map +1 -0
  132. package/dist/components/Content/AsyncApi/helpers/filter-children-by-type.d.ts +9 -0
  133. package/dist/components/Content/AsyncApi/helpers/filter-children-by-type.d.ts.map +1 -0
  134. package/dist/components/Content/AsyncApi/helpers/filter-children-by-type.js +12 -0
  135. package/dist/components/Content/AsyncApi/helpers/filter-children-by-type.js.map +1 -0
  136. package/dist/components/Content/AsyncApi/helpers/get-async-api-labels.d.ts +13 -0
  137. package/dist/components/Content/AsyncApi/helpers/get-async-api-labels.d.ts.map +1 -0
  138. package/dist/components/Content/AsyncApi/helpers/get-async-api-labels.js +23 -0
  139. package/dist/components/Content/AsyncApi/helpers/get-async-api-labels.js.map +1 -0
  140. package/dist/components/Content/AsyncApi/helpers/pick-heading.d.ts +10 -0
  141. package/dist/components/Content/AsyncApi/helpers/pick-heading.d.ts.map +1 -0
  142. package/dist/components/Content/AsyncApi/helpers/pick-heading.js +20 -0
  143. package/dist/components/Content/AsyncApi/helpers/pick-heading.js.map +1 -0
  144. package/dist/components/Content/AsyncApi/helpers/resolve-async-api-nodes.d.ts +21 -0
  145. package/dist/components/Content/AsyncApi/helpers/resolve-async-api-nodes.d.ts.map +1 -0
  146. package/dist/components/Content/AsyncApi/helpers/resolve-async-api-nodes.js +35 -0
  147. package/dist/components/Content/AsyncApi/helpers/resolve-async-api-nodes.js.map +1 -0
  148. package/dist/components/Content/Schema/Schema.vue.d.ts.map +1 -1
  149. package/dist/components/Content/Schema/Schema.vue.js +1 -1
  150. package/dist/components/Content/Schema/Schema.vue.js.map +1 -1
  151. package/dist/components/Content/Schema/Schema.vue.script.js +2 -1
  152. package/dist/components/Content/Schema/Schema.vue.script.js.map +1 -1
  153. package/dist/components/Content/Schema/SchemaComposition.vue.d.ts.map +1 -1
  154. package/dist/components/Content/Schema/SchemaComposition.vue.js.map +1 -1
  155. package/dist/components/Content/Schema/SchemaComposition.vue.script.js +16 -1
  156. package/dist/components/Content/Schema/SchemaComposition.vue.script.js.map +1 -1
  157. package/dist/components/Content/Schema/SchemaHeading.vue.script.js +1 -1
  158. package/dist/components/Content/Schema/SchemaProperty.vue.d.ts.map +1 -1
  159. package/dist/components/Content/Schema/SchemaProperty.vue.js +1 -1
  160. package/dist/components/Content/Schema/SchemaProperty.vue.js.map +1 -1
  161. package/dist/components/Content/Schema/SchemaProperty.vue.script.js +21 -6
  162. package/dist/components/Content/Schema/SchemaProperty.vue.script.js.map +1 -1
  163. package/dist/components/Content/Schema/helpers/merge-all-of-schemas.d.ts.map +1 -1
  164. package/dist/components/Content/Schema/helpers/merge-all-of-schemas.js +10 -9
  165. package/dist/components/Content/Schema/helpers/merge-all-of-schemas.js.map +1 -1
  166. package/dist/helpers/get-async-api-message-payload-schema.d.ts +18 -0
  167. package/dist/helpers/get-async-api-message-payload-schema.d.ts.map +1 -0
  168. package/dist/helpers/get-async-api-message-payload-schema.js +33 -0
  169. package/dist/helpers/get-async-api-message-payload-schema.js.map +1 -0
  170. package/dist/helpers/get-async-api-model-schema.d.ts.map +1 -1
  171. package/dist/helpers/get-async-api-model-schema.js +2 -11
  172. package/dist/helpers/get-async-api-model-schema.js.map +1 -1
  173. package/dist/helpers/map-config-plugins.d.ts +8 -3
  174. package/dist/helpers/map-config-plugins.d.ts.map +1 -1
  175. package/dist/helpers/map-config-plugins.js +22 -4
  176. package/dist/helpers/map-config-plugins.js.map +1 -1
  177. package/dist/style.css +416 -311
  178. package/dist/vue-styles.css +398 -298
  179. package/package.json +12 -12
@@ -1 +1 @@
1
- {"version":3,"file":"SchemaComposition.vue.js","names":[],"sources":["../../../../src/components/Content/Schema/SchemaComposition.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport {\n ScalarListbox,\n type ScalarListboxOption,\n} from '@scalar/components/listbox'\nimport { isDefined } from '@scalar/helpers/array/is-defined'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type {\n DiscriminatorObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, inject, ref, watch } from 'vue'\n\nimport type { SchemaOptions } from '@/components/Content/Schema/types'\nimport {\n REQUEST_BODY_COMPOSITION_INDEX_SYMBOL,\n type RequestBodyCompositionSelection,\n} from '@/features/Operation/request-body-composition-index'\n\nimport { getSchemaType } from './helpers/get-schema-type'\nimport { mergeAllOfSchemas } from './helpers/merge-all-of-schemas'\nimport { type CompositionKeyword } from './helpers/schema-composition'\nimport { getCycleKey } from './helpers/schema-cycle'\nimport { getModelNameFromSchema } from './helpers/schema-name'\nimport Schema from './Schema.vue'\n\nconst props = withDefaults(\n defineProps<{\n /** The composition keyword (oneOf, anyOf, allOf) */\n composition: CompositionKeyword\n /** Optional discriminator object for polymorphic schemas */\n discriminator?: DiscriminatorObject\n /** Optional name for the schema */\n name?: string\n /** The schema value containing the composition */\n schema: SchemaObject\n /** Nesting level for proper indentation */\n level: number\n /** Whether to use compact layout */\n compact?: boolean\n /** Whether to hide the heading */\n hideHeading?: boolean\n /** Hide model names in type display */\n hideModelNames?: boolean\n /** Breadcrumb for navigation */\n breadcrumb?: string[]\n /** Event bus emitting actions */\n eventBus: WorkspaceEventBus | null\n /** Move the options into single prop so they are easy to pass around */\n options: SchemaOptions\n /** When \"requestBody\", sync selected index with the example snippet */\n schemaContext?: string\n /** Internal path used to sync nested request body compositions with the code sample */\n compositionPath?: string[]\n }>(),\n {\n compact: false,\n hideHeading: false,\n },\n)\n\n/** The current composition */\nconst composition = computed(() =>\n [props.schema[props.composition]]\n .flat()\n .map((schema) => ({ value: resolve.schema(schema), original: schema }))\n .filter((it) => isDefined(it.value)),\n)\n\n/**\n * Generate listbox options for the composition selector.\n * Each option represents a schema in the composition with a human-readable label.\n * Prefers schema title/name over structural type when present.\n */\nconst listboxOptions = computed((): ScalarListboxOption[] =>\n composition.value.map((schema, index: number) => {\n const resolved = resolve.schema(schema.original!)\n const label =\n (getModelNameFromSchema(resolved)?.label ?? getSchemaType(resolved)) ||\n 'Schema'\n return { id: String(index), label }\n }),\n)\n\nconst compositionSelectionKey = computed(() =>\n props.compositionPath?.length\n ? [...props.compositionPath, props.composition].join('.')\n : '',\n)\n\n/** When this composition is in the request body, sync selection with the example snippet */\nconst requestBodyCompositionSelectionRef = inject(\n REQUEST_BODY_COMPOSITION_INDEX_SYMBOL,\n undefined,\n)\n\nconst initialSelectedIndex = computed(() => {\n if (\n props.schemaContext !== 'requestBody' ||\n !requestBodyCompositionSelectionRef?.value ||\n !compositionSelectionKey.value\n ) {\n return 0\n }\n\n const selectedIndex =\n requestBodyCompositionSelectionRef.value[compositionSelectionKey.value]\n\n if (typeof selectedIndex !== 'number' || Number.isNaN(selectedIndex)) {\n return 0\n }\n\n return Math.max(0, Math.min(selectedIndex, listboxOptions.value.length - 1))\n})\n\n/**\n * Two-way computed property for the selected option.\n * Handles conversion between the selected index and the listbox option format.\n */\nconst selectedOption = ref<ScalarListboxOption | undefined>()\n\nwatch(\n [listboxOptions, initialSelectedIndex],\n ([options, selectedIndex]) => {\n if (\n !selectedOption.value ||\n !options.some((option) => option.id === selectedOption.value?.id)\n ) {\n selectedOption.value = options[selectedIndex] ?? options[0]\n }\n },\n { immediate: true },\n)\n\n/**\n * Humanize composition keyword name for display.\n * Converts camelCase to Title Case (e.g., oneOf -> One of).\n */\nconst humanizeType = (type: CompositionKeyword): string =>\n type\n .replace(/([A-Z])/g, ' $1')\n .replace(/^./, (str) => str.toUpperCase())\n .toLowerCase()\n .replace(/^(\\w)/, (c) => c.toUpperCase())\n\n/** Inside the currently selected composition */\nconst selectedComposition = computed(\n () => composition.value[Number(selectedOption.value?.id ?? '0')]?.value,\n)\n\n/**\n * Cycle key for the selected composition member, derived from its raw\n * (unresolved) value so a member that references an ancestor is detected as a\n * cycle.\n */\nconst selectedCompositionCycleKey = computed(() =>\n getCycleKey(\n composition.value[Number(selectedOption.value?.id ?? '0')]?.original,\n ),\n)\n\n/**\n * Controls whether the nested schema is displayed. When expanding all schema\n * properties we open it by default; the nested Schema handles cycle detection,\n * so finite compositions render fully while recursive ones still stop.\n */\nconst showNestedSchema = ref(!!props.options.expandAllSchemaProperties)\n\nif (\n requestBodyCompositionSelectionRef &&\n props.schemaContext === 'requestBody' &&\n compositionSelectionKey.value\n) {\n watch(\n selectedOption,\n (option) => {\n const index = option ? Number(option.id) : 0\n if (!Number.isNaN(index)) {\n requestBodyCompositionSelectionRef.value = {\n ...requestBodyCompositionSelectionRef.value,\n [compositionSelectionKey.value]: index,\n } satisfies RequestBodyCompositionSelection\n }\n },\n { immediate: true },\n )\n}\n</script>\n\n<template>\n <div class=\"property-rule\">\n <!-- We merge allOf schemas into a single schema -->\n <Schema\n v-if=\"props.composition === 'allOf'\"\n :breadcrumb=\"breadcrumb\"\n :compact=\"compact\"\n :compositionPath=\"compositionPath\"\n :discriminator=\"discriminator\"\n :eventBus=\"eventBus\"\n :hideHeading=\"hideHeading\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"true\"\n :options=\"options\"\n :schema=\"mergeAllOfSchemas(schema)\"\n :schemaContext=\"schemaContext\" />\n\n <template v-else>\n <!-- Composition selector and panel for nested compositions -->\n <ScalarListbox\n v-model=\"selectedOption\"\n :options=\"listboxOptions\"\n resize>\n <button\n class=\"composition-selector bg-b-1.5 hover:bg-b-2 flex w-full cursor-pointer items-center gap-1 rounded-t-lg border px-2.5 py-2.5 pr-3 text-left\"\n type=\"button\">\n <span class=\"text-c-2\">{{ humanizeType(props.composition) }}</span>\n <span\n class=\"composition-selector-label text-c-1\"\n :class=\"{\n 'line-through': selectedComposition?.deprecated,\n }\">\n {{ selectedOption?.label || 'Schema' }}\n </span>\n <div\n v-if=\"selectedComposition?.deprecated\"\n class=\"text-red\">\n deprecated\n </div>\n <ScalarIconCaretDown />\n </button>\n </ScalarListbox>\n\n <div class=\"composition-panel\">\n <!-- Button to toggle nested schema display -->\n <button\n v-if=\"!showNestedSchema && level > 2\"\n class=\"bg-b-1 hover:bg-b-2 text-c-1 flex w-full items-center justify-center gap-2 rounded-b-lg border border-t-0 px-2 py-2 text-sm font-medium transition-colors\"\n type=\"button\"\n @click=\"showNestedSchema = true\">\n Show Schema Details\n <ScalarIconCaretDown class=\"h-3 w-3\" />\n </button>\n\n <!-- Render the selected schema if it has content to display -->\n <Schema\n v-else\n :key=\"selectedOption?.id ?? '0'\"\n :breadcrumb=\"breadcrumb\"\n :compact=\"compact\"\n :compositionPath=\"compositionPath\"\n :cycleKey=\"selectedCompositionCycleKey\"\n :discriminator=\"discriminator\"\n :eventBus=\"eventBus\"\n :hideHeading=\"hideHeading\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"true\"\n :options=\"options\"\n :schema=\"selectedComposition\"\n :schemaContext=\"schemaContext\" />\n </div>\n </template>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"SchemaComposition.vue.js","names":[],"sources":["../../../../src/components/Content/Schema/SchemaComposition.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport {\n ScalarListbox,\n type ScalarListboxOption,\n} from '@scalar/components/listbox'\nimport { isDefined } from '@scalar/helpers/array/is-defined'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type {\n DiscriminatorObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, inject, ref, watch } from 'vue'\n\nimport type { SchemaOptions } from '@/components/Content/Schema/types'\nimport {\n REQUEST_BODY_COMPOSITION_INDEX_SYMBOL,\n type RequestBodyCompositionSelection,\n} from '@/features/Operation/request-body-composition-index'\n\nimport { getSchemaType } from './helpers/get-schema-type'\nimport { mergeAllOfSchemas } from './helpers/merge-all-of-schemas'\nimport { type CompositionKeyword } from './helpers/schema-composition'\nimport { getCycleKey } from './helpers/schema-cycle'\nimport { getModelNameFromSchema } from './helpers/schema-name'\nimport Schema from './Schema.vue'\n\nconst props = withDefaults(\n defineProps<{\n /** The composition keyword (oneOf, anyOf, allOf) */\n composition: CompositionKeyword\n /** Optional discriminator object for polymorphic schemas */\n discriminator?: DiscriminatorObject\n /** Optional name for the schema */\n name?: string\n /** The schema value containing the composition */\n schema: SchemaObject\n /** Nesting level for proper indentation */\n level: number\n /** Whether to use compact layout */\n compact?: boolean\n /** Whether to hide the heading */\n hideHeading?: boolean\n /** Hide model names in type display */\n hideModelNames?: boolean\n /** Breadcrumb for navigation */\n breadcrumb?: string[]\n /** Event bus emitting actions */\n eventBus: WorkspaceEventBus | null\n /** Move the options into single prop so they are easy to pass around */\n options: SchemaOptions\n /** When \"requestBody\", sync selected index with the example snippet */\n schemaContext?: string\n /** Internal path used to sync nested request body compositions with the code sample */\n compositionPath?: string[]\n }>(),\n {\n compact: false,\n hideHeading: false,\n },\n)\n\n/** The current composition */\nconst composition = computed(() =>\n [props.schema[props.composition]]\n .flat()\n .map((schema) => ({ value: resolve.schema(schema), original: schema }))\n .filter((it) => isDefined(it.value)),\n)\n\n/**\n * Generate listbox options for the composition selector.\n * Each option represents a schema in the composition with a human-readable label.\n * Prefers schema title/name over structural type when present.\n */\nconst listboxOptions = computed((): ScalarListboxOption[] =>\n composition.value.map((schema, index: number) => {\n const resolved = resolve.schema(schema.original!)\n const label =\n (getModelNameFromSchema(resolved)?.label ?? getSchemaType(resolved)) ||\n 'Schema'\n return { id: String(index), label }\n }),\n)\n\nconst compositionSelectionKey = computed(() =>\n props.compositionPath?.length\n ? [...props.compositionPath, props.composition].join('.')\n : '',\n)\n\n/** When this composition is in the request body, sync selection with the example snippet */\nconst requestBodyCompositionSelectionRef = inject(\n REQUEST_BODY_COMPOSITION_INDEX_SYMBOL,\n undefined,\n)\n\nconst initialSelectedIndex = computed(() => {\n if (\n props.schemaContext !== 'requestBody' ||\n !requestBodyCompositionSelectionRef?.value ||\n !compositionSelectionKey.value\n ) {\n return 0\n }\n\n const selectedIndex =\n requestBodyCompositionSelectionRef.value[compositionSelectionKey.value]\n\n if (typeof selectedIndex !== 'number' || Number.isNaN(selectedIndex)) {\n return 0\n }\n\n return Math.max(0, Math.min(selectedIndex, listboxOptions.value.length - 1))\n})\n\n/**\n * Two-way computed property for the selected option.\n * Handles conversion between the selected index and the listbox option format.\n */\nconst selectedOption = ref<ScalarListboxOption | undefined>()\n\nwatch(\n [listboxOptions, initialSelectedIndex],\n ([options, selectedIndex]) => {\n if (\n !selectedOption.value ||\n !options.some((option) => option.id === selectedOption.value?.id)\n ) {\n selectedOption.value = options[selectedIndex] ?? options[0]\n }\n },\n { immediate: true },\n)\n\n/**\n * Humanize composition keyword name for display.\n * Converts camelCase to Title Case (e.g., oneOf -> One of).\n */\nconst humanizeType = (type: CompositionKeyword): string =>\n type\n .replace(/([A-Z])/g, ' $1')\n .replace(/^./, (str) => str.toUpperCase())\n .toLowerCase()\n .replace(/^(\\w)/, (c) => c.toUpperCase())\n\n/** Inside the currently selected composition */\nconst selectedComposition = computed(\n () => composition.value[Number(selectedOption.value?.id ?? '0')]?.value,\n)\n\n/**\n * The request body card renders the merged `allOf` description on its outer card\n * (see `Schema.vue`), but only for the top-level request body schema. For that\n * single composition we hide the nested merged `Schema`'s description so the text\n * is not shown twice. Nested request-body compositions (deeper properties) are\n * not shown on the outer card and would otherwise lose their description\n * entirely, because the property row already skips it when `allOf` is present.\n *\n * The top-level request body composition is the one whose `compositionPath` is\n * still the request body root (`['requestBody']`); nested compositions append\n * property segments and therefore have a longer path.\n */\nconst isRequestBodyRootComposition = computed(\n () =>\n props.schemaContext === 'requestBody' &&\n props.compositionPath?.length === 1,\n)\n\n/**\n * Cycle key for the selected composition member, derived from its raw\n * (unresolved) value so a member that references an ancestor is detected as a\n * cycle.\n */\nconst selectedCompositionCycleKey = computed(() =>\n getCycleKey(\n composition.value[Number(selectedOption.value?.id ?? '0')]?.original,\n ),\n)\n\n/**\n * Controls whether the nested schema is displayed. When expanding all schema\n * properties we open it by default; the nested Schema handles cycle detection,\n * so finite compositions render fully while recursive ones still stop.\n */\nconst showNestedSchema = ref(!!props.options.expandAllSchemaProperties)\n\nif (\n requestBodyCompositionSelectionRef &&\n props.schemaContext === 'requestBody' &&\n compositionSelectionKey.value\n) {\n watch(\n selectedOption,\n (option) => {\n const index = option ? Number(option.id) : 0\n if (!Number.isNaN(index)) {\n requestBodyCompositionSelectionRef.value = {\n ...requestBodyCompositionSelectionRef.value,\n [compositionSelectionKey.value]: index,\n } satisfies RequestBodyCompositionSelection\n }\n },\n { immediate: true },\n )\n}\n</script>\n\n<template>\n <div class=\"property-rule\">\n <!-- We merge allOf schemas into a single schema -->\n <Schema\n v-if=\"props.composition === 'allOf'\"\n :breadcrumb=\"breadcrumb\"\n :compact=\"compact\"\n :compositionPath=\"compositionPath\"\n :discriminator=\"discriminator\"\n :eventBus=\"eventBus\"\n :hideDescription=\"isRequestBodyRootComposition\"\n :hideHeading=\"hideHeading\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"true\"\n :options=\"options\"\n :schema=\"mergeAllOfSchemas(schema)\"\n :schemaContext=\"schemaContext\" />\n\n <template v-else>\n <!-- Composition selector and panel for nested compositions -->\n <ScalarListbox\n v-model=\"selectedOption\"\n :options=\"listboxOptions\"\n resize>\n <button\n class=\"composition-selector bg-b-1.5 hover:bg-b-2 flex w-full cursor-pointer items-center gap-1 rounded-t-lg border px-2.5 py-2.5 pr-3 text-left\"\n type=\"button\">\n <span class=\"text-c-2\">{{ humanizeType(props.composition) }}</span>\n <span\n class=\"composition-selector-label text-c-1\"\n :class=\"{\n 'line-through': selectedComposition?.deprecated,\n }\">\n {{ selectedOption?.label || 'Schema' }}\n </span>\n <div\n v-if=\"selectedComposition?.deprecated\"\n class=\"text-red\">\n deprecated\n </div>\n <ScalarIconCaretDown />\n </button>\n </ScalarListbox>\n\n <div class=\"composition-panel\">\n <!-- Button to toggle nested schema display -->\n <button\n v-if=\"!showNestedSchema && level > 2\"\n class=\"bg-b-1 hover:bg-b-2 text-c-1 flex w-full items-center justify-center gap-2 rounded-b-lg border border-t-0 px-2 py-2 text-sm font-medium transition-colors\"\n type=\"button\"\n @click=\"showNestedSchema = true\">\n Show Schema Details\n <ScalarIconCaretDown class=\"h-3 w-3\" />\n </button>\n\n <!-- Render the selected schema if it has content to display -->\n <Schema\n v-else\n :key=\"selectedOption?.id ?? '0'\"\n :breadcrumb=\"breadcrumb\"\n :compact=\"compact\"\n :compositionPath=\"compositionPath\"\n :cycleKey=\"selectedCompositionCycleKey\"\n :discriminator=\"discriminator\"\n :eventBus=\"eventBus\"\n :hideHeading=\"hideHeading\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"true\"\n :options=\"options\"\n :schema=\"selectedComposition\"\n :schemaContext=\"schemaContext\" />\n </div>\n </template>\n </div>\n</template>\n"],"mappings":""}
@@ -1,7 +1,7 @@
1
+ import { mergeAllOfSchemas } from "./helpers/merge-all-of-schemas.js";
1
2
  import { getCycleKey } from "./helpers/schema-cycle.js";
2
3
  import { REQUEST_BODY_COMPOSITION_INDEX_SYMBOL } from "../../../features/Operation/request-body-composition-index.js";
3
4
  import { getSchemaType } from "./helpers/get-schema-type.js";
4
- import { mergeAllOfSchemas } from "./helpers/merge-all-of-schemas.js";
5
5
  import { getModelNameFromSchema } from "./helpers/schema-name.js";
6
6
  import Schema_default from "./Schema.vue.js";
7
7
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, inject, normalizeClass, openBlock, ref, toDisplayString, unref, watch, withCtx } from "vue";
@@ -89,6 +89,19 @@ var SchemaComposition_vue_vue_type_script_setup_true_lang_default = /* @__PURE__
89
89
  /** Inside the currently selected composition */
90
90
  const selectedComposition = computed(() => composition.value[Number(selectedOption.value?.id ?? "0")]?.value);
91
91
  /**
92
+ * The request body card renders the merged `allOf` description on its outer card
93
+ * (see `Schema.vue`), but only for the top-level request body schema. For that
94
+ * single composition we hide the nested merged `Schema`'s description so the text
95
+ * is not shown twice. Nested request-body compositions (deeper properties) are
96
+ * not shown on the outer card and would otherwise lose their description
97
+ * entirely, because the property row already skips it when `allOf` is present.
98
+ *
99
+ * The top-level request body composition is the one whose `compositionPath` is
100
+ * still the request body root (`['requestBody']`); nested compositions append
101
+ * property segments and therefore have a longer path.
102
+ */
103
+ const isRequestBodyRootComposition = computed(() => props.schemaContext === "requestBody" && props.compositionPath?.length === 1);
104
+ /**
92
105
  * Cycle key for the selected composition member, derived from its raw
93
106
  * (unresolved) value so a member that references an ancestor is detected as a
94
107
  * cycle.
@@ -115,6 +128,7 @@ var SchemaComposition_vue_vue_type_script_setup_true_lang_default = /* @__PURE__
115
128
  compositionPath: __props.compositionPath,
116
129
  discriminator: __props.discriminator,
117
130
  eventBus: __props.eventBus,
131
+ hideDescription: isRequestBodyRootComposition.value,
118
132
  hideHeading: __props.hideHeading,
119
133
  hideModelNames: __props.hideModelNames,
120
134
  level: __props.level + 1,
@@ -129,6 +143,7 @@ var SchemaComposition_vue_vue_type_script_setup_true_lang_default = /* @__PURE__
129
143
  "compositionPath",
130
144
  "discriminator",
131
145
  "eventBus",
146
+ "hideDescription",
132
147
  "hideHeading",
133
148
  "hideModelNames",
134
149
  "level",
@@ -1 +1 @@
1
- {"version":3,"file":"SchemaComposition.vue.script.js","names":[],"sources":["../../../../src/components/Content/Schema/SchemaComposition.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport {\n ScalarListbox,\n type ScalarListboxOption,\n} from '@scalar/components/listbox'\nimport { isDefined } from '@scalar/helpers/array/is-defined'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type {\n DiscriminatorObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, inject, ref, watch } from 'vue'\n\nimport type { SchemaOptions } from '@/components/Content/Schema/types'\nimport {\n REQUEST_BODY_COMPOSITION_INDEX_SYMBOL,\n type RequestBodyCompositionSelection,\n} from '@/features/Operation/request-body-composition-index'\n\nimport { getSchemaType } from './helpers/get-schema-type'\nimport { mergeAllOfSchemas } from './helpers/merge-all-of-schemas'\nimport { type CompositionKeyword } from './helpers/schema-composition'\nimport { getCycleKey } from './helpers/schema-cycle'\nimport { getModelNameFromSchema } from './helpers/schema-name'\nimport Schema from './Schema.vue'\n\nconst props = withDefaults(\n defineProps<{\n /** The composition keyword (oneOf, anyOf, allOf) */\n composition: CompositionKeyword\n /** Optional discriminator object for polymorphic schemas */\n discriminator?: DiscriminatorObject\n /** Optional name for the schema */\n name?: string\n /** The schema value containing the composition */\n schema: SchemaObject\n /** Nesting level for proper indentation */\n level: number\n /** Whether to use compact layout */\n compact?: boolean\n /** Whether to hide the heading */\n hideHeading?: boolean\n /** Hide model names in type display */\n hideModelNames?: boolean\n /** Breadcrumb for navigation */\n breadcrumb?: string[]\n /** Event bus emitting actions */\n eventBus: WorkspaceEventBus | null\n /** Move the options into single prop so they are easy to pass around */\n options: SchemaOptions\n /** When \"requestBody\", sync selected index with the example snippet */\n schemaContext?: string\n /** Internal path used to sync nested request body compositions with the code sample */\n compositionPath?: string[]\n }>(),\n {\n compact: false,\n hideHeading: false,\n },\n)\n\n/** The current composition */\nconst composition = computed(() =>\n [props.schema[props.composition]]\n .flat()\n .map((schema) => ({ value: resolve.schema(schema), original: schema }))\n .filter((it) => isDefined(it.value)),\n)\n\n/**\n * Generate listbox options for the composition selector.\n * Each option represents a schema in the composition with a human-readable label.\n * Prefers schema title/name over structural type when present.\n */\nconst listboxOptions = computed((): ScalarListboxOption[] =>\n composition.value.map((schema, index: number) => {\n const resolved = resolve.schema(schema.original!)\n const label =\n (getModelNameFromSchema(resolved)?.label ?? getSchemaType(resolved)) ||\n 'Schema'\n return { id: String(index), label }\n }),\n)\n\nconst compositionSelectionKey = computed(() =>\n props.compositionPath?.length\n ? [...props.compositionPath, props.composition].join('.')\n : '',\n)\n\n/** When this composition is in the request body, sync selection with the example snippet */\nconst requestBodyCompositionSelectionRef = inject(\n REQUEST_BODY_COMPOSITION_INDEX_SYMBOL,\n undefined,\n)\n\nconst initialSelectedIndex = computed(() => {\n if (\n props.schemaContext !== 'requestBody' ||\n !requestBodyCompositionSelectionRef?.value ||\n !compositionSelectionKey.value\n ) {\n return 0\n }\n\n const selectedIndex =\n requestBodyCompositionSelectionRef.value[compositionSelectionKey.value]\n\n if (typeof selectedIndex !== 'number' || Number.isNaN(selectedIndex)) {\n return 0\n }\n\n return Math.max(0, Math.min(selectedIndex, listboxOptions.value.length - 1))\n})\n\n/**\n * Two-way computed property for the selected option.\n * Handles conversion between the selected index and the listbox option format.\n */\nconst selectedOption = ref<ScalarListboxOption | undefined>()\n\nwatch(\n [listboxOptions, initialSelectedIndex],\n ([options, selectedIndex]) => {\n if (\n !selectedOption.value ||\n !options.some((option) => option.id === selectedOption.value?.id)\n ) {\n selectedOption.value = options[selectedIndex] ?? options[0]\n }\n },\n { immediate: true },\n)\n\n/**\n * Humanize composition keyword name for display.\n * Converts camelCase to Title Case (e.g., oneOf -> One of).\n */\nconst humanizeType = (type: CompositionKeyword): string =>\n type\n .replace(/([A-Z])/g, ' $1')\n .replace(/^./, (str) => str.toUpperCase())\n .toLowerCase()\n .replace(/^(\\w)/, (c) => c.toUpperCase())\n\n/** Inside the currently selected composition */\nconst selectedComposition = computed(\n () => composition.value[Number(selectedOption.value?.id ?? '0')]?.value,\n)\n\n/**\n * Cycle key for the selected composition member, derived from its raw\n * (unresolved) value so a member that references an ancestor is detected as a\n * cycle.\n */\nconst selectedCompositionCycleKey = computed(() =>\n getCycleKey(\n composition.value[Number(selectedOption.value?.id ?? '0')]?.original,\n ),\n)\n\n/**\n * Controls whether the nested schema is displayed. When expanding all schema\n * properties we open it by default; the nested Schema handles cycle detection,\n * so finite compositions render fully while recursive ones still stop.\n */\nconst showNestedSchema = ref(!!props.options.expandAllSchemaProperties)\n\nif (\n requestBodyCompositionSelectionRef &&\n props.schemaContext === 'requestBody' &&\n compositionSelectionKey.value\n) {\n watch(\n selectedOption,\n (option) => {\n const index = option ? Number(option.id) : 0\n if (!Number.isNaN(index)) {\n requestBodyCompositionSelectionRef.value = {\n ...requestBodyCompositionSelectionRef.value,\n [compositionSelectionKey.value]: index,\n } satisfies RequestBodyCompositionSelection\n }\n },\n { immediate: true },\n )\n}\n</script>\n\n<template>\n <div class=\"property-rule\">\n <!-- We merge allOf schemas into a single schema -->\n <Schema\n v-if=\"props.composition === 'allOf'\"\n :breadcrumb=\"breadcrumb\"\n :compact=\"compact\"\n :compositionPath=\"compositionPath\"\n :discriminator=\"discriminator\"\n :eventBus=\"eventBus\"\n :hideHeading=\"hideHeading\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"true\"\n :options=\"options\"\n :schema=\"mergeAllOfSchemas(schema)\"\n :schemaContext=\"schemaContext\" />\n\n <template v-else>\n <!-- Composition selector and panel for nested compositions -->\n <ScalarListbox\n v-model=\"selectedOption\"\n :options=\"listboxOptions\"\n resize>\n <button\n class=\"composition-selector bg-b-1.5 hover:bg-b-2 flex w-full cursor-pointer items-center gap-1 rounded-t-lg border px-2.5 py-2.5 pr-3 text-left\"\n type=\"button\">\n <span class=\"text-c-2\">{{ humanizeType(props.composition) }}</span>\n <span\n class=\"composition-selector-label text-c-1\"\n :class=\"{\n 'line-through': selectedComposition?.deprecated,\n }\">\n {{ selectedOption?.label || 'Schema' }}\n </span>\n <div\n v-if=\"selectedComposition?.deprecated\"\n class=\"text-red\">\n deprecated\n </div>\n <ScalarIconCaretDown />\n </button>\n </ScalarListbox>\n\n <div class=\"composition-panel\">\n <!-- Button to toggle nested schema display -->\n <button\n v-if=\"!showNestedSchema && level > 2\"\n class=\"bg-b-1 hover:bg-b-2 text-c-1 flex w-full items-center justify-center gap-2 rounded-b-lg border border-t-0 px-2 py-2 text-sm font-medium transition-colors\"\n type=\"button\"\n @click=\"showNestedSchema = true\">\n Show Schema Details\n <ScalarIconCaretDown class=\"h-3 w-3\" />\n </button>\n\n <!-- Render the selected schema if it has content to display -->\n <Schema\n v-else\n :key=\"selectedOption?.id ?? '0'\"\n :breadcrumb=\"breadcrumb\"\n :compact=\"compact\"\n :compositionPath=\"compositionPath\"\n :cycleKey=\"selectedCompositionCycleKey\"\n :discriminator=\"discriminator\"\n :eventBus=\"eventBus\"\n :hideHeading=\"hideHeading\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"true\"\n :options=\"options\"\n :schema=\"selectedComposition\"\n :schemaContext=\"schemaContext\" />\n </div>\n </template>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"SchemaComposition.vue.script.js","names":[],"sources":["../../../../src/components/Content/Schema/SchemaComposition.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport {\n ScalarListbox,\n type ScalarListboxOption,\n} from '@scalar/components/listbox'\nimport { isDefined } from '@scalar/helpers/array/is-defined'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type {\n DiscriminatorObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, inject, ref, watch } from 'vue'\n\nimport type { SchemaOptions } from '@/components/Content/Schema/types'\nimport {\n REQUEST_BODY_COMPOSITION_INDEX_SYMBOL,\n type RequestBodyCompositionSelection,\n} from '@/features/Operation/request-body-composition-index'\n\nimport { getSchemaType } from './helpers/get-schema-type'\nimport { mergeAllOfSchemas } from './helpers/merge-all-of-schemas'\nimport { type CompositionKeyword } from './helpers/schema-composition'\nimport { getCycleKey } from './helpers/schema-cycle'\nimport { getModelNameFromSchema } from './helpers/schema-name'\nimport Schema from './Schema.vue'\n\nconst props = withDefaults(\n defineProps<{\n /** The composition keyword (oneOf, anyOf, allOf) */\n composition: CompositionKeyword\n /** Optional discriminator object for polymorphic schemas */\n discriminator?: DiscriminatorObject\n /** Optional name for the schema */\n name?: string\n /** The schema value containing the composition */\n schema: SchemaObject\n /** Nesting level for proper indentation */\n level: number\n /** Whether to use compact layout */\n compact?: boolean\n /** Whether to hide the heading */\n hideHeading?: boolean\n /** Hide model names in type display */\n hideModelNames?: boolean\n /** Breadcrumb for navigation */\n breadcrumb?: string[]\n /** Event bus emitting actions */\n eventBus: WorkspaceEventBus | null\n /** Move the options into single prop so they are easy to pass around */\n options: SchemaOptions\n /** When \"requestBody\", sync selected index with the example snippet */\n schemaContext?: string\n /** Internal path used to sync nested request body compositions with the code sample */\n compositionPath?: string[]\n }>(),\n {\n compact: false,\n hideHeading: false,\n },\n)\n\n/** The current composition */\nconst composition = computed(() =>\n [props.schema[props.composition]]\n .flat()\n .map((schema) => ({ value: resolve.schema(schema), original: schema }))\n .filter((it) => isDefined(it.value)),\n)\n\n/**\n * Generate listbox options for the composition selector.\n * Each option represents a schema in the composition with a human-readable label.\n * Prefers schema title/name over structural type when present.\n */\nconst listboxOptions = computed((): ScalarListboxOption[] =>\n composition.value.map((schema, index: number) => {\n const resolved = resolve.schema(schema.original!)\n const label =\n (getModelNameFromSchema(resolved)?.label ?? getSchemaType(resolved)) ||\n 'Schema'\n return { id: String(index), label }\n }),\n)\n\nconst compositionSelectionKey = computed(() =>\n props.compositionPath?.length\n ? [...props.compositionPath, props.composition].join('.')\n : '',\n)\n\n/** When this composition is in the request body, sync selection with the example snippet */\nconst requestBodyCompositionSelectionRef = inject(\n REQUEST_BODY_COMPOSITION_INDEX_SYMBOL,\n undefined,\n)\n\nconst initialSelectedIndex = computed(() => {\n if (\n props.schemaContext !== 'requestBody' ||\n !requestBodyCompositionSelectionRef?.value ||\n !compositionSelectionKey.value\n ) {\n return 0\n }\n\n const selectedIndex =\n requestBodyCompositionSelectionRef.value[compositionSelectionKey.value]\n\n if (typeof selectedIndex !== 'number' || Number.isNaN(selectedIndex)) {\n return 0\n }\n\n return Math.max(0, Math.min(selectedIndex, listboxOptions.value.length - 1))\n})\n\n/**\n * Two-way computed property for the selected option.\n * Handles conversion between the selected index and the listbox option format.\n */\nconst selectedOption = ref<ScalarListboxOption | undefined>()\n\nwatch(\n [listboxOptions, initialSelectedIndex],\n ([options, selectedIndex]) => {\n if (\n !selectedOption.value ||\n !options.some((option) => option.id === selectedOption.value?.id)\n ) {\n selectedOption.value = options[selectedIndex] ?? options[0]\n }\n },\n { immediate: true },\n)\n\n/**\n * Humanize composition keyword name for display.\n * Converts camelCase to Title Case (e.g., oneOf -> One of).\n */\nconst humanizeType = (type: CompositionKeyword): string =>\n type\n .replace(/([A-Z])/g, ' $1')\n .replace(/^./, (str) => str.toUpperCase())\n .toLowerCase()\n .replace(/^(\\w)/, (c) => c.toUpperCase())\n\n/** Inside the currently selected composition */\nconst selectedComposition = computed(\n () => composition.value[Number(selectedOption.value?.id ?? '0')]?.value,\n)\n\n/**\n * The request body card renders the merged `allOf` description on its outer card\n * (see `Schema.vue`), but only for the top-level request body schema. For that\n * single composition we hide the nested merged `Schema`'s description so the text\n * is not shown twice. Nested request-body compositions (deeper properties) are\n * not shown on the outer card and would otherwise lose their description\n * entirely, because the property row already skips it when `allOf` is present.\n *\n * The top-level request body composition is the one whose `compositionPath` is\n * still the request body root (`['requestBody']`); nested compositions append\n * property segments and therefore have a longer path.\n */\nconst isRequestBodyRootComposition = computed(\n () =>\n props.schemaContext === 'requestBody' &&\n props.compositionPath?.length === 1,\n)\n\n/**\n * Cycle key for the selected composition member, derived from its raw\n * (unresolved) value so a member that references an ancestor is detected as a\n * cycle.\n */\nconst selectedCompositionCycleKey = computed(() =>\n getCycleKey(\n composition.value[Number(selectedOption.value?.id ?? '0')]?.original,\n ),\n)\n\n/**\n * Controls whether the nested schema is displayed. When expanding all schema\n * properties we open it by default; the nested Schema handles cycle detection,\n * so finite compositions render fully while recursive ones still stop.\n */\nconst showNestedSchema = ref(!!props.options.expandAllSchemaProperties)\n\nif (\n requestBodyCompositionSelectionRef &&\n props.schemaContext === 'requestBody' &&\n compositionSelectionKey.value\n) {\n watch(\n selectedOption,\n (option) => {\n const index = option ? Number(option.id) : 0\n if (!Number.isNaN(index)) {\n requestBodyCompositionSelectionRef.value = {\n ...requestBodyCompositionSelectionRef.value,\n [compositionSelectionKey.value]: index,\n } satisfies RequestBodyCompositionSelection\n }\n },\n { immediate: true },\n )\n}\n</script>\n\n<template>\n <div class=\"property-rule\">\n <!-- We merge allOf schemas into a single schema -->\n <Schema\n v-if=\"props.composition === 'allOf'\"\n :breadcrumb=\"breadcrumb\"\n :compact=\"compact\"\n :compositionPath=\"compositionPath\"\n :discriminator=\"discriminator\"\n :eventBus=\"eventBus\"\n :hideDescription=\"isRequestBodyRootComposition\"\n :hideHeading=\"hideHeading\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"true\"\n :options=\"options\"\n :schema=\"mergeAllOfSchemas(schema)\"\n :schemaContext=\"schemaContext\" />\n\n <template v-else>\n <!-- Composition selector and panel for nested compositions -->\n <ScalarListbox\n v-model=\"selectedOption\"\n :options=\"listboxOptions\"\n resize>\n <button\n class=\"composition-selector bg-b-1.5 hover:bg-b-2 flex w-full cursor-pointer items-center gap-1 rounded-t-lg border px-2.5 py-2.5 pr-3 text-left\"\n type=\"button\">\n <span class=\"text-c-2\">{{ humanizeType(props.composition) }}</span>\n <span\n class=\"composition-selector-label text-c-1\"\n :class=\"{\n 'line-through': selectedComposition?.deprecated,\n }\">\n {{ selectedOption?.label || 'Schema' }}\n </span>\n <div\n v-if=\"selectedComposition?.deprecated\"\n class=\"text-red\">\n deprecated\n </div>\n <ScalarIconCaretDown />\n </button>\n </ScalarListbox>\n\n <div class=\"composition-panel\">\n <!-- Button to toggle nested schema display -->\n <button\n v-if=\"!showNestedSchema && level > 2\"\n class=\"bg-b-1 hover:bg-b-2 text-c-1 flex w-full items-center justify-center gap-2 rounded-b-lg border border-t-0 px-2 py-2 text-sm font-medium transition-colors\"\n type=\"button\"\n @click=\"showNestedSchema = true\">\n Show Schema Details\n <ScalarIconCaretDown class=\"h-3 w-3\" />\n </button>\n\n <!-- Render the selected schema if it has content to display -->\n <Schema\n v-else\n :key=\"selectedOption?.id ?? '0'\"\n :breadcrumb=\"breadcrumb\"\n :compact=\"compact\"\n :compositionPath=\"compositionPath\"\n :cycleKey=\"selectedCompositionCycleKey\"\n :discriminator=\"discriminator\"\n :eventBus=\"eventBus\"\n :hideHeading=\"hideHeading\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"true\"\n :options=\"options\"\n :schema=\"selectedComposition\"\n :schemaContext=\"schemaContext\" />\n </div>\n </template>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { isTypeObject } from "./helpers/is-type-object.js";
2
2
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, defineComponent, openBlock, toDisplayString, unref } from "vue";
3
- import { ScalarWrappingText } from "@scalar/components/wrapping-text";
4
3
  import { isArraySchema } from "@scalar/workspace-store/schemas/v3.1/strict/type-guards";
4
+ import { ScalarWrappingText } from "@scalar/components/wrapping-text";
5
5
  //#region src/components/Content/Schema/SchemaHeading.vue?vue&type=script&setup=true&lang.ts
6
6
  var _hoisted_1 = {
7
7
  key: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"SchemaProperty.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/Content/Schema/SchemaProperty.vue"],"names":[],"mappings":"AA0gBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAEvE,OAAO,KAAK,EACV,mBAAmB,EACnB,YAAY,EACb,MAAM,8DAA8D,CAAA;AAErE,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,KAAK,CAAA;AAK9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAA;AAyBtE,KAAK,WAAW,GAAG;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvB,MAAM,EAAE,YAAY,GAAG,SAAS,CAAA;IAChC,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,kGAAkG;IAClG,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,OAAO,CAAC,EAAE,sBAAsB,GAAG,mBAAmB,CAAA;IACtD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAClC,OAAO,EAAE,aAAa,CAAA;IACtB,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uFAAuF;IACvF,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,oFAAoF;IACpF,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAC;AAuiBJ,QAAA,MAAM,YAAY;WA/jBN,MAAM;cAEH,OAAO;aACR,OAAO;oBAGA,OAAO;6EA4jB1B,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"SchemaProperty.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/Content/Schema/SchemaProperty.vue"],"names":[],"mappings":"AAgjBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAEvE,OAAO,KAAK,EACV,mBAAmB,EACnB,YAAY,EACb,MAAM,8DAA8D,CAAA;AAErE,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,KAAK,CAAA;AAK9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAA;AAyBtE,KAAK,WAAW,GAAG;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvB,MAAM,EAAE,YAAY,GAAG,SAAS,CAAA;IAChC,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,kGAAkG;IAClG,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,OAAO,CAAC,EAAE,sBAAsB,GAAG,mBAAmB,CAAA;IACtD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAClC,OAAO,EAAE,aAAa,CAAA;IACtB,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uFAAuF;IACvF,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,oFAAoF;IACpF,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAC;AA6kBJ,QAAA,MAAM,YAAY;WArmBN,MAAM;cAEH,OAAO;aACR,OAAO;oBAGA,OAAO;6EAkmB1B,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -2,7 +2,7 @@ import _plugin_vue_export_helper_default from "../../../_virtual/_plugin-vue_exp
2
2
  import SchemaProperty_vue_vue_type_script_setup_true_lang_default from "./SchemaProperty.vue.script.js";
3
3
  /* empty css */
4
4
  //#region src/components/Content/Schema/SchemaProperty.vue
5
- var SchemaProperty_default = /* @__PURE__ */ _plugin_vue_export_helper_default(SchemaProperty_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-e16b102d"]]);
5
+ var SchemaProperty_default = /* @__PURE__ */ _plugin_vue_export_helper_default(SchemaProperty_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-2e5a7cbc"]]);
6
6
  //#endregion
7
7
  export { SchemaProperty_default as default };
8
8
 
@@ -1 +1 @@
1
- {"version":3,"file":"SchemaProperty.vue.js","names":[],"sources":["../../../../src/components/Content/Schema/SchemaProperty.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { ScalarMarkdown } from '@scalar/components/markdown'\nimport { ScalarWrappingText } from '@scalar/components/wrapping-text'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type {\n DiscriminatorObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { isArraySchema } from '@scalar/workspace-store/schemas/v3.1/strict/type-guards'\nimport { computed, type Component } from 'vue'\n\nimport { WithBreadcrumb } from '@/components/Anchor'\nimport { isTypeObject } from '@/components/Content/Schema/helpers/is-type-object'\nimport { getCycleKey } from '@/components/Content/Schema/helpers/schema-cycle'\nimport type { SchemaOptions } from '@/components/Content/Schema/types'\nimport { SpecificationExtension } from '@/features/specification-extension'\n\nimport { getCompositionsToRender } from './helpers/get-compositions-to-render'\nimport { getEnumValues } from './helpers/get-enum-values'\nimport { getPropertyDescription } from './helpers/get-property-description'\nimport { hasComplexArrayItems } from './helpers/has-complex-array-items'\nimport { optimizeValueForDisplay } from './helpers/optimize-value-for-display'\nimport { shouldDisplayDescription } from './helpers/should-display-description'\nimport { shouldDisplayHeading } from './helpers/should-display-heading'\nimport Schema from './Schema.vue'\nimport SchemaComposition from './SchemaComposition.vue'\nimport SchemaEnums from './SchemaEnums.vue'\nimport SchemaPropertyHeading from './SchemaPropertyHeading.vue'\n\n/**\n * Note: We're taking in a prop called `value` which should be a JSON Schema.\n *\n * We're using `optimizeValueForDisplay` to merge null types in compositions (anyOf, allOf, oneOf, not).\n * So you should basically use the optimizedValue everywhere in the component.\n */\n\n/** Composition keywords that hold a list of schemas and can be flattened when they contain a single member. */\nconst SINGLE_ITEM_COMPOSITIONS = ['oneOf', 'anyOf', 'allOf'] as const\n\nconst props = withDefaults(\n defineProps<{\n is?: string | Component\n schema: SchemaObject | undefined\n noncollapsible?: boolean\n level?: number\n name?: string\n required?: boolean\n compact?: boolean\n discriminator?: DiscriminatorObject\n description?: string\n hideModelNames?: boolean\n hideHeading?: boolean\n /** When the root schema was resolved from a $ref, pass the ref name for display (e.g. \"Data\"). */\n modelName?: string | null\n variant?: 'additionalProperties' | 'patternProperties'\n breadcrumb?: string[]\n eventBus: WorkspaceEventBus | null\n options: SchemaOptions\n /** Enum values for property names (from JSON Schema propertyNames keyword). */\n propertyNamesEnum?: string[]\n /** When \"requestBody\", composition selection is synced with the example snippet */\n schemaContext?: string\n /** Internal path used to sync nested request body compositions with the code sample */\n compositionPath?: string[]\n /** Internal path segment for this property when building nested composition keys */\n compositionPathSegment?: string\n /** Stable identity of this property's schema, used for cycle detection. */\n cycleKey?: unknown\n }>(),\n {\n level: 0,\n required: false,\n compact: false,\n hideModelNames: false,\n },\n)\n\n/** Simplified composition with `null` type. */\nconst optimizedValue = computed(() => optimizeValueForDisplay(props.schema))\n\nconst childBreadcrumb = computed<string[] | undefined>(() =>\n props.breadcrumb && props.name\n ? [...props.breadcrumb, props.name]\n : undefined,\n)\n\nconst currentCompositionPath = computed<string[]>(() =>\n props.compositionPathSegment\n ? [...(props.compositionPath ?? []), props.compositionPathSegment]\n : (props.compositionPath ?? []),\n)\n\nconst arrayItemsCompositionPath = computed<string[]>(() => [\n ...currentCompositionPath.value,\n 'items',\n])\n\nconst shouldHaveLink = computed(() => props.level <= 2)\n\n/** Checks if array items have complex structure */\nconst hasComplexArrayItemsComputed = computed(() =>\n hasComplexArrayItems(optimizedValue.value),\n)\n\n/** Check if enum should be displayed (from value schema or from propertyNames) */\nconst hasEnum = computed(() => enumValues.value.length > 0)\n\n/** Determine if object properties should be displayed */\nconst shouldRenderObjectProperties = computed(() => {\n const value = optimizedValue.value\n if (!value) {\n return false\n }\n\n return (\n isTypeObject(value) &&\n ('properties' in value || 'additionalProperties' in value)\n )\n})\n\n/** Determine if array of objects should be rendered */\nconst shouldRenderArrayOfObjects = computed(() => {\n const value = optimizedValue.value\n if (!value || !isArraySchema(value) || typeof value.items !== 'object') {\n return false\n }\n\n return hasComplexArrayItemsComputed.value\n})\n\n/** Extract enum values from schema or array items */\nconst enumValues = computed(() => getEnumValues(optimizedValue.value))\n\n/** Generate property description from type/format */\nconst propertyDescription = computed(() =>\n getPropertyDescription(optimizedValue.value),\n)\n\n/** Determine if description should be displayed */\nconst displayDescription = computed(() =>\n shouldDisplayDescription(optimizedValue.value, props.description),\n)\n\n/**\n * When the property already renders the description, avoid repeating it in the nested object schema card.\n */\nconst objectSchemaForChildren = computed(() => {\n const value = optimizedValue.value\n if (!value || !displayDescription.value || !('description' in value)) {\n return value\n }\n\n const { description: _description, ...schemaWithoutDescription } = value\n return schemaWithoutDescription as SchemaObject\n})\n\n/** Determine if property heading should be displayed */\nconst shouldDisplayHeadingComputed = computed(() =>\n shouldDisplayHeading(optimizedValue.value, props.name, props.required),\n)\n\n/** Computes which compositions should be rendered and with which values */\nconst compositionsToRender = computed(() =>\n getCompositionsToRender(optimizedValue.value, props.options.document),\n)\n\n/**\n * Get resolved array items for rendering.\n *\n * When the items are wrapped in a single-item composition (e.g. `items: { allOf: [{ type: 'object', ... }] }`), we\n * flatten that wrapper into its plain form. A composition with a single member is equivalent to that member, so\n * keeping the composition keyword only makes the items render through an extra schema layer, which adds an\n * unnecessary level of nesting and duplicates the item description. See https://github.com/scalar/scalar/issues/5900\n */\nconst resolvedArrayItems = computed(() => {\n const value = optimizedValue.value\n if (!value || !isArraySchema(value) || typeof value.items !== 'object') {\n return undefined\n }\n\n const items = resolve.schema(value.items)\n const hasSingleItemComposition = SINGLE_ITEM_COMPOSITIONS.some(\n (keyword) =>\n Array.isArray(items?.[keyword]) && items[keyword]?.length === 1,\n )\n\n return hasSingleItemComposition ? optimizeValueForDisplay(items) : items\n})\n\n/**\n * Cycle key for the array items schema, derived from the raw (unresolved) items\n * so a self-referential array element is detected as a cycle.\n */\nconst arrayItemsCycleKey = computed(() => {\n const value = optimizedValue.value\n if (!value || !isArraySchema(value)) {\n return undefined\n }\n return getCycleKey(value.items)\n})\n\n/** Check if discriminator matches current property */\nconst isDiscriminatorProperty = computed(() =>\n Boolean(props.name && props.discriminator?.propertyName === props.name),\n)\n</script>\n<template>\n <component\n :is=\"is ?? 'li'\"\n class=\"property\"\n :class=\"[\n `property--level-${level}`,\n {\n 'property--compact': compact,\n 'property--deprecated': optimizedValue?.deprecated,\n },\n ]\">\n <SchemaPropertyHeading\n v-if=\"shouldDisplayHeadingComputed\"\n class=\"group\"\n :enum=\"hasEnum\"\n :eventBus=\"eventBus\"\n :hideModelNames\n :isDiscriminator=\"isDiscriminatorProperty\"\n :modelName=\"modelName\"\n :required\n :value=\"optimizedValue\">\n <template\n v-if=\"name\"\n #name>\n <WithBreadcrumb\n :breadcrumb=\"shouldHaveLink ? childBreadcrumb : undefined\"\n :eventBus=\"eventBus\">\n <span\n v-if=\"variant === 'patternProperties'\"\n class=\"property-name-pattern-properties\">\n <ScalarWrappingText\n preset=\"property\"\n :text=\"name\" />\n </span>\n <span\n v-else-if=\"variant === 'additionalProperties'\"\n class=\"property-name-additional-properties\">\n <ScalarWrappingText\n preset=\"property\"\n :text=\"name\" />\n </span>\n <ScalarWrappingText\n v-else\n preset=\"property\"\n :text=\"name\" />\n </WithBreadcrumb>\n </template>\n <template\n v-if=\"optimizedValue?.example !== undefined\"\n #example>\n Example:\n {{ optimizedValue.example }}\n </template>\n </SchemaPropertyHeading>\n\n <!-- Description -->\n <div\n v-if=\"displayDescription || propertyDescription\"\n class=\"property-description\">\n <ScalarMarkdown\n :value=\"displayDescription || propertyDescription || ''\" />\n </div>\n\n <!-- Enum for property names -->\n <SchemaEnums\n v-if=\"propertyNamesEnum && propertyNamesEnum.length > 0\"\n propertyNames\n :value=\"{ enum: propertyNamesEnum } as SchemaObject\" />\n\n <!-- Enum values -->\n <SchemaEnums\n v-if=\"enumValues.length > 0\"\n :value=\"optimizedValue\" />\n\n <!-- Object -->\n <div\n v-if=\"shouldRenderObjectProperties\"\n class=\"children\">\n <Schema\n :breadcrumb=\"childBreadcrumb\"\n :compact=\"compact\"\n :compositionPath=\"currentCompositionPath\"\n :cycleKey=\"cycleKey\"\n :eventBus=\"eventBus\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"noncollapsible\"\n :options=\"options\"\n :schema=\"objectSchemaForChildren\"\n :schemaContext=\"schemaContext\" />\n </div>\n\n <!-- Array of objects or nested arrays -->\n <div\n v-if=\"shouldRenderArrayOfObjects && resolvedArrayItems\"\n class=\"children\">\n <Schema\n :compact=\"compact\"\n :compositionPath=\"arrayItemsCompositionPath\"\n :cycleKey=\"arrayItemsCycleKey\"\n :eventBus=\"eventBus\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"noncollapsible\"\n :options=\"options\"\n :schema=\"resolve.schema(resolvedArrayItems)\"\n :schemaContext=\"schemaContext\" />\n </div>\n\n <!-- Compositions -->\n <SchemaComposition\n v-for=\"compositionData in compositionsToRender\"\n :key=\"compositionData.composition\"\n :breadcrumb=\"breadcrumb\"\n :compact=\"compact\"\n :composition=\"compositionData.composition\"\n :compositionPath=\"currentCompositionPath\"\n :discriminator=\"schema?.discriminator\"\n :eventBus=\"eventBus\"\n :hideHeading=\"hideHeading\"\n :hideModelNames\n :level=\"level\"\n :name=\"name\"\n :noncollapsible=\"noncollapsible\"\n :options=\"options\"\n :schema=\"compositionData.value\"\n :schemaContext=\"schemaContext\" />\n <SpecificationExtension :value=\"optimizedValue\" />\n </component>\n</template>\n\n<style scoped>\n.property {\n color: var(--scalar-color-1);\n display: flex;\n flex-direction: column;\n padding: 10px;\n font-size: var(--scalar-small);\n position: relative;\n}\n\n/** Remove top padding for top level schema card */\n.property.property--level-0:has(\n > .property-rule\n > .schema-card\n > .schema-properties.schema-properties-open\n > ul\n > li.property\n ) {\n padding-top: 0;\n}\n\n.property--compact.property--level-0,\n.property--compact.property--level-1 {\n padding: 10px 0;\n}\n\n.composition-panel .property.property.property.property--level-0 {\n padding: 0px;\n}\n\n.property--compact.property--level-0\n .composition-panel\n .property--compact.property--level-1 {\n padding: 8px;\n}\n\n/* if a property doesn't have a heading, remove the top padding */\n.property:has(> .property-rule:nth-of-type(1)):not(.property--compact) {\n padding-top: 8px;\n padding-bottom: 8px;\n}\n\n.property--deprecated {\n background: repeating-linear-gradient(\n -45deg,\n var(--scalar-background-2) 0,\n var(--scalar-background-2) 2px,\n transparent 2px,\n transparent 5px\n );\n background-size: 100%;\n}\n\n.property--deprecated > * {\n opacity: 0.75;\n}\n\n.property-description {\n margin-top: 6px;\n line-height: 1.4;\n font-size: var(--scalar-small);\n}\n\n.property-description:has(+ .property-rule) {\n margin-bottom: 9px;\n}\n\n:deep(.property-description) * {\n color: var(--scalar-color-2) !important;\n}\n\n.property:not(:last-of-type) {\n border-bottom: var(--scalar-border-width) solid var(--scalar-border-color);\n}\n\n.property-description + .children,\n.children + .property-rule {\n margin-top: 9px;\n}\n\n.children {\n display: flex;\n flex-direction: column;\n}\n\n.children .property--compact.property--level-1 {\n padding: 12px;\n}\n\n.property-example-value {\n all: unset;\n font-family: var(--scalar-font-code);\n padding: 6px;\n border-top: var(--scalar-border-width) solid var(--scalar-border-color);\n}\n\n.property-rule {\n border-radius: var(--scalar-radius-lg);\n display: flex;\n flex-direction: column;\n}\n\n.property--level-2 :deep(.relative > button) {\n left: -2rem;\n}\n\n.property-rule\n :deep(\n .composition-panel\n .schema-card--level-1\n > .schema-properties.schema-properties-open\n ) {\n border-radius: 0 0 var(--scalar-radius-lg) var(--scalar-radius-lg);\n}\n\n.property-rule\n :deep(.composition-panel > .schema-card > .schema-card-description) {\n padding: 10px;\n border-left: var(--scalar-border-width) solid var(--scalar-border-color);\n border-right: var(--scalar-border-width) solid var(--scalar-border-color);\n\n & + .schema-properties {\n margin-top: 0;\n }\n}\n\n.property-example {\n background: transparent;\n border: none;\n display: flex;\n flex-direction: row;\n gap: 8px;\n}\n\n.property-example-label,\n.property-example-value {\n padding: 3px 0 0 0;\n}\n\n.property-example-value {\n background: var(--scalar-background-2);\n border-top: 0;\n border-radius: var(--scalar-radius);\n padding: 3px 4px;\n}\n\n.property-name {\n font-family: var(--scalar-font-code);\n font-weight: var(--scalar-semibold);\n}\n\n.property-name-additional-properties::before,\n.property-name-pattern-properties::before {\n text-transform: uppercase;\n font-size: var(--scalar-micro);\n display: inline-block;\n padding: 2px 4px;\n border-radius: var(--scalar-radius);\n color: var(--scalar-color-1);\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n background-color: var(--scalar-background-2);\n margin-right: 4px;\n}\n\n.property-name-pattern-properties::before {\n content: 'regex';\n}\n\n.property-name-additional-properties,\n.property-name-pattern-properties {\n border: 1px dashed var(--scalar-border-color);\n color: var(--scalar-color-accent);\n display: inline-block;\n padding: 2px;\n border-radius: var(--scalar-radius);\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"SchemaProperty.vue.js","names":[],"sources":["../../../../src/components/Content/Schema/SchemaProperty.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { ScalarMarkdown } from '@scalar/components/markdown'\nimport { ScalarWrappingText } from '@scalar/components/wrapping-text'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type {\n DiscriminatorObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { isArraySchema } from '@scalar/workspace-store/schemas/v3.1/strict/type-guards'\nimport { computed, type Component } from 'vue'\n\nimport { WithBreadcrumb } from '@/components/Anchor'\nimport { isTypeObject } from '@/components/Content/Schema/helpers/is-type-object'\nimport { getCycleKey } from '@/components/Content/Schema/helpers/schema-cycle'\nimport type { SchemaOptions } from '@/components/Content/Schema/types'\nimport { SpecificationExtension } from '@/features/specification-extension'\n\nimport { getCompositionsToRender } from './helpers/get-compositions-to-render'\nimport { getEnumValues } from './helpers/get-enum-values'\nimport { getPropertyDescription } from './helpers/get-property-description'\nimport { hasComplexArrayItems } from './helpers/has-complex-array-items'\nimport { optimizeValueForDisplay } from './helpers/optimize-value-for-display'\nimport { shouldDisplayDescription } from './helpers/should-display-description'\nimport { shouldDisplayHeading } from './helpers/should-display-heading'\nimport Schema from './Schema.vue'\nimport SchemaComposition from './SchemaComposition.vue'\nimport SchemaEnums from './SchemaEnums.vue'\nimport SchemaPropertyHeading from './SchemaPropertyHeading.vue'\n\n/**\n * Note: We're taking in a prop called `value` which should be a JSON Schema.\n *\n * We're using `optimizeValueForDisplay` to merge null types in compositions (anyOf, allOf, oneOf, not).\n * So you should basically use the optimizedValue everywhere in the component.\n */\n\n/** Composition keywords that hold a list of schemas and can be flattened when they contain a single member. */\nconst SINGLE_ITEM_COMPOSITIONS = ['oneOf', 'anyOf', 'allOf'] as const\n\nconst props = withDefaults(\n defineProps<{\n is?: string | Component\n schema: SchemaObject | undefined\n noncollapsible?: boolean\n level?: number\n name?: string\n required?: boolean\n compact?: boolean\n discriminator?: DiscriminatorObject\n description?: string\n hideModelNames?: boolean\n hideHeading?: boolean\n /** When the root schema was resolved from a $ref, pass the ref name for display (e.g. \"Data\"). */\n modelName?: string | null\n variant?: 'additionalProperties' | 'patternProperties'\n breadcrumb?: string[]\n eventBus: WorkspaceEventBus | null\n options: SchemaOptions\n /** Enum values for property names (from JSON Schema propertyNames keyword). */\n propertyNamesEnum?: string[]\n /** When \"requestBody\", composition selection is synced with the example snippet */\n schemaContext?: string\n /** Internal path used to sync nested request body compositions with the code sample */\n compositionPath?: string[]\n /** Internal path segment for this property when building nested composition keys */\n compositionPathSegment?: string\n /** Stable identity of this property's schema, used for cycle detection. */\n cycleKey?: unknown\n }>(),\n {\n level: 0,\n required: false,\n compact: false,\n hideModelNames: false,\n },\n)\n\n/** Simplified composition with `null` type. */\nconst optimizedValue = computed(() => optimizeValueForDisplay(props.schema))\n\nconst childBreadcrumb = computed<string[] | undefined>(() =>\n props.breadcrumb && props.name\n ? [...props.breadcrumb, props.name]\n : undefined,\n)\n\nconst currentCompositionPath = computed<string[]>(() =>\n props.compositionPathSegment\n ? [...(props.compositionPath ?? []), props.compositionPathSegment]\n : (props.compositionPath ?? []),\n)\n\nconst arrayItemsCompositionPath = computed<string[]>(() => [\n ...currentCompositionPath.value,\n 'items',\n])\n\nconst shouldHaveLink = computed(() => props.level <= 2)\n\n/** Checks if array items have complex structure */\nconst hasComplexArrayItemsComputed = computed(() =>\n hasComplexArrayItems(optimizedValue.value),\n)\n\n/** Check if enum should be displayed (from value schema or from propertyNames) */\nconst hasEnum = computed(() => enumValues.value.length > 0)\n\n/** Determine if object properties should be displayed */\nconst shouldRenderObjectProperties = computed(() => {\n const value = optimizedValue.value\n if (!value) {\n return false\n }\n\n if (!('properties' in value || 'additionalProperties' in value)) {\n return false\n }\n\n // `allOf` already merges the factored-out sibling `properties` into its\n // rendered result (see `mergeAllOfSchemas`), so rendering a separate object\n // block here would show those properties twice. Let the composition handle it.\n if ('allOf' in value) {\n return false\n }\n\n // A schema may factor its common `properties` out to the top level alongside\n // a composition keyword (anyOf/oneOf/not), as described in the JSON Schema\n // \"factoring schemas\" guide. `isTypeObject` deliberately rejects such schemas\n // so the composition is rendered, but the factored-out properties must still\n // show. Unlike `allOf`, these compositions do not merge sibling properties.\n // Render them unless the schema is an explicit non-object (scalar or array)\n // type. See https://github.com/scalar/scalar/issues/8593\n const type = (value as { type?: unknown }).type\n const isExplicitNonObject = typeof type === 'string' && type !== 'object'\n\n return isTypeObject(value) || !isExplicitNonObject\n})\n\n/** Determine if array of objects should be rendered */\nconst shouldRenderArrayOfObjects = computed(() => {\n const value = optimizedValue.value\n if (!value || !isArraySchema(value) || typeof value.items !== 'object') {\n return false\n }\n\n return hasComplexArrayItemsComputed.value\n})\n\n/** Extract enum values from schema or array items */\nconst enumValues = computed(() => getEnumValues(optimizedValue.value))\n\n/** Generate property description from type/format */\nconst propertyDescription = computed(() =>\n getPropertyDescription(optimizedValue.value),\n)\n\n/** Determine if description should be displayed */\nconst displayDescription = computed(() =>\n shouldDisplayDescription(optimizedValue.value, props.description),\n)\n\n/**\n * The schema used to render the object's own properties.\n *\n * Composition keywords are stripped so the nested object renders only its\n * properties. The compositions are rendered separately below; leaving them here\n * would route the nested `Schema` back through `SchemaProperty` and recurse.\n *\n * When the property already renders the description, we also drop it to avoid\n * repeating it in the nested object schema card.\n */\nconst objectSchemaForChildren = computed(() => {\n const value = optimizedValue.value\n if (!value) {\n return value\n }\n\n const {\n oneOf: _oneOf,\n anyOf: _anyOf,\n allOf: _allOf,\n not: _not,\n ...objectSchema\n } = value as Record<string, unknown>\n\n if (displayDescription.value && 'description' in objectSchema) {\n const { description: _description, ...schemaWithoutDescription } =\n objectSchema\n return schemaWithoutDescription as SchemaObject\n }\n\n return objectSchema as SchemaObject\n})\n\n/** Determine if property heading should be displayed */\nconst shouldDisplayHeadingComputed = computed(() =>\n shouldDisplayHeading(optimizedValue.value, props.name, props.required),\n)\n\n/** Computes which compositions should be rendered and with which values */\nconst compositionsToRender = computed(() =>\n getCompositionsToRender(optimizedValue.value, props.options.document),\n)\n\n/**\n * Get resolved array items for rendering.\n *\n * When the items are wrapped in a single-item composition (e.g. `items: { allOf: [{ type: 'object', ... }] }`), we\n * flatten that wrapper into its plain form. A composition with a single member is equivalent to that member, so\n * keeping the composition keyword only makes the items render through an extra schema layer, which adds an\n * unnecessary level of nesting and duplicates the item description. See https://github.com/scalar/scalar/issues/5900\n */\nconst resolvedArrayItems = computed(() => {\n const value = optimizedValue.value\n if (!value || !isArraySchema(value) || typeof value.items !== 'object') {\n return undefined\n }\n\n const items = resolve.schema(value.items)\n const hasSingleItemComposition = SINGLE_ITEM_COMPOSITIONS.some(\n (keyword) =>\n Array.isArray(items?.[keyword]) && items[keyword]?.length === 1,\n )\n\n return hasSingleItemComposition ? optimizeValueForDisplay(items) : items\n})\n\n/**\n * Cycle key for the array items schema, derived from the raw (unresolved) items\n * so a self-referential array element is detected as a cycle.\n */\nconst arrayItemsCycleKey = computed(() => {\n const value = optimizedValue.value\n if (!value || !isArraySchema(value)) {\n return undefined\n }\n return getCycleKey(value.items)\n})\n\n/** Check if discriminator matches current property */\nconst isDiscriminatorProperty = computed(() =>\n Boolean(props.name && props.discriminator?.propertyName === props.name),\n)\n</script>\n<template>\n <component\n :is=\"is ?? 'li'\"\n class=\"property\"\n :class=\"[\n `property--level-${level}`,\n {\n 'property--compact': compact,\n 'property--deprecated': optimizedValue?.deprecated,\n },\n ]\">\n <SchemaPropertyHeading\n v-if=\"shouldDisplayHeadingComputed\"\n class=\"group\"\n :enum=\"hasEnum\"\n :eventBus=\"eventBus\"\n :hideModelNames\n :isDiscriminator=\"isDiscriminatorProperty\"\n :modelName=\"modelName\"\n :required\n :value=\"optimizedValue\">\n <template\n v-if=\"name\"\n #name>\n <WithBreadcrumb\n :breadcrumb=\"shouldHaveLink ? childBreadcrumb : undefined\"\n :eventBus=\"eventBus\">\n <span\n v-if=\"variant === 'patternProperties'\"\n class=\"property-name-pattern-properties\">\n <ScalarWrappingText\n preset=\"property\"\n :text=\"name\" />\n </span>\n <span\n v-else-if=\"variant === 'additionalProperties'\"\n class=\"property-name-additional-properties\">\n <ScalarWrappingText\n preset=\"property\"\n :text=\"name\" />\n </span>\n <ScalarWrappingText\n v-else\n preset=\"property\"\n :text=\"name\" />\n </WithBreadcrumb>\n </template>\n <template\n v-if=\"optimizedValue?.example !== undefined\"\n #example>\n Example:\n {{ optimizedValue.example }}\n </template>\n </SchemaPropertyHeading>\n\n <!-- Description -->\n <div\n v-if=\"displayDescription || propertyDescription\"\n class=\"property-description\">\n <ScalarMarkdown\n :value=\"displayDescription || propertyDescription || ''\" />\n </div>\n\n <!-- Enum for property names -->\n <SchemaEnums\n v-if=\"propertyNamesEnum && propertyNamesEnum.length > 0\"\n propertyNames\n :value=\"{ enum: propertyNamesEnum } as SchemaObject\" />\n\n <!-- Enum values -->\n <SchemaEnums\n v-if=\"enumValues.length > 0\"\n :value=\"optimizedValue\" />\n\n <!-- Object -->\n <div\n v-if=\"shouldRenderObjectProperties\"\n class=\"children\">\n <Schema\n :breadcrumb=\"childBreadcrumb\"\n :compact=\"compact\"\n :compositionPath=\"currentCompositionPath\"\n :cycleKey=\"cycleKey\"\n :eventBus=\"eventBus\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"noncollapsible\"\n :options=\"options\"\n :schema=\"objectSchemaForChildren\"\n :schemaContext=\"schemaContext\" />\n </div>\n\n <!-- Array of objects or nested arrays -->\n <div\n v-if=\"shouldRenderArrayOfObjects && resolvedArrayItems\"\n class=\"children\">\n <Schema\n :compact=\"compact\"\n :compositionPath=\"arrayItemsCompositionPath\"\n :cycleKey=\"arrayItemsCycleKey\"\n :eventBus=\"eventBus\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"noncollapsible\"\n :options=\"options\"\n :schema=\"resolve.schema(resolvedArrayItems)\"\n :schemaContext=\"schemaContext\" />\n </div>\n\n <!-- Compositions -->\n <SchemaComposition\n v-for=\"compositionData in compositionsToRender\"\n :key=\"compositionData.composition\"\n :breadcrumb=\"breadcrumb\"\n :compact=\"compact\"\n :composition=\"compositionData.composition\"\n :compositionPath=\"currentCompositionPath\"\n :discriminator=\"schema?.discriminator\"\n :eventBus=\"eventBus\"\n :hideHeading=\"hideHeading\"\n :hideModelNames\n :level=\"level\"\n :name=\"name\"\n :noncollapsible=\"noncollapsible\"\n :options=\"options\"\n :schema=\"compositionData.value\"\n :schemaContext=\"schemaContext\" />\n <SpecificationExtension :value=\"optimizedValue\" />\n </component>\n</template>\n\n<style scoped>\n.property {\n color: var(--scalar-color-1);\n display: flex;\n flex-direction: column;\n padding: 10px;\n font-size: var(--scalar-small);\n position: relative;\n}\n\n/** Remove top padding for top level schema card */\n.property.property--level-0:has(\n > .property-rule\n > .schema-card\n > .schema-properties.schema-properties-open\n > ul\n > li.property\n ) {\n padding-top: 0;\n}\n\n.property--compact.property--level-0,\n.property--compact.property--level-1 {\n padding: 10px 0;\n}\n\n.composition-panel .property.property.property.property--level-0 {\n padding: 0px;\n}\n\n.property--compact.property--level-0\n .composition-panel\n .property--compact.property--level-1 {\n padding: 8px;\n}\n\n/* if a property doesn't have a heading, remove the top padding */\n.property:has(> .property-rule:nth-of-type(1)):not(.property--compact) {\n padding-top: 8px;\n padding-bottom: 8px;\n}\n\n.property--deprecated {\n background: repeating-linear-gradient(\n -45deg,\n var(--scalar-background-2) 0,\n var(--scalar-background-2) 2px,\n transparent 2px,\n transparent 5px\n );\n background-size: 100%;\n}\n\n.property--deprecated > * {\n opacity: 0.75;\n}\n\n.property-description {\n margin-top: 6px;\n line-height: 1.4;\n font-size: var(--scalar-small);\n}\n\n.property-description:has(+ .property-rule) {\n margin-bottom: 9px;\n}\n\n:deep(.property-description) * {\n color: var(--scalar-color-2) !important;\n}\n\n.property:not(:last-of-type) {\n border-bottom: var(--scalar-border-width) solid var(--scalar-border-color);\n}\n\n.property-description + .children,\n.children + .property-rule {\n margin-top: 9px;\n}\n\n.children {\n display: flex;\n flex-direction: column;\n}\n\n.children .property--compact.property--level-1 {\n padding: 12px;\n}\n\n.property-example-value {\n all: unset;\n font-family: var(--scalar-font-code);\n padding: 6px;\n border-top: var(--scalar-border-width) solid var(--scalar-border-color);\n}\n\n.property-rule {\n border-radius: var(--scalar-radius-lg);\n display: flex;\n flex-direction: column;\n}\n\n.property--level-2 :deep(.relative > button) {\n left: -2rem;\n}\n\n.property-rule\n :deep(\n .composition-panel\n .schema-card--level-1\n > .schema-properties.schema-properties-open\n ) {\n border-radius: 0 0 var(--scalar-radius-lg) var(--scalar-radius-lg);\n}\n\n.property-rule\n :deep(.composition-panel > .schema-card > .schema-card-description) {\n padding: 10px;\n border-left: var(--scalar-border-width) solid var(--scalar-border-color);\n border-right: var(--scalar-border-width) solid var(--scalar-border-color);\n\n & + .schema-properties {\n margin-top: 0;\n }\n}\n\n.property-example {\n background: transparent;\n border: none;\n display: flex;\n flex-direction: row;\n gap: 8px;\n}\n\n.property-example-label,\n.property-example-value {\n padding: 3px 0 0 0;\n}\n\n.property-example-value {\n background: var(--scalar-background-2);\n border-top: 0;\n border-radius: var(--scalar-radius);\n padding: 3px 4px;\n}\n\n.property-name {\n font-family: var(--scalar-font-code);\n font-weight: var(--scalar-semibold);\n}\n\n.property-name-additional-properties::before,\n.property-name-pattern-properties::before {\n text-transform: uppercase;\n font-size: var(--scalar-micro);\n display: inline-block;\n padding: 2px 4px;\n border-radius: var(--scalar-radius);\n color: var(--scalar-color-1);\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n background-color: var(--scalar-background-2);\n margin-right: 4px;\n}\n\n.property-name-pattern-properties::before {\n content: 'regex';\n}\n\n.property-name-additional-properties,\n.property-name-pattern-properties {\n border: 1px dashed var(--scalar-border-color);\n color: var(--scalar-color-accent);\n display: inline-block;\n padding: 2px;\n border-radius: var(--scalar-radius);\n}\n</style>\n"],"mappings":""}
@@ -16,8 +16,8 @@ import Schema_default from "./Schema.vue.js";
16
16
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createSlots, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, renderList, resolveDynamicComponent, toDisplayString, unref, withCtx } from "vue";
17
17
  import { ScalarMarkdown } from "@scalar/components/markdown";
18
18
  import { resolve } from "@scalar/workspace-store/resolve";
19
- import { ScalarWrappingText } from "@scalar/components/wrapping-text";
20
19
  import { isArraySchema } from "@scalar/workspace-store/schemas/v3.1/strict/type-guards";
20
+ import { ScalarWrappingText } from "@scalar/components/wrapping-text";
21
21
  //#region src/components/Content/Schema/SchemaProperty.vue?vue&type=script&setup=true&lang.ts
22
22
  var _hoisted_1 = {
23
23
  key: 0,
@@ -101,7 +101,11 @@ var SchemaProperty_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
101
101
  const shouldRenderObjectProperties = computed(() => {
102
102
  const value = optimizedValue.value;
103
103
  if (!value) return false;
104
- return isTypeObject(value) && ("properties" in value || "additionalProperties" in value);
104
+ if (!("properties" in value || "additionalProperties" in value)) return false;
105
+ if ("allOf" in value) return false;
106
+ const type = value.type;
107
+ const isExplicitNonObject = typeof type === "string" && type !== "object";
108
+ return isTypeObject(value) || !isExplicitNonObject;
105
109
  });
106
110
  /** Determine if array of objects should be rendered */
107
111
  const shouldRenderArrayOfObjects = computed(() => {
@@ -116,13 +120,24 @@ var SchemaProperty_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
116
120
  /** Determine if description should be displayed */
117
121
  const displayDescription = computed(() => shouldDisplayDescription(optimizedValue.value, props.description));
118
122
  /**
119
- * When the property already renders the description, avoid repeating it in the nested object schema card.
123
+ * The schema used to render the object's own properties.
124
+ *
125
+ * Composition keywords are stripped so the nested object renders only its
126
+ * properties. The compositions are rendered separately below; leaving them here
127
+ * would route the nested `Schema` back through `SchemaProperty` and recurse.
128
+ *
129
+ * When the property already renders the description, we also drop it to avoid
130
+ * repeating it in the nested object schema card.
120
131
  */
121
132
  const objectSchemaForChildren = computed(() => {
122
133
  const value = optimizedValue.value;
123
- if (!value || !displayDescription.value || !("description" in value)) return value;
124
- const { description: _description, ...schemaWithoutDescription } = value;
125
- return schemaWithoutDescription;
134
+ if (!value) return value;
135
+ const { oneOf: _oneOf, anyOf: _anyOf, allOf: _allOf, not: _not, ...objectSchema } = value;
136
+ if (displayDescription.value && "description" in objectSchema) {
137
+ const { description: _description, ...schemaWithoutDescription } = objectSchema;
138
+ return schemaWithoutDescription;
139
+ }
140
+ return objectSchema;
126
141
  });
127
142
  /** Determine if property heading should be displayed */
128
143
  const shouldDisplayHeadingComputed = computed(() => shouldDisplayHeading(optimizedValue.value, props.name, props.required));
@@ -1 +1 @@
1
- {"version":3,"file":"SchemaProperty.vue.script.js","names":[],"sources":["../../../../src/components/Content/Schema/SchemaProperty.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { ScalarMarkdown } from '@scalar/components/markdown'\nimport { ScalarWrappingText } from '@scalar/components/wrapping-text'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type {\n DiscriminatorObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { isArraySchema } from '@scalar/workspace-store/schemas/v3.1/strict/type-guards'\nimport { computed, type Component } from 'vue'\n\nimport { WithBreadcrumb } from '@/components/Anchor'\nimport { isTypeObject } from '@/components/Content/Schema/helpers/is-type-object'\nimport { getCycleKey } from '@/components/Content/Schema/helpers/schema-cycle'\nimport type { SchemaOptions } from '@/components/Content/Schema/types'\nimport { SpecificationExtension } from '@/features/specification-extension'\n\nimport { getCompositionsToRender } from './helpers/get-compositions-to-render'\nimport { getEnumValues } from './helpers/get-enum-values'\nimport { getPropertyDescription } from './helpers/get-property-description'\nimport { hasComplexArrayItems } from './helpers/has-complex-array-items'\nimport { optimizeValueForDisplay } from './helpers/optimize-value-for-display'\nimport { shouldDisplayDescription } from './helpers/should-display-description'\nimport { shouldDisplayHeading } from './helpers/should-display-heading'\nimport Schema from './Schema.vue'\nimport SchemaComposition from './SchemaComposition.vue'\nimport SchemaEnums from './SchemaEnums.vue'\nimport SchemaPropertyHeading from './SchemaPropertyHeading.vue'\n\n/**\n * Note: We're taking in a prop called `value` which should be a JSON Schema.\n *\n * We're using `optimizeValueForDisplay` to merge null types in compositions (anyOf, allOf, oneOf, not).\n * So you should basically use the optimizedValue everywhere in the component.\n */\n\n/** Composition keywords that hold a list of schemas and can be flattened when they contain a single member. */\nconst SINGLE_ITEM_COMPOSITIONS = ['oneOf', 'anyOf', 'allOf'] as const\n\nconst props = withDefaults(\n defineProps<{\n is?: string | Component\n schema: SchemaObject | undefined\n noncollapsible?: boolean\n level?: number\n name?: string\n required?: boolean\n compact?: boolean\n discriminator?: DiscriminatorObject\n description?: string\n hideModelNames?: boolean\n hideHeading?: boolean\n /** When the root schema was resolved from a $ref, pass the ref name for display (e.g. \"Data\"). */\n modelName?: string | null\n variant?: 'additionalProperties' | 'patternProperties'\n breadcrumb?: string[]\n eventBus: WorkspaceEventBus | null\n options: SchemaOptions\n /** Enum values for property names (from JSON Schema propertyNames keyword). */\n propertyNamesEnum?: string[]\n /** When \"requestBody\", composition selection is synced with the example snippet */\n schemaContext?: string\n /** Internal path used to sync nested request body compositions with the code sample */\n compositionPath?: string[]\n /** Internal path segment for this property when building nested composition keys */\n compositionPathSegment?: string\n /** Stable identity of this property's schema, used for cycle detection. */\n cycleKey?: unknown\n }>(),\n {\n level: 0,\n required: false,\n compact: false,\n hideModelNames: false,\n },\n)\n\n/** Simplified composition with `null` type. */\nconst optimizedValue = computed(() => optimizeValueForDisplay(props.schema))\n\nconst childBreadcrumb = computed<string[] | undefined>(() =>\n props.breadcrumb && props.name\n ? [...props.breadcrumb, props.name]\n : undefined,\n)\n\nconst currentCompositionPath = computed<string[]>(() =>\n props.compositionPathSegment\n ? [...(props.compositionPath ?? []), props.compositionPathSegment]\n : (props.compositionPath ?? []),\n)\n\nconst arrayItemsCompositionPath = computed<string[]>(() => [\n ...currentCompositionPath.value,\n 'items',\n])\n\nconst shouldHaveLink = computed(() => props.level <= 2)\n\n/** Checks if array items have complex structure */\nconst hasComplexArrayItemsComputed = computed(() =>\n hasComplexArrayItems(optimizedValue.value),\n)\n\n/** Check if enum should be displayed (from value schema or from propertyNames) */\nconst hasEnum = computed(() => enumValues.value.length > 0)\n\n/** Determine if object properties should be displayed */\nconst shouldRenderObjectProperties = computed(() => {\n const value = optimizedValue.value\n if (!value) {\n return false\n }\n\n return (\n isTypeObject(value) &&\n ('properties' in value || 'additionalProperties' in value)\n )\n})\n\n/** Determine if array of objects should be rendered */\nconst shouldRenderArrayOfObjects = computed(() => {\n const value = optimizedValue.value\n if (!value || !isArraySchema(value) || typeof value.items !== 'object') {\n return false\n }\n\n return hasComplexArrayItemsComputed.value\n})\n\n/** Extract enum values from schema or array items */\nconst enumValues = computed(() => getEnumValues(optimizedValue.value))\n\n/** Generate property description from type/format */\nconst propertyDescription = computed(() =>\n getPropertyDescription(optimizedValue.value),\n)\n\n/** Determine if description should be displayed */\nconst displayDescription = computed(() =>\n shouldDisplayDescription(optimizedValue.value, props.description),\n)\n\n/**\n * When the property already renders the description, avoid repeating it in the nested object schema card.\n */\nconst objectSchemaForChildren = computed(() => {\n const value = optimizedValue.value\n if (!value || !displayDescription.value || !('description' in value)) {\n return value\n }\n\n const { description: _description, ...schemaWithoutDescription } = value\n return schemaWithoutDescription as SchemaObject\n})\n\n/** Determine if property heading should be displayed */\nconst shouldDisplayHeadingComputed = computed(() =>\n shouldDisplayHeading(optimizedValue.value, props.name, props.required),\n)\n\n/** Computes which compositions should be rendered and with which values */\nconst compositionsToRender = computed(() =>\n getCompositionsToRender(optimizedValue.value, props.options.document),\n)\n\n/**\n * Get resolved array items for rendering.\n *\n * When the items are wrapped in a single-item composition (e.g. `items: { allOf: [{ type: 'object', ... }] }`), we\n * flatten that wrapper into its plain form. A composition with a single member is equivalent to that member, so\n * keeping the composition keyword only makes the items render through an extra schema layer, which adds an\n * unnecessary level of nesting and duplicates the item description. See https://github.com/scalar/scalar/issues/5900\n */\nconst resolvedArrayItems = computed(() => {\n const value = optimizedValue.value\n if (!value || !isArraySchema(value) || typeof value.items !== 'object') {\n return undefined\n }\n\n const items = resolve.schema(value.items)\n const hasSingleItemComposition = SINGLE_ITEM_COMPOSITIONS.some(\n (keyword) =>\n Array.isArray(items?.[keyword]) && items[keyword]?.length === 1,\n )\n\n return hasSingleItemComposition ? optimizeValueForDisplay(items) : items\n})\n\n/**\n * Cycle key for the array items schema, derived from the raw (unresolved) items\n * so a self-referential array element is detected as a cycle.\n */\nconst arrayItemsCycleKey = computed(() => {\n const value = optimizedValue.value\n if (!value || !isArraySchema(value)) {\n return undefined\n }\n return getCycleKey(value.items)\n})\n\n/** Check if discriminator matches current property */\nconst isDiscriminatorProperty = computed(() =>\n Boolean(props.name && props.discriminator?.propertyName === props.name),\n)\n</script>\n<template>\n <component\n :is=\"is ?? 'li'\"\n class=\"property\"\n :class=\"[\n `property--level-${level}`,\n {\n 'property--compact': compact,\n 'property--deprecated': optimizedValue?.deprecated,\n },\n ]\">\n <SchemaPropertyHeading\n v-if=\"shouldDisplayHeadingComputed\"\n class=\"group\"\n :enum=\"hasEnum\"\n :eventBus=\"eventBus\"\n :hideModelNames\n :isDiscriminator=\"isDiscriminatorProperty\"\n :modelName=\"modelName\"\n :required\n :value=\"optimizedValue\">\n <template\n v-if=\"name\"\n #name>\n <WithBreadcrumb\n :breadcrumb=\"shouldHaveLink ? childBreadcrumb : undefined\"\n :eventBus=\"eventBus\">\n <span\n v-if=\"variant === 'patternProperties'\"\n class=\"property-name-pattern-properties\">\n <ScalarWrappingText\n preset=\"property\"\n :text=\"name\" />\n </span>\n <span\n v-else-if=\"variant === 'additionalProperties'\"\n class=\"property-name-additional-properties\">\n <ScalarWrappingText\n preset=\"property\"\n :text=\"name\" />\n </span>\n <ScalarWrappingText\n v-else\n preset=\"property\"\n :text=\"name\" />\n </WithBreadcrumb>\n </template>\n <template\n v-if=\"optimizedValue?.example !== undefined\"\n #example>\n Example:\n {{ optimizedValue.example }}\n </template>\n </SchemaPropertyHeading>\n\n <!-- Description -->\n <div\n v-if=\"displayDescription || propertyDescription\"\n class=\"property-description\">\n <ScalarMarkdown\n :value=\"displayDescription || propertyDescription || ''\" />\n </div>\n\n <!-- Enum for property names -->\n <SchemaEnums\n v-if=\"propertyNamesEnum && propertyNamesEnum.length > 0\"\n propertyNames\n :value=\"{ enum: propertyNamesEnum } as SchemaObject\" />\n\n <!-- Enum values -->\n <SchemaEnums\n v-if=\"enumValues.length > 0\"\n :value=\"optimizedValue\" />\n\n <!-- Object -->\n <div\n v-if=\"shouldRenderObjectProperties\"\n class=\"children\">\n <Schema\n :breadcrumb=\"childBreadcrumb\"\n :compact=\"compact\"\n :compositionPath=\"currentCompositionPath\"\n :cycleKey=\"cycleKey\"\n :eventBus=\"eventBus\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"noncollapsible\"\n :options=\"options\"\n :schema=\"objectSchemaForChildren\"\n :schemaContext=\"schemaContext\" />\n </div>\n\n <!-- Array of objects or nested arrays -->\n <div\n v-if=\"shouldRenderArrayOfObjects && resolvedArrayItems\"\n class=\"children\">\n <Schema\n :compact=\"compact\"\n :compositionPath=\"arrayItemsCompositionPath\"\n :cycleKey=\"arrayItemsCycleKey\"\n :eventBus=\"eventBus\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"noncollapsible\"\n :options=\"options\"\n :schema=\"resolve.schema(resolvedArrayItems)\"\n :schemaContext=\"schemaContext\" />\n </div>\n\n <!-- Compositions -->\n <SchemaComposition\n v-for=\"compositionData in compositionsToRender\"\n :key=\"compositionData.composition\"\n :breadcrumb=\"breadcrumb\"\n :compact=\"compact\"\n :composition=\"compositionData.composition\"\n :compositionPath=\"currentCompositionPath\"\n :discriminator=\"schema?.discriminator\"\n :eventBus=\"eventBus\"\n :hideHeading=\"hideHeading\"\n :hideModelNames\n :level=\"level\"\n :name=\"name\"\n :noncollapsible=\"noncollapsible\"\n :options=\"options\"\n :schema=\"compositionData.value\"\n :schemaContext=\"schemaContext\" />\n <SpecificationExtension :value=\"optimizedValue\" />\n </component>\n</template>\n\n<style scoped>\n.property {\n color: var(--scalar-color-1);\n display: flex;\n flex-direction: column;\n padding: 10px;\n font-size: var(--scalar-small);\n position: relative;\n}\n\n/** Remove top padding for top level schema card */\n.property.property--level-0:has(\n > .property-rule\n > .schema-card\n > .schema-properties.schema-properties-open\n > ul\n > li.property\n ) {\n padding-top: 0;\n}\n\n.property--compact.property--level-0,\n.property--compact.property--level-1 {\n padding: 10px 0;\n}\n\n.composition-panel .property.property.property.property--level-0 {\n padding: 0px;\n}\n\n.property--compact.property--level-0\n .composition-panel\n .property--compact.property--level-1 {\n padding: 8px;\n}\n\n/* if a property doesn't have a heading, remove the top padding */\n.property:has(> .property-rule:nth-of-type(1)):not(.property--compact) {\n padding-top: 8px;\n padding-bottom: 8px;\n}\n\n.property--deprecated {\n background: repeating-linear-gradient(\n -45deg,\n var(--scalar-background-2) 0,\n var(--scalar-background-2) 2px,\n transparent 2px,\n transparent 5px\n );\n background-size: 100%;\n}\n\n.property--deprecated > * {\n opacity: 0.75;\n}\n\n.property-description {\n margin-top: 6px;\n line-height: 1.4;\n font-size: var(--scalar-small);\n}\n\n.property-description:has(+ .property-rule) {\n margin-bottom: 9px;\n}\n\n:deep(.property-description) * {\n color: var(--scalar-color-2) !important;\n}\n\n.property:not(:last-of-type) {\n border-bottom: var(--scalar-border-width) solid var(--scalar-border-color);\n}\n\n.property-description + .children,\n.children + .property-rule {\n margin-top: 9px;\n}\n\n.children {\n display: flex;\n flex-direction: column;\n}\n\n.children .property--compact.property--level-1 {\n padding: 12px;\n}\n\n.property-example-value {\n all: unset;\n font-family: var(--scalar-font-code);\n padding: 6px;\n border-top: var(--scalar-border-width) solid var(--scalar-border-color);\n}\n\n.property-rule {\n border-radius: var(--scalar-radius-lg);\n display: flex;\n flex-direction: column;\n}\n\n.property--level-2 :deep(.relative > button) {\n left: -2rem;\n}\n\n.property-rule\n :deep(\n .composition-panel\n .schema-card--level-1\n > .schema-properties.schema-properties-open\n ) {\n border-radius: 0 0 var(--scalar-radius-lg) var(--scalar-radius-lg);\n}\n\n.property-rule\n :deep(.composition-panel > .schema-card > .schema-card-description) {\n padding: 10px;\n border-left: var(--scalar-border-width) solid var(--scalar-border-color);\n border-right: var(--scalar-border-width) solid var(--scalar-border-color);\n\n & + .schema-properties {\n margin-top: 0;\n }\n}\n\n.property-example {\n background: transparent;\n border: none;\n display: flex;\n flex-direction: row;\n gap: 8px;\n}\n\n.property-example-label,\n.property-example-value {\n padding: 3px 0 0 0;\n}\n\n.property-example-value {\n background: var(--scalar-background-2);\n border-top: 0;\n border-radius: var(--scalar-radius);\n padding: 3px 4px;\n}\n\n.property-name {\n font-family: var(--scalar-font-code);\n font-weight: var(--scalar-semibold);\n}\n\n.property-name-additional-properties::before,\n.property-name-pattern-properties::before {\n text-transform: uppercase;\n font-size: var(--scalar-micro);\n display: inline-block;\n padding: 2px 4px;\n border-radius: var(--scalar-radius);\n color: var(--scalar-color-1);\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n background-color: var(--scalar-background-2);\n margin-right: 4px;\n}\n\n.property-name-pattern-properties::before {\n content: 'regex';\n}\n\n.property-name-additional-properties,\n.property-name-pattern-properties {\n border: 1px dashed var(--scalar-border-color);\n color: var(--scalar-color-accent);\n display: inline-block;\n padding: 2px;\n border-radius: var(--scalar-radius);\n}\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"SchemaProperty.vue.script.js","names":[],"sources":["../../../../src/components/Content/Schema/SchemaProperty.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { ScalarMarkdown } from '@scalar/components/markdown'\nimport { ScalarWrappingText } from '@scalar/components/wrapping-text'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type {\n DiscriminatorObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { isArraySchema } from '@scalar/workspace-store/schemas/v3.1/strict/type-guards'\nimport { computed, type Component } from 'vue'\n\nimport { WithBreadcrumb } from '@/components/Anchor'\nimport { isTypeObject } from '@/components/Content/Schema/helpers/is-type-object'\nimport { getCycleKey } from '@/components/Content/Schema/helpers/schema-cycle'\nimport type { SchemaOptions } from '@/components/Content/Schema/types'\nimport { SpecificationExtension } from '@/features/specification-extension'\n\nimport { getCompositionsToRender } from './helpers/get-compositions-to-render'\nimport { getEnumValues } from './helpers/get-enum-values'\nimport { getPropertyDescription } from './helpers/get-property-description'\nimport { hasComplexArrayItems } from './helpers/has-complex-array-items'\nimport { optimizeValueForDisplay } from './helpers/optimize-value-for-display'\nimport { shouldDisplayDescription } from './helpers/should-display-description'\nimport { shouldDisplayHeading } from './helpers/should-display-heading'\nimport Schema from './Schema.vue'\nimport SchemaComposition from './SchemaComposition.vue'\nimport SchemaEnums from './SchemaEnums.vue'\nimport SchemaPropertyHeading from './SchemaPropertyHeading.vue'\n\n/**\n * Note: We're taking in a prop called `value` which should be a JSON Schema.\n *\n * We're using `optimizeValueForDisplay` to merge null types in compositions (anyOf, allOf, oneOf, not).\n * So you should basically use the optimizedValue everywhere in the component.\n */\n\n/** Composition keywords that hold a list of schemas and can be flattened when they contain a single member. */\nconst SINGLE_ITEM_COMPOSITIONS = ['oneOf', 'anyOf', 'allOf'] as const\n\nconst props = withDefaults(\n defineProps<{\n is?: string | Component\n schema: SchemaObject | undefined\n noncollapsible?: boolean\n level?: number\n name?: string\n required?: boolean\n compact?: boolean\n discriminator?: DiscriminatorObject\n description?: string\n hideModelNames?: boolean\n hideHeading?: boolean\n /** When the root schema was resolved from a $ref, pass the ref name for display (e.g. \"Data\"). */\n modelName?: string | null\n variant?: 'additionalProperties' | 'patternProperties'\n breadcrumb?: string[]\n eventBus: WorkspaceEventBus | null\n options: SchemaOptions\n /** Enum values for property names (from JSON Schema propertyNames keyword). */\n propertyNamesEnum?: string[]\n /** When \"requestBody\", composition selection is synced with the example snippet */\n schemaContext?: string\n /** Internal path used to sync nested request body compositions with the code sample */\n compositionPath?: string[]\n /** Internal path segment for this property when building nested composition keys */\n compositionPathSegment?: string\n /** Stable identity of this property's schema, used for cycle detection. */\n cycleKey?: unknown\n }>(),\n {\n level: 0,\n required: false,\n compact: false,\n hideModelNames: false,\n },\n)\n\n/** Simplified composition with `null` type. */\nconst optimizedValue = computed(() => optimizeValueForDisplay(props.schema))\n\nconst childBreadcrumb = computed<string[] | undefined>(() =>\n props.breadcrumb && props.name\n ? [...props.breadcrumb, props.name]\n : undefined,\n)\n\nconst currentCompositionPath = computed<string[]>(() =>\n props.compositionPathSegment\n ? [...(props.compositionPath ?? []), props.compositionPathSegment]\n : (props.compositionPath ?? []),\n)\n\nconst arrayItemsCompositionPath = computed<string[]>(() => [\n ...currentCompositionPath.value,\n 'items',\n])\n\nconst shouldHaveLink = computed(() => props.level <= 2)\n\n/** Checks if array items have complex structure */\nconst hasComplexArrayItemsComputed = computed(() =>\n hasComplexArrayItems(optimizedValue.value),\n)\n\n/** Check if enum should be displayed (from value schema or from propertyNames) */\nconst hasEnum = computed(() => enumValues.value.length > 0)\n\n/** Determine if object properties should be displayed */\nconst shouldRenderObjectProperties = computed(() => {\n const value = optimizedValue.value\n if (!value) {\n return false\n }\n\n if (!('properties' in value || 'additionalProperties' in value)) {\n return false\n }\n\n // `allOf` already merges the factored-out sibling `properties` into its\n // rendered result (see `mergeAllOfSchemas`), so rendering a separate object\n // block here would show those properties twice. Let the composition handle it.\n if ('allOf' in value) {\n return false\n }\n\n // A schema may factor its common `properties` out to the top level alongside\n // a composition keyword (anyOf/oneOf/not), as described in the JSON Schema\n // \"factoring schemas\" guide. `isTypeObject` deliberately rejects such schemas\n // so the composition is rendered, but the factored-out properties must still\n // show. Unlike `allOf`, these compositions do not merge sibling properties.\n // Render them unless the schema is an explicit non-object (scalar or array)\n // type. See https://github.com/scalar/scalar/issues/8593\n const type = (value as { type?: unknown }).type\n const isExplicitNonObject = typeof type === 'string' && type !== 'object'\n\n return isTypeObject(value) || !isExplicitNonObject\n})\n\n/** Determine if array of objects should be rendered */\nconst shouldRenderArrayOfObjects = computed(() => {\n const value = optimizedValue.value\n if (!value || !isArraySchema(value) || typeof value.items !== 'object') {\n return false\n }\n\n return hasComplexArrayItemsComputed.value\n})\n\n/** Extract enum values from schema or array items */\nconst enumValues = computed(() => getEnumValues(optimizedValue.value))\n\n/** Generate property description from type/format */\nconst propertyDescription = computed(() =>\n getPropertyDescription(optimizedValue.value),\n)\n\n/** Determine if description should be displayed */\nconst displayDescription = computed(() =>\n shouldDisplayDescription(optimizedValue.value, props.description),\n)\n\n/**\n * The schema used to render the object's own properties.\n *\n * Composition keywords are stripped so the nested object renders only its\n * properties. The compositions are rendered separately below; leaving them here\n * would route the nested `Schema` back through `SchemaProperty` and recurse.\n *\n * When the property already renders the description, we also drop it to avoid\n * repeating it in the nested object schema card.\n */\nconst objectSchemaForChildren = computed(() => {\n const value = optimizedValue.value\n if (!value) {\n return value\n }\n\n const {\n oneOf: _oneOf,\n anyOf: _anyOf,\n allOf: _allOf,\n not: _not,\n ...objectSchema\n } = value as Record<string, unknown>\n\n if (displayDescription.value && 'description' in objectSchema) {\n const { description: _description, ...schemaWithoutDescription } =\n objectSchema\n return schemaWithoutDescription as SchemaObject\n }\n\n return objectSchema as SchemaObject\n})\n\n/** Determine if property heading should be displayed */\nconst shouldDisplayHeadingComputed = computed(() =>\n shouldDisplayHeading(optimizedValue.value, props.name, props.required),\n)\n\n/** Computes which compositions should be rendered and with which values */\nconst compositionsToRender = computed(() =>\n getCompositionsToRender(optimizedValue.value, props.options.document),\n)\n\n/**\n * Get resolved array items for rendering.\n *\n * When the items are wrapped in a single-item composition (e.g. `items: { allOf: [{ type: 'object', ... }] }`), we\n * flatten that wrapper into its plain form. A composition with a single member is equivalent to that member, so\n * keeping the composition keyword only makes the items render through an extra schema layer, which adds an\n * unnecessary level of nesting and duplicates the item description. See https://github.com/scalar/scalar/issues/5900\n */\nconst resolvedArrayItems = computed(() => {\n const value = optimizedValue.value\n if (!value || !isArraySchema(value) || typeof value.items !== 'object') {\n return undefined\n }\n\n const items = resolve.schema(value.items)\n const hasSingleItemComposition = SINGLE_ITEM_COMPOSITIONS.some(\n (keyword) =>\n Array.isArray(items?.[keyword]) && items[keyword]?.length === 1,\n )\n\n return hasSingleItemComposition ? optimizeValueForDisplay(items) : items\n})\n\n/**\n * Cycle key for the array items schema, derived from the raw (unresolved) items\n * so a self-referential array element is detected as a cycle.\n */\nconst arrayItemsCycleKey = computed(() => {\n const value = optimizedValue.value\n if (!value || !isArraySchema(value)) {\n return undefined\n }\n return getCycleKey(value.items)\n})\n\n/** Check if discriminator matches current property */\nconst isDiscriminatorProperty = computed(() =>\n Boolean(props.name && props.discriminator?.propertyName === props.name),\n)\n</script>\n<template>\n <component\n :is=\"is ?? 'li'\"\n class=\"property\"\n :class=\"[\n `property--level-${level}`,\n {\n 'property--compact': compact,\n 'property--deprecated': optimizedValue?.deprecated,\n },\n ]\">\n <SchemaPropertyHeading\n v-if=\"shouldDisplayHeadingComputed\"\n class=\"group\"\n :enum=\"hasEnum\"\n :eventBus=\"eventBus\"\n :hideModelNames\n :isDiscriminator=\"isDiscriminatorProperty\"\n :modelName=\"modelName\"\n :required\n :value=\"optimizedValue\">\n <template\n v-if=\"name\"\n #name>\n <WithBreadcrumb\n :breadcrumb=\"shouldHaveLink ? childBreadcrumb : undefined\"\n :eventBus=\"eventBus\">\n <span\n v-if=\"variant === 'patternProperties'\"\n class=\"property-name-pattern-properties\">\n <ScalarWrappingText\n preset=\"property\"\n :text=\"name\" />\n </span>\n <span\n v-else-if=\"variant === 'additionalProperties'\"\n class=\"property-name-additional-properties\">\n <ScalarWrappingText\n preset=\"property\"\n :text=\"name\" />\n </span>\n <ScalarWrappingText\n v-else\n preset=\"property\"\n :text=\"name\" />\n </WithBreadcrumb>\n </template>\n <template\n v-if=\"optimizedValue?.example !== undefined\"\n #example>\n Example:\n {{ optimizedValue.example }}\n </template>\n </SchemaPropertyHeading>\n\n <!-- Description -->\n <div\n v-if=\"displayDescription || propertyDescription\"\n class=\"property-description\">\n <ScalarMarkdown\n :value=\"displayDescription || propertyDescription || ''\" />\n </div>\n\n <!-- Enum for property names -->\n <SchemaEnums\n v-if=\"propertyNamesEnum && propertyNamesEnum.length > 0\"\n propertyNames\n :value=\"{ enum: propertyNamesEnum } as SchemaObject\" />\n\n <!-- Enum values -->\n <SchemaEnums\n v-if=\"enumValues.length > 0\"\n :value=\"optimizedValue\" />\n\n <!-- Object -->\n <div\n v-if=\"shouldRenderObjectProperties\"\n class=\"children\">\n <Schema\n :breadcrumb=\"childBreadcrumb\"\n :compact=\"compact\"\n :compositionPath=\"currentCompositionPath\"\n :cycleKey=\"cycleKey\"\n :eventBus=\"eventBus\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"noncollapsible\"\n :options=\"options\"\n :schema=\"objectSchemaForChildren\"\n :schemaContext=\"schemaContext\" />\n </div>\n\n <!-- Array of objects or nested arrays -->\n <div\n v-if=\"shouldRenderArrayOfObjects && resolvedArrayItems\"\n class=\"children\">\n <Schema\n :compact=\"compact\"\n :compositionPath=\"arrayItemsCompositionPath\"\n :cycleKey=\"arrayItemsCycleKey\"\n :eventBus=\"eventBus\"\n :hideModelNames\n :level=\"level + 1\"\n :name=\"name\"\n :noncollapsible=\"noncollapsible\"\n :options=\"options\"\n :schema=\"resolve.schema(resolvedArrayItems)\"\n :schemaContext=\"schemaContext\" />\n </div>\n\n <!-- Compositions -->\n <SchemaComposition\n v-for=\"compositionData in compositionsToRender\"\n :key=\"compositionData.composition\"\n :breadcrumb=\"breadcrumb\"\n :compact=\"compact\"\n :composition=\"compositionData.composition\"\n :compositionPath=\"currentCompositionPath\"\n :discriminator=\"schema?.discriminator\"\n :eventBus=\"eventBus\"\n :hideHeading=\"hideHeading\"\n :hideModelNames\n :level=\"level\"\n :name=\"name\"\n :noncollapsible=\"noncollapsible\"\n :options=\"options\"\n :schema=\"compositionData.value\"\n :schemaContext=\"schemaContext\" />\n <SpecificationExtension :value=\"optimizedValue\" />\n </component>\n</template>\n\n<style scoped>\n.property {\n color: var(--scalar-color-1);\n display: flex;\n flex-direction: column;\n padding: 10px;\n font-size: var(--scalar-small);\n position: relative;\n}\n\n/** Remove top padding for top level schema card */\n.property.property--level-0:has(\n > .property-rule\n > .schema-card\n > .schema-properties.schema-properties-open\n > ul\n > li.property\n ) {\n padding-top: 0;\n}\n\n.property--compact.property--level-0,\n.property--compact.property--level-1 {\n padding: 10px 0;\n}\n\n.composition-panel .property.property.property.property--level-0 {\n padding: 0px;\n}\n\n.property--compact.property--level-0\n .composition-panel\n .property--compact.property--level-1 {\n padding: 8px;\n}\n\n/* if a property doesn't have a heading, remove the top padding */\n.property:has(> .property-rule:nth-of-type(1)):not(.property--compact) {\n padding-top: 8px;\n padding-bottom: 8px;\n}\n\n.property--deprecated {\n background: repeating-linear-gradient(\n -45deg,\n var(--scalar-background-2) 0,\n var(--scalar-background-2) 2px,\n transparent 2px,\n transparent 5px\n );\n background-size: 100%;\n}\n\n.property--deprecated > * {\n opacity: 0.75;\n}\n\n.property-description {\n margin-top: 6px;\n line-height: 1.4;\n font-size: var(--scalar-small);\n}\n\n.property-description:has(+ .property-rule) {\n margin-bottom: 9px;\n}\n\n:deep(.property-description) * {\n color: var(--scalar-color-2) !important;\n}\n\n.property:not(:last-of-type) {\n border-bottom: var(--scalar-border-width) solid var(--scalar-border-color);\n}\n\n.property-description + .children,\n.children + .property-rule {\n margin-top: 9px;\n}\n\n.children {\n display: flex;\n flex-direction: column;\n}\n\n.children .property--compact.property--level-1 {\n padding: 12px;\n}\n\n.property-example-value {\n all: unset;\n font-family: var(--scalar-font-code);\n padding: 6px;\n border-top: var(--scalar-border-width) solid var(--scalar-border-color);\n}\n\n.property-rule {\n border-radius: var(--scalar-radius-lg);\n display: flex;\n flex-direction: column;\n}\n\n.property--level-2 :deep(.relative > button) {\n left: -2rem;\n}\n\n.property-rule\n :deep(\n .composition-panel\n .schema-card--level-1\n > .schema-properties.schema-properties-open\n ) {\n border-radius: 0 0 var(--scalar-radius-lg) var(--scalar-radius-lg);\n}\n\n.property-rule\n :deep(.composition-panel > .schema-card > .schema-card-description) {\n padding: 10px;\n border-left: var(--scalar-border-width) solid var(--scalar-border-color);\n border-right: var(--scalar-border-width) solid var(--scalar-border-color);\n\n & + .schema-properties {\n margin-top: 0;\n }\n}\n\n.property-example {\n background: transparent;\n border: none;\n display: flex;\n flex-direction: row;\n gap: 8px;\n}\n\n.property-example-label,\n.property-example-value {\n padding: 3px 0 0 0;\n}\n\n.property-example-value {\n background: var(--scalar-background-2);\n border-top: 0;\n border-radius: var(--scalar-radius);\n padding: 3px 4px;\n}\n\n.property-name {\n font-family: var(--scalar-font-code);\n font-weight: var(--scalar-semibold);\n}\n\n.property-name-additional-properties::before,\n.property-name-pattern-properties::before {\n text-transform: uppercase;\n font-size: var(--scalar-micro);\n display: inline-block;\n padding: 2px 4px;\n border-radius: var(--scalar-radius);\n color: var(--scalar-color-1);\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n background-color: var(--scalar-background-2);\n margin-right: 4px;\n}\n\n.property-name-pattern-properties::before {\n content: 'regex';\n}\n\n.property-name-additional-properties,\n.property-name-pattern-properties {\n border: 1px dashed var(--scalar-border-color);\n color: var(--scalar-color-accent);\n display: inline-block;\n padding: 2px;\n border-radius: var(--scalar-radius);\n}\n</style>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"merge-all-of-schemas.d.ts","sourceRoot":"","sources":["../../../../../src/components/Content/Schema/helpers/merge-all-of-schemas.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAA;AAGhG;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAC5B,SAAS,YAAY,GAAG,SAAS,EACjC,aAAa,YAAY,EACzB,WAAU,GAAG,CAAC,MAAM,CAAa,KAChC,YA+CF,CAAA"}
1
+ {"version":3,"file":"merge-all-of-schemas.d.ts","sourceRoot":"","sources":["../../../../../src/components/Content/Schema/helpers/merge-all-of-schemas.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAA;AAWhG;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAC5B,SAAS,YAAY,GAAG,SAAS,EACjC,aAAa,YAAY,EACzB,WAAU,GAAG,CAAC,MAAM,CAAa,KAChC,YA+CF,CAAA"}
@@ -1,9 +1,16 @@
1
1
  import { getResolvedRef } from "@scalar/workspace-store/helpers/get-resolved-ref";
2
2
  import { resolve } from "@scalar/workspace-store/resolve";
3
- import { isArraySchema } from "@scalar/workspace-store/schemas/v3.1/strict/type-guards";
4
3
  import { objectKeys } from "@scalar/helpers/object/object-keys";
4
+ import { isArraySchema } from "@scalar/workspace-store/schemas/v3.1/strict/type-guards";
5
5
  //#region src/components/Content/Schema/helpers/merge-all-of-schemas.ts
6
6
  /**
7
+ * Schema keywords whose value should reflect the *last* occurrence when merging
8
+ * `allOf` members. Most keywords keep the first occurrence, but for human-facing
9
+ * annotations a later subschema is expected to override an earlier one — matching
10
+ * OpenAPI/JSON Schema tooling like Swagger UI.
11
+ */
12
+ var LAST_WINS_KEYS = new Set(["description", "title"]);
13
+ /**
7
14
  * Merges multiple OpenAPI schema objects into a single schema object.
8
15
  * Handles nested allOf compositions and merges properties recursively.
9
16
  *
@@ -72,15 +79,9 @@ var mergeSchemaIntoResult = (result, schema, override = false, seenRefs = /* @__
72
79
  } else if (key === "enum") {
73
80
  if (Array.isArray(value) && value.length > 0) result.enum = [...new Set([...result.enum || [], ...value])];
74
81
  } else if (key === "oneOf" || key === "anyOf") {
75
- if (Array.isArray(value)) {
76
- if (!("properties" in result)) result.properties = {};
77
- for (const _option of value) {
78
- const option = resolve.schema(_option);
79
- if (option && "properties" in option && "properties" in result) mergePropertiesIntoResult(result.properties, option.properties, seenRefs);
80
- }
81
- }
82
+ if (Array.isArray(value) && value.length > 0 && (override || result[key] === void 0)) result[key] = value;
82
83
  } else if (key === "allOf") continue;
83
- else if (override || result[key] === void 0) result[key] = value;
84
+ else if (override || LAST_WINS_KEYS.has(key) || result[key] === void 0) result[key] = value;
84
85
  }
85
86
  };
86
87
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"merge-all-of-schemas.js","names":[],"sources":["../../../../../src/components/Content/Schema/helpers/merge-all-of-schemas.ts"],"sourcesContent":["import { objectKeys } from '@scalar/helpers/object/object-keys'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type { SchemaObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { isArraySchema } from '@scalar/workspace-store/schemas/v3.1/strict/type-guards'\n\n/**\n * Merges multiple OpenAPI schema objects into a single schema object.\n * Handles nested allOf compositions and merges properties recursively.\n *\n * @param schemas - Array of OpenAPI schema objects to merge\n * @param rootSchema - Optional root schema to merge with the result\n * @param seenRefs - `$ref` strings already being merged higher in the call stack\n * @returns Merged schema object\n */\nexport const mergeAllOfSchemas = (\n schemas: SchemaObject | undefined,\n rootSchema?: SchemaObject,\n seenRefs: Set<string> = new Set(),\n): SchemaObject => {\n // Handle max depth, empty or invalid input\n if (!schemas?.allOf?.length || !Array.isArray(schemas.allOf)) {\n return rootSchema || ({} as SchemaObject)\n }\n\n // Initialize result object once\n const result = {} as SchemaObject\n\n // Extract base schema properties (everything except allOf)\n const { allOf: _, ...baseSchema } = schemas\n\n // Process allOf schemas first\n for (const _schema of schemas.allOf) {\n if (!_schema || typeof _schema !== 'object') {\n continue\n }\n\n // Resolve ref if present\n const schema = resolve.schema(_schema)\n\n // Handle nested allOf recursively\n if (schema.allOf) {\n const nestedMerged = mergeAllOfSchemas(schema, undefined, seenRefs)\n mergeSchemaIntoResult(result, nestedMerged, false, seenRefs)\n continue\n }\n\n mergeSchemaIntoResult(result, schema, false, seenRefs)\n }\n\n // Apply base schema properties with precedence over allOf properties\n if (Object.keys(baseSchema).length > 0) {\n mergeSchemaIntoResult(result, baseSchema, true, seenRefs)\n }\n\n // Process root schema last if provided\n if (rootSchema && typeof rootSchema === 'object') {\n if (rootSchema.allOf) {\n const nestedMerged = mergeAllOfSchemas(rootSchema, undefined, seenRefs)\n mergeSchemaIntoResult(result, nestedMerged, true, seenRefs)\n } else {\n mergeSchemaIntoResult(result, rootSchema, true, seenRefs)\n }\n }\n\n return result\n}\n\n/**\n * Efficiently merges a source schema into a target result object.\n * Handles all schema merging logic in a single optimized function.\n *\n * @param result - The target schema object to merge into\n * @param schema - The source schema object to merge from\n * @param override - Whether to override existing properties (default: false)\n */\nconst mergeSchemaIntoResult = (\n result: SchemaObject,\n schema: SchemaObject,\n override: boolean = false,\n seenRefs: Set<string> = new Set(),\n): void => {\n // Early return if schema is empty\n const schemaKeys = objectKeys(schema)\n if (schemaKeys.length === 0) {\n return\n }\n\n // Loop through all schema properties and handle them appropriately\n for (const key of schemaKeys) {\n const value = getResolvedRef(schema[key]) as any\n\n if (value === undefined) {\n continue\n }\n\n // Required\n if ((key as string) === 'required') {\n // Merge required fields with deduplication\n if (Array.isArray(value) && value.length > 0) {\n // @ts-expect-error\n if (result.required?.length) {\n // @ts-expect-error\n result.required = [...new Set([...result.required, ...value])]\n } else {\n // @ts-expect-error\n result.required = value.slice()\n }\n }\n }\n // Properties\n else if ((key as string) === 'properties') {\n // Merge properties recursively\n if (value && typeof value === 'object') {\n // @ts-expect-error\n if (!result.properties) {\n // @ts-expect-error\n result.properties = {}\n }\n\n // @ts-expect-error\n mergePropertiesIntoResult(result.properties, value, seenRefs)\n }\n }\n // Items\n else if ((key as string) === 'items') {\n // Handle items (for both arrays and objects with items)\n const items = resolve.schema(value)\n if (items) {\n if (isArraySchema(schema)) {\n // @ts-expect-error\n if (!result.items) {\n // @ts-expect-error\n result.items = {}\n }\n\n // Handle allOf within array items\n if (items.allOf) {\n const mergedItems = mergeAllOfSchemas(items, undefined, seenRefs)\n // @ts-expect-error\n Object.assign(result.items, mergedItems)\n } else {\n // @ts-expect-error\n mergeItemsIntoResult(getResolvedRef(result.items), items, seenRefs)\n }\n }\n // For non-array types with items.allOf, merge into properties\n else if (items.allOf) {\n const mergedItems = mergeAllOfSchemas(items, undefined, seenRefs)\n if ('properties' in mergedItems) {\n if (!('properties' in result)) {\n // @ts-expect-error\n result.properties = {}\n }\n\n 'properties' in result && mergePropertiesIntoResult(result.properties, mergedItems.properties, seenRefs)\n }\n }\n // For non-array types without allOf, still set items if not already set\n else if (!('items' in result)) {\n // @ts-expect-error\n result.items = items\n }\n }\n }\n // Enum\n else if (key === 'enum') {\n if (Array.isArray(value) && value.length > 0) {\n result.enum = [...new Set([...(result.enum || []), ...value])]\n }\n }\n // OneOf/AnyOf\n else if (key === 'oneOf' || key === 'anyOf') {\n // Merge oneOf/anyOf subschema\n if (Array.isArray(value)) {\n if (!('properties' in result)) {\n // @ts-expect-error\n result.properties = {}\n }\n for (const _option of value) {\n const option = resolve.schema(_option)\n if (option && 'properties' in option && 'properties' in result) {\n mergePropertiesIntoResult(result.properties, option.properties, seenRefs)\n }\n }\n }\n }\n // Skip allOf as it's handled at a higher level\n else if (key === 'allOf') {\n continue\n }\n // For all other properties, preserve the first occurrence or override if specified\n else {\n if (override || result[key] === undefined) {\n result[key] = value\n }\n }\n }\n}\n\n/**\n * Efficiently merges properties into a result object without creating new objects.\n */\nconst mergePropertiesIntoResult = (\n result: Extract<SchemaObject, { type: 'object' }>['properties'],\n properties: Extract<SchemaObject, { type: 'object' }>['properties'],\n seenRefs: Set<string> = new Set(),\n): void => {\n const propertyKeys = Object.keys(properties ?? {})\n if (!properties || !result || propertyKeys.length === 0) {\n return\n }\n\n for (const key of propertyKeys) {\n const schema = resolve.schema(properties[key])\n if (!schema) {\n delete result[key]\n continue\n }\n\n if (typeof schema !== 'object') {\n result[key] = schema\n continue\n }\n\n if (!result[key]) {\n // Handle new property with allOf\n if (schema.allOf) {\n result[key] = mergeAllOfSchemas(schema, undefined, seenRefs)\n } else if (isArraySchema(schema) && resolve.schema(schema.items)?.allOf) {\n result[key] = {\n ...schema,\n items: mergeAllOfSchemas(resolve.schema(schema.items), undefined, seenRefs),\n }\n } else if (properties[key]) {\n result[key] = properties[key]\n }\n continue\n }\n\n // Merge existing property\n const existing = resolve.schema(result[key])\n\n // Break self-referential cycles: when this property's `$ref` is already\n // being merged higher in the call stack, keep the partially merged existing\n // schema instead of recursing into it again. This mirrors the guard in\n // `mergeItems` and covers schemas that point back at themselves through a\n // plain object property (e.g. a tree node whose `parent` $refs the node).\n const schemaRef = (schema as { $ref?: string }).$ref\n if (typeof schemaRef === 'string' && seenRefs.has(schemaRef)) {\n result[key] = existing\n continue\n }\n const nextSeenRefs = typeof schemaRef === 'string' ? new Set(seenRefs).add(schemaRef) : seenRefs\n\n if (schema.allOf) {\n result[key] = mergeAllOfSchemas({ allOf: [existing, ...schema.allOf] } as SchemaObject, undefined, nextSeenRefs)\n } else if (isArraySchema(schema) && isArraySchema(existing) && schema.items) {\n const existingItems = resolve.schema(existing.items)\n result[key] = {\n ...existing,\n type: 'array',\n items: existingItems\n ? mergeItems(existingItems, resolve.schema(schema.items), nextSeenRefs)\n : resolve.schema(schema.items),\n }\n } else {\n // Create merged object with properties handled separately\n if ('properties' in existing && 'properties' in schema) {\n const merged = { ...existing, ...schema }\n merged.properties = { ...existing.properties }\n mergePropertiesIntoResult(merged.properties, schema.properties, nextSeenRefs)\n result[key] = merged\n }\n // Simple merge without property recursion\n else {\n result[key] = { ...schema, ...existing }\n }\n }\n }\n}\n\n/**\n * Efficiently merges array items into a result object.\n */\nconst mergeItemsIntoResult = (result: SchemaObject, items: SchemaObject, seenRefs: Set<string> = new Set()): void => {\n // Handle allOf in items\n if (items.allOf || result.allOf) {\n // Build array without spreads for better performance\n const allOfSchemas: SchemaObject[] = []\n\n if (result.allOf) {\n for (const schema of result.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(result)\n }\n\n if (items.allOf) {\n for (const schema of items.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(items)\n }\n\n const merged = mergeAllOfSchemas({ allOf: allOfSchemas } as SchemaObject, undefined, seenRefs)\n Object.assign(result, merged)\n return\n }\n\n // Regular merge\n Object.assign(result, items)\n\n // Merge properties if both have them\n if ('properties' in result && 'properties' in items) {\n mergePropertiesIntoResult(result.properties, items.properties, seenRefs)\n }\n}\n\n/**\n * Helper function for merging items that returns a new object.\n */\nconst mergeItems = (\n existing: SchemaObject,\n incoming: SchemaObject,\n seenRefs: Set<string> = new Set(),\n): SchemaObject => {\n const incomingRef = (incoming as { $ref?: string }).$ref\n\n if (typeof incomingRef === 'string') {\n if (seenRefs.has(incomingRef)) {\n return existing\n }\n return mergeItemsInner(existing, incoming, new Set(seenRefs).add(incomingRef))\n }\n\n return mergeItemsInner(existing, incoming, seenRefs)\n}\n\nconst mergeItemsInner = (\n existing: SchemaObject,\n incoming: SchemaObject,\n seenRefs: Set<string> = new Set(),\n): SchemaObject => {\n // Handle allOf in either schema\n if (existing.allOf || incoming.allOf) {\n // Build array without spreads for better performance\n const allOfSchemas: SchemaObject[] = []\n\n if (existing.allOf) {\n for (const schema of existing.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(existing)\n }\n\n if (incoming.allOf) {\n for (const schema of incoming.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(incoming)\n }\n\n return mergeAllOfSchemas({ allOf: allOfSchemas } as SchemaObject, undefined, seenRefs)\n }\n\n const merged = { ...existing, ...incoming }\n\n // Recursively merge properties if both have properties\n if ('properties' in existing && 'properties' in incoming) {\n // @ts-expect-error\n merged.properties = { ...existing.properties }\n // @ts-expect-error\n mergePropertiesIntoResult(merged.properties, incoming.properties, seenRefs)\n }\n\n return merged as SchemaObject\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"merge-all-of-schemas.js","names":[],"sources":["../../../../../src/components/Content/Schema/helpers/merge-all-of-schemas.ts"],"sourcesContent":["import { objectKeys } from '@scalar/helpers/object/object-keys'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type { SchemaObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { isArraySchema } from '@scalar/workspace-store/schemas/v3.1/strict/type-guards'\n\n/**\n * Schema keywords whose value should reflect the *last* occurrence when merging\n * `allOf` members. Most keywords keep the first occurrence, but for human-facing\n * annotations a later subschema is expected to override an earlier one — matching\n * OpenAPI/JSON Schema tooling like Swagger UI.\n */\nconst LAST_WINS_KEYS = new Set<string>(['description', 'title'])\n\n/**\n * Merges multiple OpenAPI schema objects into a single schema object.\n * Handles nested allOf compositions and merges properties recursively.\n *\n * @param schemas - Array of OpenAPI schema objects to merge\n * @param rootSchema - Optional root schema to merge with the result\n * @param seenRefs - `$ref` strings already being merged higher in the call stack\n * @returns Merged schema object\n */\nexport const mergeAllOfSchemas = (\n schemas: SchemaObject | undefined,\n rootSchema?: SchemaObject,\n seenRefs: Set<string> = new Set(),\n): SchemaObject => {\n // Handle max depth, empty or invalid input\n if (!schemas?.allOf?.length || !Array.isArray(schemas.allOf)) {\n return rootSchema || ({} as SchemaObject)\n }\n\n // Initialize result object once\n const result = {} as SchemaObject\n\n // Extract base schema properties (everything except allOf)\n const { allOf: _, ...baseSchema } = schemas\n\n // Process allOf schemas first\n for (const _schema of schemas.allOf) {\n if (!_schema || typeof _schema !== 'object') {\n continue\n }\n\n // Resolve ref if present\n const schema = resolve.schema(_schema)\n\n // Handle nested allOf recursively\n if (schema.allOf) {\n const nestedMerged = mergeAllOfSchemas(schema, undefined, seenRefs)\n mergeSchemaIntoResult(result, nestedMerged, false, seenRefs)\n continue\n }\n\n mergeSchemaIntoResult(result, schema, false, seenRefs)\n }\n\n // Apply base schema properties with precedence over allOf properties\n if (Object.keys(baseSchema).length > 0) {\n mergeSchemaIntoResult(result, baseSchema, true, seenRefs)\n }\n\n // Process root schema last if provided\n if (rootSchema && typeof rootSchema === 'object') {\n if (rootSchema.allOf) {\n const nestedMerged = mergeAllOfSchemas(rootSchema, undefined, seenRefs)\n mergeSchemaIntoResult(result, nestedMerged, true, seenRefs)\n } else {\n mergeSchemaIntoResult(result, rootSchema, true, seenRefs)\n }\n }\n\n return result\n}\n\n/**\n * Efficiently merges a source schema into a target result object.\n * Handles all schema merging logic in a single optimized function.\n *\n * @param result - The target schema object to merge into\n * @param schema - The source schema object to merge from\n * @param override - Whether to override existing properties (default: false)\n */\nconst mergeSchemaIntoResult = (\n result: SchemaObject,\n schema: SchemaObject,\n override: boolean = false,\n seenRefs: Set<string> = new Set(),\n): void => {\n // Early return if schema is empty\n const schemaKeys = objectKeys(schema)\n if (schemaKeys.length === 0) {\n return\n }\n\n // Loop through all schema properties and handle them appropriately\n for (const key of schemaKeys) {\n const value = getResolvedRef(schema[key]) as any\n\n if (value === undefined) {\n continue\n }\n\n // Required\n if ((key as string) === 'required') {\n // Merge required fields with deduplication\n if (Array.isArray(value) && value.length > 0) {\n // @ts-expect-error\n if (result.required?.length) {\n // @ts-expect-error\n result.required = [...new Set([...result.required, ...value])]\n } else {\n // @ts-expect-error\n result.required = value.slice()\n }\n }\n }\n // Properties\n else if ((key as string) === 'properties') {\n // Merge properties recursively\n if (value && typeof value === 'object') {\n // @ts-expect-error\n if (!result.properties) {\n // @ts-expect-error\n result.properties = {}\n }\n\n // @ts-expect-error\n mergePropertiesIntoResult(result.properties, value, seenRefs)\n }\n }\n // Items\n else if ((key as string) === 'items') {\n // Handle items (for both arrays and objects with items)\n const items = resolve.schema(value)\n if (items) {\n if (isArraySchema(schema)) {\n // @ts-expect-error\n if (!result.items) {\n // @ts-expect-error\n result.items = {}\n }\n\n // Handle allOf within array items\n if (items.allOf) {\n const mergedItems = mergeAllOfSchemas(items, undefined, seenRefs)\n // @ts-expect-error\n Object.assign(result.items, mergedItems)\n } else {\n // @ts-expect-error\n mergeItemsIntoResult(getResolvedRef(result.items), items, seenRefs)\n }\n }\n // For non-array types with items.allOf, merge into properties\n else if (items.allOf) {\n const mergedItems = mergeAllOfSchemas(items, undefined, seenRefs)\n if ('properties' in mergedItems) {\n if (!('properties' in result)) {\n // @ts-expect-error\n result.properties = {}\n }\n\n 'properties' in result && mergePropertiesIntoResult(result.properties, mergedItems.properties, seenRefs)\n }\n }\n // For non-array types without allOf, still set items if not already set\n else if (!('items' in result)) {\n // @ts-expect-error\n result.items = items\n }\n }\n }\n // Enum\n else if (key === 'enum') {\n if (Array.isArray(value) && value.length > 0) {\n result.enum = [...new Set([...(result.enum || []), ...value])]\n }\n }\n // OneOf/AnyOf\n else if (key === 'oneOf' || key === 'anyOf') {\n // Preserve the composition itself so its variants keep rendering as a\n // selector. Flattening the option properties into the parent would drop\n // the variant structure entirely and silently lose branches that have no\n // top-level `properties` (for example branches that are themselves an\n // `allOf`). The sibling `allOf` members stay on `result` as base\n // properties, which the Schema component renders above the selector.\n if (Array.isArray(value) && value.length > 0 && (override || result[key] === undefined)) {\n result[key] = value\n }\n }\n // Skip allOf as it's handled at a higher level\n else if (key === 'allOf') {\n continue\n }\n // For all other properties, preserve the first occurrence or override if specified.\n // Annotation keywords (see LAST_WINS_KEYS) always take the latest value so a later\n // allOf member can override an earlier one.\n else {\n if (override || LAST_WINS_KEYS.has(key as string) || result[key] === undefined) {\n result[key] = value\n }\n }\n }\n}\n\n/**\n * Efficiently merges properties into a result object without creating new objects.\n */\nconst mergePropertiesIntoResult = (\n result: Extract<SchemaObject, { type: 'object' }>['properties'],\n properties: Extract<SchemaObject, { type: 'object' }>['properties'],\n seenRefs: Set<string> = new Set(),\n): void => {\n const propertyKeys = Object.keys(properties ?? {})\n if (!properties || !result || propertyKeys.length === 0) {\n return\n }\n\n for (const key of propertyKeys) {\n const schema = resolve.schema(properties[key])\n if (!schema) {\n delete result[key]\n continue\n }\n\n if (typeof schema !== 'object') {\n result[key] = schema\n continue\n }\n\n if (!result[key]) {\n // Handle new property with allOf\n if (schema.allOf) {\n result[key] = mergeAllOfSchemas(schema, undefined, seenRefs)\n } else if (isArraySchema(schema) && resolve.schema(schema.items)?.allOf) {\n result[key] = {\n ...schema,\n items: mergeAllOfSchemas(resolve.schema(schema.items), undefined, seenRefs),\n }\n } else if (properties[key]) {\n result[key] = properties[key]\n }\n continue\n }\n\n // Merge existing property\n const existing = resolve.schema(result[key])\n\n // Break self-referential cycles: when this property's `$ref` is already\n // being merged higher in the call stack, keep the partially merged existing\n // schema instead of recursing into it again. This mirrors the guard in\n // `mergeItems` and covers schemas that point back at themselves through a\n // plain object property (e.g. a tree node whose `parent` $refs the node).\n const schemaRef = (schema as { $ref?: string }).$ref\n if (typeof schemaRef === 'string' && seenRefs.has(schemaRef)) {\n result[key] = existing\n continue\n }\n const nextSeenRefs = typeof schemaRef === 'string' ? new Set(seenRefs).add(schemaRef) : seenRefs\n\n if (schema.allOf) {\n result[key] = mergeAllOfSchemas({ allOf: [existing, ...schema.allOf] } as SchemaObject, undefined, nextSeenRefs)\n } else if (isArraySchema(schema) && isArraySchema(existing) && schema.items) {\n const existingItems = resolve.schema(existing.items)\n result[key] = {\n ...existing,\n type: 'array',\n items: existingItems\n ? mergeItems(existingItems, resolve.schema(schema.items), nextSeenRefs)\n : resolve.schema(schema.items),\n }\n } else {\n // Create merged object with properties handled separately\n if ('properties' in existing && 'properties' in schema) {\n const merged = { ...existing, ...schema }\n merged.properties = { ...existing.properties }\n mergePropertiesIntoResult(merged.properties, schema.properties, nextSeenRefs)\n result[key] = merged\n }\n // Simple merge without property recursion\n else {\n result[key] = { ...schema, ...existing }\n }\n }\n }\n}\n\n/**\n * Efficiently merges array items into a result object.\n */\nconst mergeItemsIntoResult = (result: SchemaObject, items: SchemaObject, seenRefs: Set<string> = new Set()): void => {\n // Handle allOf in items\n if (items.allOf || result.allOf) {\n // Build array without spreads for better performance\n const allOfSchemas: SchemaObject[] = []\n\n if (result.allOf) {\n for (const schema of result.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(result)\n }\n\n if (items.allOf) {\n for (const schema of items.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(items)\n }\n\n const merged = mergeAllOfSchemas({ allOf: allOfSchemas } as SchemaObject, undefined, seenRefs)\n Object.assign(result, merged)\n return\n }\n\n // Regular merge\n Object.assign(result, items)\n\n // Merge properties if both have them\n if ('properties' in result && 'properties' in items) {\n mergePropertiesIntoResult(result.properties, items.properties, seenRefs)\n }\n}\n\n/**\n * Helper function for merging items that returns a new object.\n */\nconst mergeItems = (\n existing: SchemaObject,\n incoming: SchemaObject,\n seenRefs: Set<string> = new Set(),\n): SchemaObject => {\n const incomingRef = (incoming as { $ref?: string }).$ref\n\n if (typeof incomingRef === 'string') {\n if (seenRefs.has(incomingRef)) {\n return existing\n }\n return mergeItemsInner(existing, incoming, new Set(seenRefs).add(incomingRef))\n }\n\n return mergeItemsInner(existing, incoming, seenRefs)\n}\n\nconst mergeItemsInner = (\n existing: SchemaObject,\n incoming: SchemaObject,\n seenRefs: Set<string> = new Set(),\n): SchemaObject => {\n // Handle allOf in either schema\n if (existing.allOf || incoming.allOf) {\n // Build array without spreads for better performance\n const allOfSchemas: SchemaObject[] = []\n\n if (existing.allOf) {\n for (const schema of existing.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(existing)\n }\n\n if (incoming.allOf) {\n for (const schema of incoming.allOf) {\n allOfSchemas.push(resolve.schema(schema))\n }\n } else {\n allOfSchemas.push(incoming)\n }\n\n return mergeAllOfSchemas({ allOf: allOfSchemas } as SchemaObject, undefined, seenRefs)\n }\n\n const merged = { ...existing, ...incoming }\n\n // Recursively merge properties if both have properties\n if ('properties' in existing && 'properties' in incoming) {\n // @ts-expect-error\n merged.properties = { ...existing.properties }\n // @ts-expect-error\n mergePropertiesIntoResult(merged.properties, incoming.properties, seenRefs)\n }\n\n return merged as SchemaObject\n}\n"],"mappings":"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"}