@scalar/blocks 0.1.9 → 0.1.11

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 (28) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/code-example/components/CodeExample.vue.d.ts.map +1 -1
  3. package/dist/code-example/components/CodeExample.vue.js +1 -1
  4. package/dist/code-example/components/CodeExample.vue.script.js +1 -1
  5. package/dist/code-example/components/CodeExample.vue.script.js.map +1 -1
  6. package/dist/code-example/components/ExamplePicker.vue.script.js +2 -2
  7. package/dist/code-example/components/ExamplePicker.vue.script.js.map +1 -1
  8. package/dist/code-example/components/HttpMethod.vue.script.js +1 -1
  9. package/dist/code-example/components/HttpMethod.vue.script.js.map +1 -1
  10. package/dist/code-example/helpers/filter-clients-by-query.js.map +1 -1
  11. package/dist/code-example/helpers/find-client.js.map +1 -1
  12. package/dist/code-example/helpers/format-language.js.map +1 -1
  13. package/dist/code-example/helpers/generate-client-options.js.map +1 -1
  14. package/dist/code-example/helpers/generate-code-snippet.js.map +1 -1
  15. package/dist/code-example/helpers/get-clients.js.map +1 -1
  16. package/dist/code-example/helpers/get-custom-code-samples.js.map +1 -1
  17. package/dist/code-example/helpers/get-secrets.js.map +1 -1
  18. package/dist/code-example/helpers/get-snippet.js.map +1 -1
  19. package/dist/code-example/helpers/operation-to-har/operation-to-har.js.map +1 -1
  20. package/dist/code-example/helpers/operation-to-har/process-body.js.map +1 -1
  21. package/dist/code-example/helpers/operation-to-har/process-parameters.js +1 -1
  22. package/dist/code-example/helpers/operation-to-har/process-parameters.js.map +1 -1
  23. package/dist/code-example/helpers/operation-to-har/process-security-schemes.js.map +1 -1
  24. package/dist/code-example/helpers/operation-to-har/process-server-url.js.map +1 -1
  25. package/dist/code-example/mount.js.map +1 -1
  26. package/dist/constants.js +1 -1
  27. package/dist/style.css +66 -35
  28. package/package.json +15 -15
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @scalar/blocks
2
2
 
3
+ ## 0.1.11
4
+
5
+ ## 0.1.10
6
+
3
7
  ## 0.1.9
4
8
 
5
9
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"CodeExample.vue.d.ts","sourceRoot":"","sources":["../../../src/code-example/components/CodeExample.vue"],"names":[],"mappings":"AAukBA,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,mCAAmC,CAAA;AAErF,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAEvE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAA;AACzF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qEAAqE,CAAA;AACxG,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACb,MAAM,8DAA8D,CAAA;AAkBrE,OAAO,KAAK,EAEV,iBAAiB,EAElB,MAAM,UAAU,CAAA;AAKjB,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;OAGG;IACH,WAAW,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAA;IACpC;;OAEG;IACH,aAAa,EAAE,iBAAiB,EAAE,CAAA;IAClC;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;OAEG;IACH,cAAc,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;IACpC;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAA;IAC3B;;OAEG;IACH,eAAe,EAAE,0BAA0B,EAAE,CAAA;IAC7C;;OAEG;IACH,MAAM,EAAE,cAAc,CAAA;IACtB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,SAAS,EAAE,eAAe,CAAA;IAC1B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,MAAM,CAAA;IAC5B;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;OAEG;IACH,aAAa,CAAC,EAAE,aAAa,EAAE,CAAA;IAC/B;;;OAGG;IACH,+BAA+B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACzD,CAAA;AAED;;;;;;;;GAQG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;;;;;YAkCR,MAAM,OAAO;YACb,CAAC,EAAE,WAAW,EAAE,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO;EAsmB3D,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"CodeExample.vue.d.ts","sourceRoot":"","sources":["../../../src/code-example/components/CodeExample.vue"],"names":[],"mappings":"AAukBA,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,mCAAmC,CAAA;AAErF,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAEvE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAA;AACzF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qEAAqE,CAAA;AACxG,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACb,MAAM,8DAA8D,CAAA;AAkBrE,OAAO,KAAK,EAEV,iBAAiB,EAElB,MAAM,UAAU,CAAA;AAKjB,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;OAGG;IACH,WAAW,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAA;IACpC;;OAEG;IACH,aAAa,EAAE,iBAAiB,EAAE,CAAA;IAClC;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;OAEG;IACH,cAAc,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;IACpC;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAA;IAC3B;;OAEG;IACH,eAAe,EAAE,0BAA0B,EAAE,CAAA;IAC7C;;OAEG;IACH,MAAM,EAAE,cAAc,CAAA;IACtB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,SAAS,EAAE,eAAe,CAAA;IAC1B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,MAAM,CAAA;IAC5B;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;OAEG;IACH,aAAa,CAAC,EAAE,aAAa,EAAE,CAAA;IAC/B;;;OAGG;IACH,+BAA+B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACzD,CAAA;AAED;;;;;;;;GAQG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;;;;;YAkCR,MAAM,OAAO;YACb,CAAC,EAAE,WAAW,EAAE,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO;EAwmB3D,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -2,7 +2,7 @@ import e from "./CodeExample.vue.script.js";
2
2
  /* empty css */
3
3
  import t from "../../_virtual/_plugin-vue_export-helper.js";
4
4
  //#region src/code-example/components/CodeExample.vue
5
- var n = /* @__PURE__ */ t(e, [["__scopeId", "data-v-e8761738"]]);
5
+ var n = /*#__PURE__*/ t(e, [["__scopeId", "data-v-e8761738"]]);
6
6
  //#endregion
7
7
  export { n as default };
8
8
 
@@ -24,7 +24,7 @@ var I = ["innerHTML"], L = {
24
24
  }, R = ["id"], z = {
25
25
  key: 0,
26
26
  class: "request-card-footer-addon"
27
- }, B = { class: "request-header" }, V = /* @__PURE__ */ _({
27
+ }, B = { class: "request-header" }, V = /*@__PURE__*/ _({
28
28
  __name: "CodeExample",
29
29
  props: {
30
30
  integration: {},
@@ -1 +1 @@
1
- {"version":3,"file":"CodeExample.vue.script.js","names":["$slots"],"sources":["../../../src/code-example/components/CodeExample.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type CodeExampleProps = {\n /**\n * Integration type: determines if the code sample is displayed in a client environment\n * or in an API reference environment.\n */\n integration?: 'client' | 'reference'\n /**\n * List of all http clients formatted into option groups for the client selector\n */\n clientOptions: ClientOptionGroup[]\n /**\n * Pre-selected client, this will determine which client is initially selected in the dropdown.\n * Either a built-in client id (e.g. `js/fetch`) or a custom sample id (e.g. `custom/python`).\n *\n * Typed as a plain string: unioning the (large) client-id union with the `custom/...`\n * ids overflows TypeScript's union-complexity limit inside this component's `defineProps`.\n *\n * @defaults to a custom sample if one is available, otherwise shell/curl\n */\n selectedClient?: string\n /**\n * Which server from the spec to use for the code example\n */\n selectedServer?: ServerObject | null\n /**\n * The selected content type from the requestBody.content, this will determine which examples are available\n * as well as the content type of the code example\n *\n * @defaults to the first content type if not provided\n */\n selectedContentType?: string\n /**\n * Example name to use for resolving example values for parameters AND requestBody.\n *\n * This is the document-wide selection: it is honored only when this operation defines an example\n * with the same key, so picking an example on one operation syncs the rest without blanking out\n * operations that do not share that key.\n *\n * @example \"limited\"\n * ```ts\n * parameters: {\n * name: 'foobar',\n * in: 'query',\n * examples: {\n * limited: {\n * dataValue: 10,\n * }\n * }\n * },\n * body: {\n * content: {\n * 'application/json': {\n * examples: {\n * limited: {\n * dataValue: { foo: 'bar' },\n * }\n * }\n * }\n * }\n * }\n *\n * ```\n */\n selectedExample?: string\n /**\n * Event bus\n */\n eventBus: WorkspaceEventBus\n /**\n * The security schemes which are applicable to this operation\n */\n securitySchemes: SecuritySchemeObjectSecret[]\n /**\n * HTTP method of the operation\n */\n method: HttpMethodType\n /**\n * Path of the operation\n */\n path: string\n /**\n * De-referenced OpenAPI Operation object\n */\n operation: OperationObject\n /**\n * If true and there's no example, we will display a small card with the method and path only\n */\n fallback?: boolean\n /**\n * A method to generate the label of the block, should return an html string\n */\n generateLabel?: () => string\n /**\n * If true, render this as a webhook request example\n */\n isWebhook?: boolean\n /**\n * Workspace + document cookies\n */\n globalCookies?: XScalarCookie[]\n /**\n * When the request body schema uses oneOf/anyOf, use these selected variants\n * for the example snippet (e.g. from the schema dropdowns in the API reference).\n */\n requestBodyCompositionSelection?: Record<string, number>\n}\n\n/**\n * Request Example\n *\n * The core component for rendering a request example block,\n * this component does not have much of its own state but operates on props and custom events\n *\n * @event workspace:update:selected-client - Emitted when the selected client changes\n * @event workspace:update:selected-example - Emitted when the selected example changes, so other operations can sync\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport {\n ScalarCard,\n ScalarCardFooter,\n ScalarCardHeader,\n ScalarCardSection,\n} from '@scalar/components/card'\nimport { ScalarCodeBlock } from '@scalar/components/code-block'\nimport { ScalarCombobox } from '@scalar/components/combobox'\nimport { ScalarVirtualText } from '@scalar/components/virtual-text'\nimport { freezeElement } from '@scalar/helpers/dom/freeze-element'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OperationObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport {\n computed,\n onBeforeMount,\n ref,\n useId,\n watch,\n watchEffect,\n type ComponentPublicInstance,\n} from 'vue'\n\nimport { filterClientsByQuery } from '../helpers/filter-clients-by-query'\nimport { findClient } from '../helpers/find-client'\nimport { generateCodeSnippet } from '../helpers/generate-code-snippet'\nimport { getClients } from '../helpers/get-clients'\nimport { getCustomCodeSamples } from '../helpers/get-custom-code-samples'\nimport { getSecrets } from '../helpers/get-secrets'\nimport { operationToHar } from '../helpers/operation-to-har/operation-to-har'\nimport type {\n ClientOption,\n ClientOptionGroup,\n CustomClientOption,\n} from '../types'\nimport ExamplePicker from './ExamplePicker.vue'\nimport HttpMethod from './HttpMethod.vue'\n\nconst {\n integration,\n clientOptions,\n selectedClient,\n selectedServer = null,\n selectedContentType,\n selectedExample,\n securitySchemes = [],\n method,\n eventBus,\n path,\n operation,\n isWebhook,\n generateLabel,\n globalCookies,\n requestBodyCompositionSelection,\n} = defineProps<CodeExampleProps>()\n\nconst emit = defineEmits<{\n /**\n * Emitted whenever the example key actually shown for this operation changes.\n *\n * This is the resolved local key (not the raw document-wide selection), so layouts that render\n * the test-request button outside this component can open the client with the same example the\n * snippet displays.\n */\n (e: 'update:exampleKey', value: string): void\n}>()\n\ndefineSlots<{\n header: () => unknown\n footer: ({ exampleName }: { exampleName: string }) => unknown\n}>()\n\n/** Grab the examples for the given content type */\nconst requestBodyExamples = computed(() => {\n const content = getResolvedRef(operation.requestBody)?.content ?? {}\n const contentType = selectedContentType || Object.keys(content)[0]\n if (!contentType) return {}\n\n const examples = content[contentType]?.examples ?? {}\n\n return examples\n})\n\n/**\n * The example key actually shown for this operation.\n *\n * `selectedExample` is the document-wide selection that syncs across operations. We honor it only\n * when this operation actually defines that key, otherwise we keep the local example: a selection\n * on one operation should never blank out an operation that does not share the same example.\n */\nconst localExampleKey = ref('')\n\n/** Resolve the key to display, preferring the document-wide selection when this operation has it */\nconst resolveExampleKey = (preferred: string | undefined): string => {\n const keys = Object.keys(requestBodyExamples.value)\n if (preferred && keys.includes(preferred)) {\n return preferred\n }\n // Keep the current local example when it is still valid, otherwise fall back to the first one\n if (localExampleKey.value && keys.includes(localExampleKey.value)) {\n return localExampleKey.value\n }\n return keys[0] ?? ''\n}\n\n// Set the initial example from the document-wide selection, falling back to the first example\nonBeforeMount(() => {\n localExampleKey.value = resolveExampleKey(selectedExample)\n})\n\n// Follow the document-wide selection when it changes and this operation has that example\nwatch(\n () => selectedExample,\n (preferred) => {\n localExampleKey.value = resolveExampleKey(preferred)\n },\n)\n\n/** Reset the selected example key if the content type changes and the new content type doesn't have the previously selected example */\nwatch(\n () => selectedContentType,\n () => {\n if (\n !Object.keys(requestBodyExamples.value).includes(localExampleKey.value)\n ) {\n // Re-resolve so the new content type still follows the document-wide selection when it has\n // that key, instead of always snapping back to the first example\n localExampleKey.value = resolveExampleKey(selectedExample)\n }\n },\n)\n\n// Keep the parent informed of the resolved key so a test-request button rendered outside this\n// component (e.g. the classic layout header) opens the client with the example the snippet shows\nwatchEffect(() => {\n emit('update:exampleKey', localExampleKey.value)\n})\n\n/** Select an example locally and sync the choice across the document */\nconst selectExample = (key: string) => {\n localExampleKey.value = key\n eventBus.emit('workspace:update:selected-example', key)\n}\n\n/** Grab any custom code samples from the operation */\nconst customCodeSamples = computed(() => getCustomCodeSamples(operation))\n\n/** Merge custom code samples with the client options */\nconst clients = computed(() =>\n getClients(\n customCodeSamples.value.samples,\n clientOptions,\n customCodeSamples.value.label,\n ),\n)\n\n/** Total number of available clients across all option groups */\nconst clientCount = computed(() =>\n clients.value.reduce((total, group) => total + group.options.length, 0),\n)\n\n/** The locally selected client which would include code samples from this operation only */\nconst localSelectedClient = ref<ClientOption | CustomClientOption | undefined>(\n findClient(clients.value, selectedClient),\n)\n\n/**\n * Re-resolve the local client whenever the global selection or the available\n * clients change. Watching `clients` matters when navigating between operations:\n * the stored id stays the same, but the matching option (e.g. a custom sample)\n * differs per operation, so without this the snippet could go stale.\n */\nwatch([() => selectedClient, clients], ([newClient]) => {\n const client = findClient(clients.value, newClient)\n if (client) {\n localSelectedClient.value = client\n }\n})\n\n/** Generate HAR data for webhook requests */\nconst webhookHar = computed(() => {\n if (!isWebhook) return null\n\n try {\n return operationToHar({\n operation,\n method,\n path,\n example: localExampleKey.value,\n requestBodyCompositionSelection,\n // Only required parameters are shown in code examples; optional parameters\n // are omitted unless explicitly enabled via `x-disabled: false`.\n defaultDisabledParameters: true,\n })\n } catch (error) {\n console.error('[webhookHar]', error)\n return null\n }\n})\n\n/** Generate the code snippet for the selected example */\nconst generatedCode = computed<string>(() => {\n if (isWebhook) {\n return webhookHar.value?.postData?.text ?? ''\n }\n\n return generateCodeSnippet({\n // Only required parameters are shown in code examples; optional parameters\n // are omitted unless explicitly enabled via `x-disabled: false`.\n defaultDisabledParameters: true,\n includeDefaultHeaders: integration === 'client',\n clientId: localSelectedClient.value?.id,\n customCodeSamples: customCodeSamples.value.samples,\n operation,\n method,\n path,\n contentType: selectedContentType,\n server: selectedServer,\n securitySchemes,\n example: localExampleKey.value,\n globalCookies,\n requestBodyCompositionSelection,\n })\n})\n\n/** The language for the code block, used for syntax highlighting */\nconst codeBlockLanguage = computed(() => {\n if (isWebhook) {\n return webhookLanguage.value\n }\n\n return localSelectedClient.value?.lang\n})\n\n/** Determine the language for webhook content based on MIME type */\nconst webhookLanguage = computed<string>(() => {\n if (!webhookHar.value?.postData) return 'json'\n\n const contentType = webhookHar.value.postData.mimeType\n if (contentType?.includes('json')) return 'json'\n if (contentType?.includes('xml')) return 'xml'\n if (contentType?.includes('yaml') || contentType?.includes('yml'))\n return 'yaml'\n if (contentType?.includes('text/plain')) return 'text'\n\n return 'json'\n})\n\n/** Block secrets from being shown in the code block */\nconst secretCredentials = computed(() => getSecrets(securitySchemes))\n\n/** Grab the ref to freeze the ui as the clients change so there's no jump as the size of the dom changes */\nconst elem = ref<ComponentPublicInstance | null>(null)\n\n/** Set custom example, or update the selected HTTP client globally */\nconst selectClient = (option: ClientOption) => {\n // We need to freeze the ui to prevent scrolling as the clients change\n if (elem.value) {\n const unfreeze = freezeElement(elem.value.$el)\n setTimeout(() => {\n unfreeze()\n }, 300)\n }\n // Update to the local example\n localSelectedClient.value = option\n\n // Sync the selection globally so other operations follow along. Custom samples\n // sync too (keyed by language), so picking e.g. the Python SDK example here\n // shows the Python example on every operation that ships one.\n if (option) {\n eventBus.emit('workspace:update:selected-client', option.id)\n }\n}\n\n// Virtualize the code block if it's too large\n// This prevents the entire app from freezing up if there's a massive example\n// We set a lower threshold here as code examples can get quite large\nconst VIRTUALIZATION_THRESHOLD = 20_000\n\nconst shouldVirtualize = computed(\n () => (generatedCode.value.length ?? 0) > VIRTUALIZATION_THRESHOLD,\n)\n\nconst id = useId()\n</script>\n<template>\n <ScalarCard\n v-if=\"generatedCode\"\n ref=\"elem\"\n class=\"request-card dark-mode\">\n <!-- Header -->\n <ScalarCardHeader class=\"pr-2.5\">\n <span class=\"sr-only\">Request Example for</span>\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <span\n v-if=\"generateLabel\"\n v-html=\"generateLabel()\" />\n <slot name=\"header\" />\n <!-- Client picker -->\n <template\n v-if=\"!isWebhook && clientCount\"\n #actions>\n <!-- Multiple clients: render a dropdown to switch between them -->\n <ScalarCombobox\n v-if=\"clientCount > 1\"\n class=\"max-h-80\"\n :filterFn=\"filterClientsByQuery\"\n :modelValue=\"localSelectedClient\"\n :options=\"clients\"\n placement=\"bottom-end\"\n teleport\n @update:modelValue=\"selectClient($event as ClientOption)\">\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\"\n variant=\"ghost\">\n {{ localSelectedClient?.title }}\n <ScalarIconCaretDown\n class=\"ui-open:rotate-180 mt-px size-3 transition-transform duration-100\"\n weight=\"bold\" />\n </ScalarButton>\n </ScalarCombobox>\n <!-- Single client: just show its label, no need for a dropdown -->\n <span\n v-else\n class=\"text-c-2 flex h-full w-fit items-center px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\">\n {{ localSelectedClient?.title }}\n </span>\n </template>\n </ScalarCardHeader>\n\n <!-- Code snippet -->\n <ScalarCardSection class=\"request-editor-section custom-scroll p-0\">\n <div\n :id=\"`${id}-example`\"\n class=\"code-snippet\">\n <ScalarCodeBlock\n v-if=\"!shouldVirtualize\"\n class=\"bg-b-2 h-full\"\n :content=\"generatedCode\"\n :hideCredentials=\"secretCredentials\"\n :lang=\"codeBlockLanguage\"\n lineNumbers />\n <ScalarVirtualText\n v-else\n containerClass=\"custom-scroll scalar-code-block border rounded-b flex flex-1 max-h-screen\"\n contentClass=\"language-plaintext whitespace-pre font-code text-base p-2\"\n :lineHeight=\"20\"\n :text=\"generatedCode\" />\n </div>\n </ScalarCardSection>\n\n <!-- Footer -->\n <ScalarCardFooter\n v-if=\"Object.keys(requestBodyExamples).length > 1 || $slots.footer\"\n class=\"request-card-footer bg-b-3\">\n <!-- Example picker -->\n <div\n v-if=\"Object.keys(requestBodyExamples).length > 1\"\n class=\"request-card-footer-addon\">\n <template v-if=\"Object.keys(requestBodyExamples).length\">\n <ExamplePicker\n :examples=\"requestBodyExamples\"\n :modelValue=\"localExampleKey\"\n @update:modelValue=\"selectExample\" />\n </template>\n </div>\n\n <!-- Footer -->\n <slot\n :exampleName=\"localExampleKey\"\n name=\"footer\" />\n </ScalarCardFooter>\n </ScalarCard>\n\n <!-- Fallback card with just method and path in the case of no examples -->\n <ScalarCard\n v-else-if=\"fallback\"\n class=\"request-card dark-mode\">\n <ScalarCardSection class=\"request-card-simple\">\n <div class=\"request-header\">\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <slot name=\"header\" />\n </div>\n <slot\n :exampleName=\"localExampleKey\"\n name=\"footer\" />\n </ScalarCardSection>\n </ScalarCard>\n</template>\n<style scoped>\n.request-card {\n color: var(--scalar-color-1);\n font-size: var(--scalar-font-size-3);\n}\n.request-method {\n font-family: var(--scalar-font-code);\n text-transform: uppercase;\n margin-right: 6px;\n}\n.request-card-footer {\n display: flex;\n justify-content: flex-end;\n padding: 6px;\n flex-shrink: 0;\n position: relative;\n}\n.request-card-footer-addon {\n display: flex;\n align-items: center;\n\n flex: 1;\n min-width: 0;\n}\n.request-editor-section {\n display: flex;\n flex: 1;\n}\n.request-card-simple {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding: 8px 8px 8px 12px;\n\n font-size: var(--scalar-small);\n}\n.code-snippet {\n display: flex;\n flex-direction: column;\n width: 100%;\n}\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"CodeExample.vue.script.js","names":["$slots"],"sources":["../../../src/code-example/components/CodeExample.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type CodeExampleProps = {\n /**\n * Integration type: determines if the code sample is displayed in a client environment\n * or in an API reference environment.\n */\n integration?: 'client' | 'reference'\n /**\n * List of all http clients formatted into option groups for the client selector\n */\n clientOptions: ClientOptionGroup[]\n /**\n * Pre-selected client, this will determine which client is initially selected in the dropdown.\n * Either a built-in client id (e.g. `js/fetch`) or a custom sample id (e.g. `custom/python`).\n *\n * Typed as a plain string: unioning the (large) client-id union with the `custom/...`\n * ids overflows TypeScript's union-complexity limit inside this component's `defineProps`.\n *\n * @defaults to a custom sample if one is available, otherwise shell/curl\n */\n selectedClient?: string\n /**\n * Which server from the spec to use for the code example\n */\n selectedServer?: ServerObject | null\n /**\n * The selected content type from the requestBody.content, this will determine which examples are available\n * as well as the content type of the code example\n *\n * @defaults to the first content type if not provided\n */\n selectedContentType?: string\n /**\n * Example name to use for resolving example values for parameters AND requestBody.\n *\n * This is the document-wide selection: it is honored only when this operation defines an example\n * with the same key, so picking an example on one operation syncs the rest without blanking out\n * operations that do not share that key.\n *\n * @example \"limited\"\n * ```ts\n * parameters: {\n * name: 'foobar',\n * in: 'query',\n * examples: {\n * limited: {\n * dataValue: 10,\n * }\n * }\n * },\n * body: {\n * content: {\n * 'application/json': {\n * examples: {\n * limited: {\n * dataValue: { foo: 'bar' },\n * }\n * }\n * }\n * }\n * }\n *\n * ```\n */\n selectedExample?: string\n /**\n * Event bus\n */\n eventBus: WorkspaceEventBus\n /**\n * The security schemes which are applicable to this operation\n */\n securitySchemes: SecuritySchemeObjectSecret[]\n /**\n * HTTP method of the operation\n */\n method: HttpMethodType\n /**\n * Path of the operation\n */\n path: string\n /**\n * De-referenced OpenAPI Operation object\n */\n operation: OperationObject\n /**\n * If true and there's no example, we will display a small card with the method and path only\n */\n fallback?: boolean\n /**\n * A method to generate the label of the block, should return an html string\n */\n generateLabel?: () => string\n /**\n * If true, render this as a webhook request example\n */\n isWebhook?: boolean\n /**\n * Workspace + document cookies\n */\n globalCookies?: XScalarCookie[]\n /**\n * When the request body schema uses oneOf/anyOf, use these selected variants\n * for the example snippet (e.g. from the schema dropdowns in the API reference).\n */\n requestBodyCompositionSelection?: Record<string, number>\n}\n\n/**\n * Request Example\n *\n * The core component for rendering a request example block,\n * this component does not have much of its own state but operates on props and custom events\n *\n * @event workspace:update:selected-client - Emitted when the selected client changes\n * @event workspace:update:selected-example - Emitted when the selected example changes, so other operations can sync\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport {\n ScalarCard,\n ScalarCardFooter,\n ScalarCardHeader,\n ScalarCardSection,\n} from '@scalar/components/card'\nimport { ScalarCodeBlock } from '@scalar/components/code-block'\nimport { ScalarCombobox } from '@scalar/components/combobox'\nimport { ScalarVirtualText } from '@scalar/components/virtual-text'\nimport { freezeElement } from '@scalar/helpers/dom/freeze-element'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OperationObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport {\n computed,\n onBeforeMount,\n ref,\n useId,\n watch,\n watchEffect,\n type ComponentPublicInstance,\n} from 'vue'\n\nimport { filterClientsByQuery } from '../helpers/filter-clients-by-query'\nimport { findClient } from '../helpers/find-client'\nimport { generateCodeSnippet } from '../helpers/generate-code-snippet'\nimport { getClients } from '../helpers/get-clients'\nimport { getCustomCodeSamples } from '../helpers/get-custom-code-samples'\nimport { getSecrets } from '../helpers/get-secrets'\nimport { operationToHar } from '../helpers/operation-to-har/operation-to-har'\nimport type {\n ClientOption,\n ClientOptionGroup,\n CustomClientOption,\n} from '../types'\nimport ExamplePicker from './ExamplePicker.vue'\nimport HttpMethod from './HttpMethod.vue'\n\nconst {\n integration,\n clientOptions,\n selectedClient,\n selectedServer = null,\n selectedContentType,\n selectedExample,\n securitySchemes = [],\n method,\n eventBus,\n path,\n operation,\n isWebhook,\n generateLabel,\n globalCookies,\n requestBodyCompositionSelection,\n} = defineProps<CodeExampleProps>()\n\nconst emit = defineEmits<{\n /**\n * Emitted whenever the example key actually shown for this operation changes.\n *\n * This is the resolved local key (not the raw document-wide selection), so layouts that render\n * the test-request button outside this component can open the client with the same example the\n * snippet displays.\n */\n (e: 'update:exampleKey', value: string): void\n}>()\n\ndefineSlots<{\n header: () => unknown\n footer: ({ exampleName }: { exampleName: string }) => unknown\n}>()\n\n/** Grab the examples for the given content type */\nconst requestBodyExamples = computed(() => {\n const content = getResolvedRef(operation.requestBody)?.content ?? {}\n const contentType = selectedContentType || Object.keys(content)[0]\n if (!contentType) return {}\n\n const examples = content[contentType]?.examples ?? {}\n\n return examples\n})\n\n/**\n * The example key actually shown for this operation.\n *\n * `selectedExample` is the document-wide selection that syncs across operations. We honor it only\n * when this operation actually defines that key, otherwise we keep the local example: a selection\n * on one operation should never blank out an operation that does not share the same example.\n */\nconst localExampleKey = ref('')\n\n/** Resolve the key to display, preferring the document-wide selection when this operation has it */\nconst resolveExampleKey = (preferred: string | undefined): string => {\n const keys = Object.keys(requestBodyExamples.value)\n if (preferred && keys.includes(preferred)) {\n return preferred\n }\n // Keep the current local example when it is still valid, otherwise fall back to the first one\n if (localExampleKey.value && keys.includes(localExampleKey.value)) {\n return localExampleKey.value\n }\n return keys[0] ?? ''\n}\n\n// Set the initial example from the document-wide selection, falling back to the first example\nonBeforeMount(() => {\n localExampleKey.value = resolveExampleKey(selectedExample)\n})\n\n// Follow the document-wide selection when it changes and this operation has that example\nwatch(\n () => selectedExample,\n (preferred) => {\n localExampleKey.value = resolveExampleKey(preferred)\n },\n)\n\n/** Reset the selected example key if the content type changes and the new content type doesn't have the previously selected example */\nwatch(\n () => selectedContentType,\n () => {\n if (\n !Object.keys(requestBodyExamples.value).includes(localExampleKey.value)\n ) {\n // Re-resolve so the new content type still follows the document-wide selection when it has\n // that key, instead of always snapping back to the first example\n localExampleKey.value = resolveExampleKey(selectedExample)\n }\n },\n)\n\n// Keep the parent informed of the resolved key so a test-request button rendered outside this\n// component (e.g. the classic layout header) opens the client with the example the snippet shows\nwatchEffect(() => {\n emit('update:exampleKey', localExampleKey.value)\n})\n\n/** Select an example locally and sync the choice across the document */\nconst selectExample = (key: string) => {\n localExampleKey.value = key\n eventBus.emit('workspace:update:selected-example', key)\n}\n\n/** Grab any custom code samples from the operation */\nconst customCodeSamples = computed(() => getCustomCodeSamples(operation))\n\n/** Merge custom code samples with the client options */\nconst clients = computed(() =>\n getClients(\n customCodeSamples.value.samples,\n clientOptions,\n customCodeSamples.value.label,\n ),\n)\n\n/** Total number of available clients across all option groups */\nconst clientCount = computed(() =>\n clients.value.reduce((total, group) => total + group.options.length, 0),\n)\n\n/** The locally selected client which would include code samples from this operation only */\nconst localSelectedClient = ref<ClientOption | CustomClientOption | undefined>(\n findClient(clients.value, selectedClient),\n)\n\n/**\n * Re-resolve the local client whenever the global selection or the available\n * clients change. Watching `clients` matters when navigating between operations:\n * the stored id stays the same, but the matching option (e.g. a custom sample)\n * differs per operation, so without this the snippet could go stale.\n */\nwatch([() => selectedClient, clients], ([newClient]) => {\n const client = findClient(clients.value, newClient)\n if (client) {\n localSelectedClient.value = client\n }\n})\n\n/** Generate HAR data for webhook requests */\nconst webhookHar = computed(() => {\n if (!isWebhook) return null\n\n try {\n return operationToHar({\n operation,\n method,\n path,\n example: localExampleKey.value,\n requestBodyCompositionSelection,\n // Only required parameters are shown in code examples; optional parameters\n // are omitted unless explicitly enabled via `x-disabled: false`.\n defaultDisabledParameters: true,\n })\n } catch (error) {\n console.error('[webhookHar]', error)\n return null\n }\n})\n\n/** Generate the code snippet for the selected example */\nconst generatedCode = computed<string>(() => {\n if (isWebhook) {\n return webhookHar.value?.postData?.text ?? ''\n }\n\n return generateCodeSnippet({\n // Only required parameters are shown in code examples; optional parameters\n // are omitted unless explicitly enabled via `x-disabled: false`.\n defaultDisabledParameters: true,\n includeDefaultHeaders: integration === 'client',\n clientId: localSelectedClient.value?.id,\n customCodeSamples: customCodeSamples.value.samples,\n operation,\n method,\n path,\n contentType: selectedContentType,\n server: selectedServer,\n securitySchemes,\n example: localExampleKey.value,\n globalCookies,\n requestBodyCompositionSelection,\n })\n})\n\n/** The language for the code block, used for syntax highlighting */\nconst codeBlockLanguage = computed(() => {\n if (isWebhook) {\n return webhookLanguage.value\n }\n\n return localSelectedClient.value?.lang\n})\n\n/** Determine the language for webhook content based on MIME type */\nconst webhookLanguage = computed<string>(() => {\n if (!webhookHar.value?.postData) return 'json'\n\n const contentType = webhookHar.value.postData.mimeType\n if (contentType?.includes('json')) return 'json'\n if (contentType?.includes('xml')) return 'xml'\n if (contentType?.includes('yaml') || contentType?.includes('yml'))\n return 'yaml'\n if (contentType?.includes('text/plain')) return 'text'\n\n return 'json'\n})\n\n/** Block secrets from being shown in the code block */\nconst secretCredentials = computed(() => getSecrets(securitySchemes))\n\n/** Grab the ref to freeze the ui as the clients change so there's no jump as the size of the dom changes */\nconst elem = ref<ComponentPublicInstance | null>(null)\n\n/** Set custom example, or update the selected HTTP client globally */\nconst selectClient = (option: ClientOption) => {\n // We need to freeze the ui to prevent scrolling as the clients change\n if (elem.value) {\n const unfreeze = freezeElement(elem.value.$el)\n setTimeout(() => {\n unfreeze()\n }, 300)\n }\n // Update to the local example\n localSelectedClient.value = option\n\n // Sync the selection globally so other operations follow along. Custom samples\n // sync too (keyed by language), so picking e.g. the Python SDK example here\n // shows the Python example on every operation that ships one.\n if (option) {\n eventBus.emit('workspace:update:selected-client', option.id)\n }\n}\n\n// Virtualize the code block if it's too large\n// This prevents the entire app from freezing up if there's a massive example\n// We set a lower threshold here as code examples can get quite large\nconst VIRTUALIZATION_THRESHOLD = 20_000\n\nconst shouldVirtualize = computed(\n () => (generatedCode.value.length ?? 0) > VIRTUALIZATION_THRESHOLD,\n)\n\nconst id = useId()\n</script>\n<template>\n <ScalarCard\n v-if=\"generatedCode\"\n ref=\"elem\"\n class=\"request-card dark-mode\">\n <!-- Header -->\n <ScalarCardHeader class=\"pr-2.5\">\n <span class=\"sr-only\">Request Example for</span>\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <span\n v-if=\"generateLabel\"\n v-html=\"generateLabel()\" />\n <slot name=\"header\" />\n <!-- Client picker -->\n <template\n v-if=\"!isWebhook && clientCount\"\n #actions>\n <!-- Multiple clients: render a dropdown to switch between them -->\n <ScalarCombobox\n v-if=\"clientCount > 1\"\n class=\"max-h-80\"\n :filterFn=\"filterClientsByQuery\"\n :modelValue=\"localSelectedClient\"\n :options=\"clients\"\n placement=\"bottom-end\"\n teleport\n @update:modelValue=\"selectClient($event as ClientOption)\">\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\"\n variant=\"ghost\">\n {{ localSelectedClient?.title }}\n <ScalarIconCaretDown\n class=\"ui-open:rotate-180 mt-px size-3 transition-transform duration-100\"\n weight=\"bold\" />\n </ScalarButton>\n </ScalarCombobox>\n <!-- Single client: just show its label, no need for a dropdown -->\n <span\n v-else\n class=\"text-c-2 flex h-full w-fit items-center px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\">\n {{ localSelectedClient?.title }}\n </span>\n </template>\n </ScalarCardHeader>\n\n <!-- Code snippet -->\n <ScalarCardSection class=\"request-editor-section custom-scroll p-0\">\n <div\n :id=\"`${id}-example`\"\n class=\"code-snippet\">\n <ScalarCodeBlock\n v-if=\"!shouldVirtualize\"\n class=\"bg-b-2 h-full\"\n :content=\"generatedCode\"\n :hideCredentials=\"secretCredentials\"\n :lang=\"codeBlockLanguage\"\n lineNumbers />\n <ScalarVirtualText\n v-else\n containerClass=\"custom-scroll scalar-code-block border rounded-b flex flex-1 max-h-screen\"\n contentClass=\"language-plaintext whitespace-pre font-code text-base p-2\"\n :lineHeight=\"20\"\n :text=\"generatedCode\" />\n </div>\n </ScalarCardSection>\n\n <!-- Footer -->\n <ScalarCardFooter\n v-if=\"Object.keys(requestBodyExamples).length > 1 || $slots.footer\"\n class=\"request-card-footer bg-b-3\">\n <!-- Example picker -->\n <div\n v-if=\"Object.keys(requestBodyExamples).length > 1\"\n class=\"request-card-footer-addon\">\n <template v-if=\"Object.keys(requestBodyExamples).length\">\n <ExamplePicker\n :examples=\"requestBodyExamples\"\n :modelValue=\"localExampleKey\"\n @update:modelValue=\"selectExample\" />\n </template>\n </div>\n\n <!-- Footer -->\n <slot\n :exampleName=\"localExampleKey\"\n name=\"footer\" />\n </ScalarCardFooter>\n </ScalarCard>\n\n <!-- Fallback card with just method and path in the case of no examples -->\n <ScalarCard\n v-else-if=\"fallback\"\n class=\"request-card dark-mode\">\n <ScalarCardSection class=\"request-card-simple\">\n <div class=\"request-header\">\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <slot name=\"header\" />\n </div>\n <slot\n :exampleName=\"localExampleKey\"\n name=\"footer\" />\n </ScalarCardSection>\n </ScalarCard>\n</template>\n<style scoped>\n.request-card {\n color: var(--scalar-color-1);\n font-size: var(--scalar-font-size-3);\n}\n.request-method {\n font-family: var(--scalar-font-code);\n text-transform: uppercase;\n margin-right: 6px;\n}\n.request-card-footer {\n display: flex;\n justify-content: flex-end;\n padding: 6px;\n flex-shrink: 0;\n position: relative;\n}\n.request-card-footer-addon {\n display: flex;\n align-items: center;\n\n flex: 1;\n min-width: 0;\n}\n.request-editor-section {\n display: flex;\n flex: 1;\n}\n.request-card-simple {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding: 8px 8px 8px 12px;\n\n font-size: var(--scalar-small);\n}\n.code-snippet {\n display: flex;\n flex-direction: column;\n width: 100%;\n}\n</style>\n"],"mappings":"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"}
@@ -3,10 +3,10 @@ import { ScalarButton as f } from "@scalar/components/button";
3
3
  import { ScalarIconCaretDown as p } from "@scalar/icons";
4
4
  import { ScalarListbox as m } from "@scalar/components/listbox";
5
5
  //#region src/code-example/components/ExamplePicker.vue?vue&type=script&setup=true&lang.ts
6
- var h = { class: "min-w-0 flex-1 truncate" }, g = /* @__PURE__ */ i({
6
+ var h = { class: "min-w-0 flex-1 truncate" }, g = /*@__PURE__*/ i({
7
7
  inheritAttrs: !1,
8
8
  __name: "ExamplePicker",
9
- props: /* @__PURE__ */ a({ examples: { default: () => ({}) } }, {
9
+ props: /*@__PURE__*/ a({ examples: { default: () => ({}) } }, {
10
10
  modelValue: { required: !0 },
11
11
  modelModifiers: {}
12
12
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"ExamplePicker.vue.script.js","names":["$attrs"],"sources":["../../../src/code-example/components/ExamplePicker.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport {\n ScalarListbox,\n type ScalarListboxOption,\n} from '@scalar/components/listbox'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport type { MediaTypeObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed } from 'vue'\n\nconst { examples = {} } = defineProps<{\n examples?: MediaTypeObject['examples'] | Record<string, string>\n}>()\n\nconst selectedExampleKey = defineModel<string>({\n required: true,\n})\n\ndefineOptions({ inheritAttrs: false })\n\nconst exampleOptions = computed<ScalarListboxOption[]>(() =>\n Object.entries(examples).map(([key, example]) => ({\n id: key,\n label: example?.summary ?? key,\n })),\n)\n\nconst selectedExample = computed<ScalarListboxOption | undefined>({\n get: () =>\n exampleOptions.value.find(({ id }) => id === selectedExampleKey.value),\n set: (v) => (selectedExampleKey.value = v?.id ?? ''),\n})\n</script>\n\n<template>\n <ScalarListbox\n v-model=\"selectedExample\"\n class=\"w-fit min-w-32\"\n :options=\"exampleOptions\"\n placement=\"bottom-start\"\n teleport>\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit min-w-0 gap-1.5 px-1.5 py-0.75 text-base font-normal\"\n data-testid=\"example-picker\"\n variant=\"ghost\"\n v-bind=\"$attrs\">\n <div class=\"min-w-0 flex-1 truncate\">\n {{ selectedExample?.label ?? 'Select an example' }}\n </div>\n <ScalarIconCaretDown\n class=\"ui-open:rotate-180 mt-0.25 size-3 transition-transform duration-100\"\n weight=\"bold\" />\n </ScalarButton>\n </ScalarListbox>\n</template>\n"],"mappings":";;;;;;;;;;;;;;EAcA,IAAM,IAAqB,EAAmB,GAAA,aAE7C,EAIK,IAAiB,QACrB,OAAO,QAAQ,EAAA,SAAS,CAAC,KAAK,CAAC,GAAK,QAAc;GAChD,IAAI;GACJ,OAAO,GAAS,WAAW;GAC5B,EAAE,CACL,EAEM,IAAkB,EAA0C;GAChE,WACE,EAAe,MAAM,MAAM,EAAE,YAAS,MAAO,EAAmB,MAAM;GACxE,MAAM,MAAO,EAAmB,QAAQ,GAAG,MAAM;GAClD,CAAA;yBAIC,EAkBgB,EAAA,EAAA,EAAA;eAjBL,EAAA;4CAAe,QAAA;GACxB,OAAM;GACL,SAAS,EAAA;GACV,WAAU;GACV,UAAA;;oBAYe,CAXf,EAWe,EAAA,EAAA,EAXf,EAWe;IAVb,OAAM;IACN,eAAY;IACZ,SAAQ;MACAA,EAAAA,OAAM,EAAA;qBAGR,CAFN,EAEM,OAFN,GAEM,EADD,EAAA,OAAiB,SAAK,oBAAA,EAAA,EAAA,EAE3B,EAEkB,EAAA,EAAA,EAAA;KADhB,OAAM;KACN,QAAO"}
1
+ {"version":3,"file":"ExamplePicker.vue.script.js","names":["$attrs"],"sources":["../../../src/code-example/components/ExamplePicker.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport {\n ScalarListbox,\n type ScalarListboxOption,\n} from '@scalar/components/listbox'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport type { MediaTypeObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed } from 'vue'\n\nconst { examples = {} } = defineProps<{\n examples?: MediaTypeObject['examples'] | Record<string, string>\n}>()\n\nconst selectedExampleKey = defineModel<string>({\n required: true,\n})\n\ndefineOptions({ inheritAttrs: false })\n\nconst exampleOptions = computed<ScalarListboxOption[]>(() =>\n Object.entries(examples).map(([key, example]) => ({\n id: key,\n label: example?.summary ?? key,\n })),\n)\n\nconst selectedExample = computed<ScalarListboxOption | undefined>({\n get: () =>\n exampleOptions.value.find(({ id }) => id === selectedExampleKey.value),\n set: (v) => (selectedExampleKey.value = v?.id ?? ''),\n})\n</script>\n\n<template>\n <ScalarListbox\n v-model=\"selectedExample\"\n class=\"w-fit min-w-32\"\n :options=\"exampleOptions\"\n placement=\"bottom-start\"\n teleport>\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit min-w-0 gap-1.5 px-1.5 py-0.75 text-base font-normal\"\n data-testid=\"example-picker\"\n variant=\"ghost\"\n v-bind=\"$attrs\">\n <div class=\"min-w-0 flex-1 truncate\">\n {{ selectedExample?.label ?? 'Select an example' }}\n </div>\n <ScalarIconCaretDown\n class=\"ui-open:rotate-180 mt-0.25 size-3 transition-transform duration-100\"\n weight=\"bold\" />\n </ScalarButton>\n </ScalarListbox>\n</template>\n"],"mappings":";;;;;;;;;;;;;;EAcA,IAAM,IAAqB,EAAmB,GAAA,YAE7C,GAIK,IAAiB,QACrB,OAAO,QAAQ,EAAA,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAK,QAAc;GAChD,IAAI;GACJ,OAAO,GAAS,WAAW;EAC7B,EAAE,CACJ,GAEM,IAAkB,EAA0C;GAChE,WACE,EAAe,MAAM,MAAM,EAAE,YAAS,MAAO,EAAmB,KAAK;GACvE,MAAM,MAAO,EAAmB,QAAQ,GAAG,MAAM;EACnD,CAAC;yBAIC,EAkBgB,EAAA,CAAA,GAAA;eAjBL,EAAA;4CAAe,QAAA;GACxB,OAAM;GACL,SAAS,EAAA;GACV,WAAU;GACV,UAAA;;oBAYe,CAXf,EAWe,EAAA,CAAA,GAXf,EAWe;IAVb,OAAM;IACN,eAAY;IACZ,SAAQ;MACAA,EAAAA,MAAM,GAAA;qBAGR,CAFN,EAEM,OAFN,GAEM,EADD,EAAA,OAAiB,SAAK,mBAAA,GAAA,CAAA,GAE3B,EAEkB,EAAA,CAAA,GAAA;KADhB,OAAM;KACN,QAAO"}
@@ -2,7 +2,7 @@ import { computed as e, createBlock as t, createTextVNode as n, defineComponent
2
2
  import { getHttpMethodInfo as u } from "@scalar/helpers/http/http-info";
3
3
  import { normalizeHttpMethod as d } from "@scalar/helpers/http/normalize-http-method";
4
4
  //#region src/code-example/components/HttpMethod.vue?vue&type=script&setup=true&lang.ts
5
- var f = /* @__PURE__ */ r({
5
+ var f = /*@__PURE__*/ r({
6
6
  __name: "HttpMethod",
7
7
  props: {
8
8
  as: {},
@@ -1 +1 @@
1
- {"version":3,"file":"HttpMethod.vue.script.js","names":[],"sources":["../../../src/code-example/components/HttpMethod.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { getHttpMethodInfo } from '@scalar/helpers/http/http-info'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { normalizeHttpMethod } from '@scalar/helpers/http/normalize-http-method'\nimport { computed, type Component } from 'vue'\n\nconst props = defineProps<{\n /** The type of element to render as, defaults to `span` */\n as?: Component | string\n /** The css style property or variable that will be set to the request method color, defaults to `color` */\n property?: string\n /** Whether or not to abbreviated the slot content */\n short?: boolean\n /** The HTTP method to show */\n method: HttpMethod | string\n}>()\n\n/** Grabs the method info object which contains abbreviation, color, and background color etc */\nconst httpMethodInfo = computed(() =>\n getHttpMethodInfo(String(props.method || '')),\n)\n\n/** Full method name */\nconst normalized = computed(() => normalizeHttpMethod(props.method))\n</script>\n\n<template>\n <component\n :is=\"as ?? 'span'\"\n class=\"uppercase\"\n :style=\"{ [property || 'color']: httpMethodInfo.colorVar }\">\n <slot />\n {{ short ? httpMethodInfo.short : normalized }}\n </component>\n</template>\n"],"mappings":";;;;;;;;;;;;;EAMA,IAAM,IAAQ,GAYR,IAAiB,QACrB,EAAkB,OAAO,EAAM,UAAU,GAAG,CAAC,CAC/C,EAGM,IAAa,QAAe,EAAoB,EAAM,OAAO,CAAA;yBAIjE,EAMY,EALL,EAAA,MAAE,OAAA,EAAA;GACP,OAAM;GACL,OAAK,EAAA,GAAK,EAAA,YAAQ,UAAc,EAAA,MAAe,UAAQ,CAAA;;oBAChD,CAAR,EAAQ,EAAA,QAAA,UAAA,EAAA,EAAA,MACR,EAAG,EAAA,QAAQ,EAAA,MAAe,QAAQ,EAAA,MAAU,EAAA,EAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"HttpMethod.vue.script.js","names":[],"sources":["../../../src/code-example/components/HttpMethod.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { getHttpMethodInfo } from '@scalar/helpers/http/http-info'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { normalizeHttpMethod } from '@scalar/helpers/http/normalize-http-method'\nimport { computed, type Component } from 'vue'\n\nconst props = defineProps<{\n /** The type of element to render as, defaults to `span` */\n as?: Component | string\n /** The css style property or variable that will be set to the request method color, defaults to `color` */\n property?: string\n /** Whether or not to abbreviated the slot content */\n short?: boolean\n /** The HTTP method to show */\n method: HttpMethod | string\n}>()\n\n/** Grabs the method info object which contains abbreviation, color, and background color etc */\nconst httpMethodInfo = computed(() =>\n getHttpMethodInfo(String(props.method || '')),\n)\n\n/** Full method name */\nconst normalized = computed(() => normalizeHttpMethod(props.method))\n</script>\n\n<template>\n <component\n :is=\"as ?? 'span'\"\n class=\"uppercase\"\n :style=\"{ [property || 'color']: httpMethodInfo.colorVar }\">\n <slot />\n {{ short ? httpMethodInfo.short : normalized }}\n </component>\n</template>\n"],"mappings":";;;;;;;;;;;;;EAMA,IAAM,IAAQ,GAYR,IAAiB,QACrB,EAAkB,OAAO,EAAM,UAAU,EAAE,CAAC,CAC9C,GAGM,IAAa,QAAe,EAAoB,EAAM,MAAM,CAAC;yBAIjE,EAMY,EALL,EAAA,MAAE,MAAA,GAAA;GACP,OAAM;GACL,OAAK,EAAA,GAAK,EAAA,YAAQ,UAAc,EAAA,MAAe,SAAQ,CAAA;;oBAChD,CAAR,EAAQ,EAAA,QAAA,SAAA,GAAA,EAAA,MACR,EAAG,EAAA,QAAQ,EAAA,MAAe,QAAQ,EAAA,KAAU,GAAA,CAAA,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"filter-clients-by-query.js","names":[],"sources":["../../../src/code-example/helpers/filter-clients-by-query.ts"],"sourcesContent":["import type { ScalarComboboxFilterFunction } from '@scalar/components/combobox'\n\nimport type { CustomClientOptionGroup, CustomOrDefaultClientOption } from '../types'\n\n/**\n * Checks if a client label, client key, or language matches a query\n */\nconst matchesOption = (option: CustomOrDefaultClientOption, query: string) => {\n const q = query.toLowerCase()\n return (\n option.label.toLowerCase().includes(q) ||\n option.clientKey.toLowerCase().includes(q) ||\n option.lang.toLowerCase().includes(q)\n )\n}\n\n/**\n * Checks if a client label, client key, or language matches a query\n */\nconst matchesGroup = (group: CustomClientOptionGroup, query: string) => {\n const q = query.toLowerCase()\n return group.label.toLowerCase().includes(q) || group.key.toLowerCase().includes(q)\n}\n\n/**\n * Filters the clients based on a query\n *\n * When dealing with multiple groups, include all options from a group if the\n * group label itself matches — so searching \"JavaScript\" shows all JS clients.\n */\nexport const filterClientsByQuery = ((\n query: string,\n options: CustomOrDefaultClientOption[],\n groups: CustomClientOptionGroup[],\n): CustomOrDefaultClientOption[] => {\n if (query === '') {\n return options\n }\n\n const q = query.toLowerCase()\n\n // Only activate when more than one group is actually visible (has a label and options).\n const visibleGroupCount = groups ? groups.filter((g) => g.label && g.options.length > 0).length : 0\n\n if (groups && visibleGroupCount > 1) {\n const result: CustomOrDefaultClientOption[] = []\n for (const group of groups) {\n if (matchesGroup(group, q)) {\n result.push(...group.options)\n } else {\n result.push(...group.options.filter((o) => matchesOption(o, q)))\n }\n }\n return result\n }\n\n return options.filter((o) => matchesOption(o, q))\n}) satisfies ScalarComboboxFilterFunction<CustomOrDefaultClientOption, CustomClientOptionGroup>\n"],"mappings":";AAOA,IAAM,KAAiB,GAAqC,MAAkB;CAC5E,IAAM,IAAI,EAAM,aAAa;AAC7B,QACE,EAAO,MAAM,aAAa,CAAC,SAAS,EAAE,IACtC,EAAO,UAAU,aAAa,CAAC,SAAS,EAAE,IAC1C,EAAO,KAAK,aAAa,CAAC,SAAS,EAAE;GAOnC,KAAgB,GAAgC,MAAkB;CACtE,IAAM,IAAI,EAAM,aAAa;AAC7B,QAAO,EAAM,MAAM,aAAa,CAAC,SAAS,EAAE,IAAI,EAAM,IAAI,aAAa,CAAC,SAAS,EAAE;GASxE,MACX,GACA,GACA,MACkC;AAClC,KAAI,MAAU,GACZ,QAAO;CAGT,IAAM,IAAI,EAAM,aAAa,EAGvB,IAAoB,IAAS,EAAO,QAAQ,MAAM,EAAE,SAAS,EAAE,QAAQ,SAAS,EAAE,CAAC,SAAS;AAElG,KAAI,KAAU,IAAoB,GAAG;EACnC,IAAM,IAAwC,EAAE;AAChD,OAAK,IAAM,KAAS,EAClB,CAAI,EAAa,GAAO,EAAE,GACxB,EAAO,KAAK,GAAG,EAAM,QAAQ,GAE7B,EAAO,KAAK,GAAG,EAAM,QAAQ,QAAQ,MAAM,EAAc,GAAG,EAAE,CAAC,CAAC;AAGpE,SAAO;;AAGT,QAAO,EAAQ,QAAQ,MAAM,EAAc,GAAG,EAAE,CAAC"}
1
+ {"version":3,"file":"filter-clients-by-query.js","names":[],"sources":["../../../src/code-example/helpers/filter-clients-by-query.ts"],"sourcesContent":["import type { ScalarComboboxFilterFunction } from '@scalar/components/combobox'\n\nimport type { CustomClientOptionGroup, CustomOrDefaultClientOption } from '../types'\n\n/**\n * Checks if a client label, client key, or language matches a query\n */\nconst matchesOption = (option: CustomOrDefaultClientOption, query: string) => {\n const q = query.toLowerCase()\n return (\n option.label.toLowerCase().includes(q) ||\n option.clientKey.toLowerCase().includes(q) ||\n option.lang.toLowerCase().includes(q)\n )\n}\n\n/**\n * Checks if a client label, client key, or language matches a query\n */\nconst matchesGroup = (group: CustomClientOptionGroup, query: string) => {\n const q = query.toLowerCase()\n return group.label.toLowerCase().includes(q) || group.key.toLowerCase().includes(q)\n}\n\n/**\n * Filters the clients based on a query\n *\n * When dealing with multiple groups, include all options from a group if the\n * group label itself matches — so searching \"JavaScript\" shows all JS clients.\n */\nexport const filterClientsByQuery = ((\n query: string,\n options: CustomOrDefaultClientOption[],\n groups: CustomClientOptionGroup[],\n): CustomOrDefaultClientOption[] => {\n if (query === '') {\n return options\n }\n\n const q = query.toLowerCase()\n\n // Only activate when more than one group is actually visible (has a label and options).\n const visibleGroupCount = groups ? groups.filter((g) => g.label && g.options.length > 0).length : 0\n\n if (groups && visibleGroupCount > 1) {\n const result: CustomOrDefaultClientOption[] = []\n for (const group of groups) {\n if (matchesGroup(group, q)) {\n result.push(...group.options)\n } else {\n result.push(...group.options.filter((o) => matchesOption(o, q)))\n }\n }\n return result\n }\n\n return options.filter((o) => matchesOption(o, q))\n}) satisfies ScalarComboboxFilterFunction<CustomOrDefaultClientOption, CustomClientOptionGroup>\n"],"mappings":";AAOA,IAAM,KAAiB,GAAqC,MAAkB;CAC5E,IAAM,IAAI,EAAM,YAAY;CAC5B,OACE,EAAO,MAAM,YAAY,CAAC,CAAC,SAAS,CAAC,KACrC,EAAO,UAAU,YAAY,CAAC,CAAC,SAAS,CAAC,KACzC,EAAO,KAAK,YAAY,CAAC,CAAC,SAAS,CAAC;AAExC,GAKM,KAAgB,GAAgC,MAAkB;CACtE,IAAM,IAAI,EAAM,YAAY;CAC5B,OAAO,EAAM,MAAM,YAAY,CAAC,CAAC,SAAS,CAAC,KAAK,EAAM,IAAI,YAAY,CAAC,CAAC,SAAS,CAAC;AACpF,GAQa,MACX,GACA,GACA,MACkC;CAClC,IAAI,MAAU,IACZ,OAAO;CAGT,IAAM,IAAI,EAAM,YAAY,GAGtB,IAAoB,IAAS,EAAO,QAAQ,MAAM,EAAE,SAAS,EAAE,QAAQ,SAAS,CAAC,CAAC,CAAC,SAAS;CAElG,IAAI,KAAU,IAAoB,GAAG;EACnC,IAAM,IAAwC,CAAC;EAC/C,KAAK,IAAM,KAAS,GAClB,AAAI,EAAa,GAAO,CAAC,IACvB,EAAO,KAAK,GAAG,EAAM,OAAO,IAE5B,EAAO,KAAK,GAAG,EAAM,QAAQ,QAAQ,MAAM,EAAc,GAAG,CAAC,CAAC,CAAC;EAGnE,OAAO;CACT;CAEA,OAAO,EAAQ,QAAQ,MAAM,EAAc,GAAG,CAAC,CAAC;AAClD"}
@@ -1 +1 @@
1
- {"version":3,"file":"find-client.js","names":[],"sources":["../../../src/code-example/helpers/find-client.ts"],"sourcesContent":["import { AVAILABLE_CLIENTS, type AvailableClients } from '@scalar/snippetz'\n\nimport type { ClientOption, CustomClientOption, CustomClientOptionGroup } from '../types'\n\nexport const DEFAULT_CLIENT = 'shell/curl'\n\n/**\n * A selection the code sample picker understands: either a built-in client id\n * (e.g. `js/fetch`) or a custom sample id (e.g. `custom/python`).\n *\n * The custom part is typed as `string & {}` rather than the `custom/${string}`\n * template literal: unioning that template literal with the (very large) built-in\n * client-id union trips TypeScript's \"union too complex\" limit inside Vue's\n * `defineProps` macro. `string & {}` keeps editor hints for the known client ids\n * without expanding the union.\n */\nexport type SelectedClientId = AvailableClients[number] | (string & {})\n\n/** Type guard to check if a string is a valid built-in client id */\nexport const isClient = (id: any): id is AvailableClients[number] => AVAILABLE_CLIENTS.includes(id)\n\n/** Type guard for any selection the picker can restore (built-in client or custom sample id) */\nexport const isSelectedClient = (id: any): id is SelectedClientId =>\n isClient(id) || (typeof id === 'string' && id.startsWith('custom/'))\n\n/**\n * Finds and returns the appropriate client option to select for an operation.\n *\n * Selection rules, given the globally selected client/sample id:\n *\n * 1. A custom sample is selected (`custom/<lang>`): show the matching sample on\n * this operation. If this operation has no sample for that exact language, we\n * keep showing a custom sample (its first one) so the selection stays \"global\".\n * 2. An explicit built-in client is selected: it wins, even when the operation\n * also has custom samples. This includes the default client (`shell/curl`):\n * a built-in id only reaches us through a real selection (config, persistence,\n * or the picker), never as an implicit default, so a deliberate cURL pick must\n * stick instead of snapping back to an SDK example.\n * 3. Otherwise (nothing selected yet): prefer a custom sample when the operation\n * has one, so custom examples are the default.\n * 4. Fall back to the default built-in client, then the first option.\n *\n * @param clientGroups - Array of client option groups, each containing a label and array of client options\n * @param clientId - Optional selection to restore (e.g. 'js/fetch' or 'custom/python')\n * @returns The selected client option, or undefined when there is nothing to select\n */\nexport const findClient = (\n clientGroups: CustomClientOptionGroup[],\n clientId?: SelectedClientId | undefined,\n): ClientOption | CustomClientOption | undefined => {\n const findById = (id: string) => {\n for (const group of clientGroups) {\n const option = group.options.find((option) => option.id === id)\n if (option) {\n return option\n }\n }\n return undefined\n }\n\n const firstCustom = clientGroups.find((group) => group.key === 'custom')?.options[0]\n\n // 1. A custom sample is selected: match the language, otherwise stay on a custom sample\n if (clientId?.startsWith('custom')) {\n return findById(clientId) ?? firstCustom ?? findById(DEFAULT_CLIENT) ?? clientGroups[0]?.options[0]\n }\n\n // 2. An explicit built-in client wins, even when custom samples exist. A built-in\n // id (including the default `shell/curl`) only reaches us through a real\n // selection, so it must stick rather than snap back to a custom sample.\n if (clientId) {\n const option = findById(clientId)\n if (option) {\n return option\n }\n }\n\n // 3. Nothing selected yet: prefer a custom sample when the operation has one\n if (firstCustom) {\n return firstCustom\n }\n\n // 4. Otherwise fall back to the default built-in client, then the first option\n return findById(DEFAULT_CLIENT) ?? clientGroups[0]?.options[0]\n}\n"],"mappings":";;AAIA,IAAa,IAAiB,cAejB,KAAY,MAA4C,EAAkB,SAAS,EAAG,EAGtF,KAAoB,MAC/B,EAAS,EAAG,IAAK,OAAO,KAAO,YAAY,EAAG,WAAW,UAAU,EAuBxD,KACX,GACA,MACkD;CAClD,IAAM,KAAY,MAAe;AAC/B,OAAK,IAAM,KAAS,GAAc;GAChC,IAAM,IAAS,EAAM,QAAQ,MAAM,MAAW,EAAO,OAAO,EAAG;AAC/D,OAAI,EACF,QAAO;;IAMP,IAAc,EAAa,MAAM,MAAU,EAAM,QAAQ,SAAS,EAAE,QAAQ;AAGlF,KAAI,GAAU,WAAW,SAAS,CAChC,QAAO,EAAS,EAAS,IAAI,KAAe,EAAA,aAAwB,IAAI,EAAa,IAAI,QAAQ;AAMnG,KAAI,GAAU;EACZ,IAAM,IAAS,EAAS,EAAS;AACjC,MAAI,EACF,QAAO;;AAUX,QALI,MAKG,EAAA,aAAwB,IAAI,EAAa,IAAI,QAAQ"}
1
+ {"version":3,"file":"find-client.js","names":[],"sources":["../../../src/code-example/helpers/find-client.ts"],"sourcesContent":["import { AVAILABLE_CLIENTS, type AvailableClients } from '@scalar/snippetz'\n\nimport type { ClientOption, CustomClientOption, CustomClientOptionGroup } from '../types'\n\nexport const DEFAULT_CLIENT = 'shell/curl'\n\n/**\n * A selection the code sample picker understands: either a built-in client id\n * (e.g. `js/fetch`) or a custom sample id (e.g. `custom/python`).\n *\n * The custom part is typed as `string & {}` rather than the `custom/${string}`\n * template literal: unioning that template literal with the (very large) built-in\n * client-id union trips TypeScript's \"union too complex\" limit inside Vue's\n * `defineProps` macro. `string & {}` keeps editor hints for the known client ids\n * without expanding the union.\n */\nexport type SelectedClientId = AvailableClients[number] | (string & {})\n\n/** Type guard to check if a string is a valid built-in client id */\nexport const isClient = (id: any): id is AvailableClients[number] => AVAILABLE_CLIENTS.includes(id)\n\n/** Type guard for any selection the picker can restore (built-in client or custom sample id) */\nexport const isSelectedClient = (id: any): id is SelectedClientId =>\n isClient(id) || (typeof id === 'string' && id.startsWith('custom/'))\n\n/**\n * Finds and returns the appropriate client option to select for an operation.\n *\n * Selection rules, given the globally selected client/sample id:\n *\n * 1. A custom sample is selected (`custom/<lang>`): show the matching sample on\n * this operation. If this operation has no sample for that exact language, we\n * keep showing a custom sample (its first one) so the selection stays \"global\".\n * 2. An explicit built-in client is selected: it wins, even when the operation\n * also has custom samples. This includes the default client (`shell/curl`):\n * a built-in id only reaches us through a real selection (config, persistence,\n * or the picker), never as an implicit default, so a deliberate cURL pick must\n * stick instead of snapping back to an SDK example.\n * 3. Otherwise (nothing selected yet): prefer a custom sample when the operation\n * has one, so custom examples are the default.\n * 4. Fall back to the default built-in client, then the first option.\n *\n * @param clientGroups - Array of client option groups, each containing a label and array of client options\n * @param clientId - Optional selection to restore (e.g. 'js/fetch' or 'custom/python')\n * @returns The selected client option, or undefined when there is nothing to select\n */\nexport const findClient = (\n clientGroups: CustomClientOptionGroup[],\n clientId?: SelectedClientId | undefined,\n): ClientOption | CustomClientOption | undefined => {\n const findById = (id: string) => {\n for (const group of clientGroups) {\n const option = group.options.find((option) => option.id === id)\n if (option) {\n return option\n }\n }\n return undefined\n }\n\n const firstCustom = clientGroups.find((group) => group.key === 'custom')?.options[0]\n\n // 1. A custom sample is selected: match the language, otherwise stay on a custom sample\n if (clientId?.startsWith('custom')) {\n return findById(clientId) ?? firstCustom ?? findById(DEFAULT_CLIENT) ?? clientGroups[0]?.options[0]\n }\n\n // 2. An explicit built-in client wins, even when custom samples exist. A built-in\n // id (including the default `shell/curl`) only reaches us through a real\n // selection, so it must stick rather than snap back to a custom sample.\n if (clientId) {\n const option = findById(clientId)\n if (option) {\n return option\n }\n }\n\n // 3. Nothing selected yet: prefer a custom sample when the operation has one\n if (firstCustom) {\n return firstCustom\n }\n\n // 4. Otherwise fall back to the default built-in client, then the first option\n return findById(DEFAULT_CLIENT) ?? clientGroups[0]?.options[0]\n}\n"],"mappings":";;AAIA,IAAa,IAAiB,cAejB,KAAY,MAA4C,EAAkB,SAAS,CAAE,GAGrF,KAAoB,MAC/B,EAAS,CAAE,KAAM,OAAO,KAAO,YAAY,EAAG,WAAW,SAAS,GAuBvD,KACX,GACA,MACkD;CAClD,IAAM,KAAY,MAAe;EAC/B,KAAK,IAAM,KAAS,GAAc;GAChC,IAAM,IAAS,EAAM,QAAQ,MAAM,MAAW,EAAO,OAAO,CAAE;GAC9D,IAAI,GACF,OAAO;EAEX;CAEF,GAEM,IAAc,EAAa,MAAM,MAAU,EAAM,QAAQ,QAAQ,CAAC,EAAE,QAAQ;CAGlF,IAAI,GAAU,WAAW,QAAQ,GAC/B,OAAO,EAAS,CAAQ,KAAK,KAAe,EAAA,YAAuB,KAAK,EAAa,EAAE,EAAE,QAAQ;CAMnG,IAAI,GAAU;EACZ,IAAM,IAAS,EAAS,CAAQ;EAChC,IAAI,GACF,OAAO;CAEX;CAQA,OALI,MAKG,EAAA,YAAuB,KAAK,EAAa,EAAE,EAAE,QAAQ;AAC9D"}
@@ -1 +1 @@
1
- {"version":3,"file":"format-language.js","names":[],"sources":["../../../src/code-example/helpers/format-language.ts"],"sourcesContent":["import { capitalize } from '@scalar/helpers/string/capitalize'\n\n/**\n * Display names for the most common languages found in custom code samples.\n *\n * Custom samples (`x-scalar-examples`, `x-readme`, `x-stainless-*`, …) carry a\n * free-form `lang` string that we otherwise show verbatim in the picker. This\n * map gives the common ones a properly cased label (e.g. `typescript` →\n * `TypeScript`). Anything not listed falls back to a simple capitalization.\n */\nconst LANGUAGE_LABELS: Record<string, string> = {\n c: 'C',\n clojure: 'Clojure',\n cpp: 'C++',\n 'c++': 'C++',\n csharp: 'C#',\n 'c#': 'C#',\n css: 'CSS',\n curl: 'cURL',\n dart: 'Dart',\n fsharp: 'F#',\n 'f#': 'F#',\n go: 'Go',\n golang: 'Go',\n graphql: 'GraphQL',\n html: 'HTML',\n http: 'HTTP',\n java: 'Java',\n javascript: 'JavaScript',\n js: 'JavaScript',\n json: 'JSON',\n kotlin: 'Kotlin',\n node: 'Node.js',\n nodejs: 'Node.js',\n objc: 'Objective-C',\n 'objective-c': 'Objective-C',\n ocaml: 'OCaml',\n php: 'PHP',\n powershell: 'PowerShell',\n py: 'Python',\n python: 'Python',\n r: 'R',\n ruby: 'Ruby',\n rust: 'Rust',\n scala: 'Scala',\n sh: 'Shell',\n shell: 'Shell',\n bash: 'Shell',\n sql: 'SQL',\n swift: 'Swift',\n ts: 'TypeScript',\n typescript: 'TypeScript',\n xml: 'XML',\n yaml: 'YAML',\n yml: 'YAML',\n}\n\n/**\n * Turn a free-form language identifier into a display label for the code sample picker.\n *\n * @param lang - The language identifier from a custom code sample (e.g. `typescript`)\n * @returns A properly cased label (e.g. `TypeScript`), or `undefined` when no language is given\n */\nexport const formatLanguage = (lang?: string): string | undefined => {\n if (!lang) {\n return undefined\n }\n\n return LANGUAGE_LABELS[lang.toLowerCase()] ?? capitalize(lang)\n}\n"],"mappings":";;AAUA,IAAM,IAA0C;CAC9C,GAAG;CACH,SAAS;CACT,KAAK;CACL,OAAO;CACP,QAAQ;CACR,MAAM;CACN,KAAK;CACL,MAAM;CACN,MAAM;CACN,QAAQ;CACR,MAAM;CACN,IAAI;CACJ,QAAQ;CACR,SAAS;CACT,MAAM;CACN,MAAM;CACN,MAAM;CACN,YAAY;CACZ,IAAI;CACJ,MAAM;CACN,QAAQ;CACR,MAAM;CACN,QAAQ;CACR,MAAM;CACN,eAAe;CACf,OAAO;CACP,KAAK;CACL,YAAY;CACZ,IAAI;CACJ,QAAQ;CACR,GAAG;CACH,MAAM;CACN,MAAM;CACN,OAAO;CACP,IAAI;CACJ,OAAO;CACP,MAAM;CACN,KAAK;CACL,OAAO;CACP,IAAI;CACJ,YAAY;CACZ,KAAK;CACL,MAAM;CACN,KAAK;CACN,EAQY,KAAkB,MAAsC;AAC9D,OAIL,QAAO,EAAgB,EAAK,aAAa,KAAK,EAAW,EAAK"}
1
+ {"version":3,"file":"format-language.js","names":[],"sources":["../../../src/code-example/helpers/format-language.ts"],"sourcesContent":["import { capitalize } from '@scalar/helpers/string/capitalize'\n\n/**\n * Display names for the most common languages found in custom code samples.\n *\n * Custom samples (`x-scalar-examples`, `x-readme`, `x-stainless-*`, …) carry a\n * free-form `lang` string that we otherwise show verbatim in the picker. This\n * map gives the common ones a properly cased label (e.g. `typescript` →\n * `TypeScript`). Anything not listed falls back to a simple capitalization.\n */\nconst LANGUAGE_LABELS: Record<string, string> = {\n c: 'C',\n clojure: 'Clojure',\n cpp: 'C++',\n 'c++': 'C++',\n csharp: 'C#',\n 'c#': 'C#',\n css: 'CSS',\n curl: 'cURL',\n dart: 'Dart',\n fsharp: 'F#',\n 'f#': 'F#',\n go: 'Go',\n golang: 'Go',\n graphql: 'GraphQL',\n html: 'HTML',\n http: 'HTTP',\n java: 'Java',\n javascript: 'JavaScript',\n js: 'JavaScript',\n json: 'JSON',\n kotlin: 'Kotlin',\n node: 'Node.js',\n nodejs: 'Node.js',\n objc: 'Objective-C',\n 'objective-c': 'Objective-C',\n ocaml: 'OCaml',\n php: 'PHP',\n powershell: 'PowerShell',\n py: 'Python',\n python: 'Python',\n r: 'R',\n ruby: 'Ruby',\n rust: 'Rust',\n scala: 'Scala',\n sh: 'Shell',\n shell: 'Shell',\n bash: 'Shell',\n sql: 'SQL',\n swift: 'Swift',\n ts: 'TypeScript',\n typescript: 'TypeScript',\n xml: 'XML',\n yaml: 'YAML',\n yml: 'YAML',\n}\n\n/**\n * Turn a free-form language identifier into a display label for the code sample picker.\n *\n * @param lang - The language identifier from a custom code sample (e.g. `typescript`)\n * @returns A properly cased label (e.g. `TypeScript`), or `undefined` when no language is given\n */\nexport const formatLanguage = (lang?: string): string | undefined => {\n if (!lang) {\n return undefined\n }\n\n return LANGUAGE_LABELS[lang.toLowerCase()] ?? capitalize(lang)\n}\n"],"mappings":";;AAUA,IAAM,IAA0C;CAC9C,GAAG;CACH,SAAS;CACT,KAAK;CACL,OAAO;CACP,QAAQ;CACR,MAAM;CACN,KAAK;CACL,MAAM;CACN,MAAM;CACN,QAAQ;CACR,MAAM;CACN,IAAI;CACJ,QAAQ;CACR,SAAS;CACT,MAAM;CACN,MAAM;CACN,MAAM;CACN,YAAY;CACZ,IAAI;CACJ,MAAM;CACN,QAAQ;CACR,MAAM;CACN,QAAQ;CACR,MAAM;CACN,eAAe;CACf,OAAO;CACP,KAAK;CACL,YAAY;CACZ,IAAI;CACJ,QAAQ;CACR,GAAG;CACH,MAAM;CACN,MAAM;CACN,OAAO;CACP,IAAI;CACJ,OAAO;CACP,MAAM;CACN,KAAK;CACL,OAAO;CACP,IAAI;CACJ,YAAY;CACZ,KAAK;CACL,MAAM;CACN,KAAK;AACP,GAQa,KAAkB,MAAsC;CAC9D,OAIL,OAAO,EAAgB,EAAK,YAAY,MAAM,EAAW,CAAI;AAC/D"}
@@ -1 +1 @@
1
- {"version":3,"file":"generate-client-options.js","names":[],"sources":["../../../src/code-example/helpers/generate-client-options.ts"],"sourcesContent":["import { AVAILABLE_CLIENTS, type AvailableClients, snippetz } from '@scalar/snippetz'\nimport type { XCodeSample } from '@scalar/workspace-store/schemas/extensions/operation'\nimport { capitalize } from 'vue'\n\nimport type { ClientOptionGroup } from '../types'\n\n/** Type of custom code sample IDs */\nexport type CustomCodeSampleId = `custom/${string}`\n\n/**\n * Build stable, language-keyed ids for an operation's custom code samples.\n *\n * Custom samples are defined per operation, but a selection (e.g. the Python SDK\n * example) should sync across every operation that ships the same language. So we\n * key the id by language rather than by position: the first sample of a language\n * becomes `custom/<lang>`, and any further samples that repeat a language fall back\n * to `custom/<lang>/<n>` so they stay individually selectable within the operation.\n *\n * The language is lower-cased so a selection still matches when operations (or\n * extensions) spell the same language with different casing (e.g. `Python` vs\n * `python`).\n *\n * @param samples - The custom code samples for a single operation\n * @returns A list of ids aligned by index with the input samples\n */\nexport const getCustomClientIds = (samples: XCodeSample[]): CustomCodeSampleId[] => {\n const countByLang = new Map<string, number>()\n\n return samples.map((sample): CustomCodeSampleId => {\n const lang = (sample.lang || 'plaintext').toLowerCase()\n const seen = countByLang.get(lang) ?? 0\n countByLang.set(lang, seen + 1)\n\n return seen === 0 ? `custom/${lang}` : `custom/${lang}/${seen}`\n })\n}\n\n/**\n * Generate client options for the request example block by filtering by allowed clients\n *\n * @param allowedClients - The list of allowed clients to include in the options\n * @returns A list of client option groups\n */\nexport const generateClientOptions = (allowedClients: AvailableClients = AVAILABLE_CLIENTS): ClientOptionGroup[] => {\n /** Create set of allowlist for quicker lookups */\n const allowedClientsSet = new Set(allowedClients)\n\n const options = snippetz()\n .clients()\n .flatMap((group) => {\n const options = group.clients.flatMap((plugin) => {\n const id = `${group.key}/${plugin.client}` as AvailableClients[number]\n\n // If the client is not allowed, skip it\n if (!allowedClientsSet.has(id)) {\n return []\n }\n\n return {\n id,\n lang: plugin.client === 'curl' ? ('curl' as const) : group.key,\n title: `${capitalize(group.title)} ${plugin.title}`,\n label: plugin.title,\n targetKey: group.key,\n targetTitle: group.title,\n clientKey: plugin.client,\n }\n })\n\n // If no clients are allowed, skip this group\n if (options.length === 0) {\n return []\n }\n\n return {\n label: group.title,\n key: group.key,\n options,\n }\n })\n\n return options\n}\n"],"mappings":";;;AAyBA,IAAa,KAAsB,MAAiD;CAClF,IAAM,oBAAc,IAAI,KAAqB;AAE7C,QAAO,EAAQ,KAAK,MAA+B;EACjD,IAAM,KAAQ,EAAO,QAAQ,aAAa,aAAa,EACjD,IAAO,EAAY,IAAI,EAAK,IAAI;AAGtC,SAFA,EAAY,IAAI,GAAM,IAAO,EAAE,EAExB,MAAS,IAAI,UAAU,MAAS,UAAU,EAAK,GAAG;GACzD;GASS,KAAyB,IAAmC,MAA2C;CAElH,IAAM,IAAoB,IAAI,IAAI,EAAe;AAoCjD,QAlCgB,GAAU,CACvB,SAAS,CACT,SAAS,MAAU;EAClB,IAAM,IAAU,EAAM,QAAQ,SAAS,MAAW;GAChD,IAAM,IAAK,GAAG,EAAM,IAAI,GAAG,EAAO;AAOlC,UAJK,EAAkB,IAAI,EAAG,GAIvB;IACL;IACA,MAAM,EAAO,WAAW,SAAU,SAAmB,EAAM;IAC3D,OAAO,GAAG,EAAW,EAAM,MAAM,CAAC,GAAG,EAAO;IAC5C,OAAO,EAAO;IACd,WAAW,EAAM;IACjB,aAAa,EAAM;IACnB,WAAW,EAAO;IACnB,GAXQ,EAAE;IAYX;AAOF,SAJI,EAAQ,WAAW,IACd,EAAE,GAGJ;GACL,OAAO,EAAM;GACb,KAAK,EAAM;GACX;GACD;GACD"}
1
+ {"version":3,"file":"generate-client-options.js","names":[],"sources":["../../../src/code-example/helpers/generate-client-options.ts"],"sourcesContent":["import { AVAILABLE_CLIENTS, type AvailableClients, snippetz } from '@scalar/snippetz'\nimport type { XCodeSample } from '@scalar/workspace-store/schemas/extensions/operation'\nimport { capitalize } from 'vue'\n\nimport type { ClientOptionGroup } from '../types'\n\n/** Type of custom code sample IDs */\nexport type CustomCodeSampleId = `custom/${string}`\n\n/**\n * Build stable, language-keyed ids for an operation's custom code samples.\n *\n * Custom samples are defined per operation, but a selection (e.g. the Python SDK\n * example) should sync across every operation that ships the same language. So we\n * key the id by language rather than by position: the first sample of a language\n * becomes `custom/<lang>`, and any further samples that repeat a language fall back\n * to `custom/<lang>/<n>` so they stay individually selectable within the operation.\n *\n * The language is lower-cased so a selection still matches when operations (or\n * extensions) spell the same language with different casing (e.g. `Python` vs\n * `python`).\n *\n * @param samples - The custom code samples for a single operation\n * @returns A list of ids aligned by index with the input samples\n */\nexport const getCustomClientIds = (samples: XCodeSample[]): CustomCodeSampleId[] => {\n const countByLang = new Map<string, number>()\n\n return samples.map((sample): CustomCodeSampleId => {\n const lang = (sample.lang || 'plaintext').toLowerCase()\n const seen = countByLang.get(lang) ?? 0\n countByLang.set(lang, seen + 1)\n\n return seen === 0 ? `custom/${lang}` : `custom/${lang}/${seen}`\n })\n}\n\n/**\n * Generate client options for the request example block by filtering by allowed clients\n *\n * @param allowedClients - The list of allowed clients to include in the options\n * @returns A list of client option groups\n */\nexport const generateClientOptions = (allowedClients: AvailableClients = AVAILABLE_CLIENTS): ClientOptionGroup[] => {\n /** Create set of allowlist for quicker lookups */\n const allowedClientsSet = new Set(allowedClients)\n\n const options = snippetz()\n .clients()\n .flatMap((group) => {\n const options = group.clients.flatMap((plugin) => {\n const id = `${group.key}/${plugin.client}` as AvailableClients[number]\n\n // If the client is not allowed, skip it\n if (!allowedClientsSet.has(id)) {\n return []\n }\n\n return {\n id,\n lang: plugin.client === 'curl' ? ('curl' as const) : group.key,\n title: `${capitalize(group.title)} ${plugin.title}`,\n label: plugin.title,\n targetKey: group.key,\n targetTitle: group.title,\n clientKey: plugin.client,\n }\n })\n\n // If no clients are allowed, skip this group\n if (options.length === 0) {\n return []\n }\n\n return {\n label: group.title,\n key: group.key,\n options,\n }\n })\n\n return options\n}\n"],"mappings":";;;AAyBA,IAAa,KAAsB,MAAiD;CAClF,IAAM,oBAAc,IAAI,IAAoB;CAE5C,OAAO,EAAQ,KAAK,MAA+B;EACjD,IAAM,KAAQ,EAAO,QAAQ,YAAA,CAAa,YAAY,GAChD,IAAO,EAAY,IAAI,CAAI,KAAK;EAGtC,OAFA,EAAY,IAAI,GAAM,IAAO,CAAC,GAEvB,MAAS,IAAI,UAAU,MAAS,UAAU,EAAK,GAAG;CAC3D,CAAC;AACH,GAQa,KAAyB,IAAmC,MAA2C;CAElH,IAAM,IAAoB,IAAI,IAAI,CAAc;CAoChD,OAlCgB,EAAS,CAAC,CACvB,QAAQ,CAAC,CACT,SAAS,MAAU;EAClB,IAAM,IAAU,EAAM,QAAQ,SAAS,MAAW;GAChD,IAAM,IAAK,GAAG,EAAM,IAAI,GAAG,EAAO;GAOlC,OAJK,EAAkB,IAAI,CAAE,IAItB;IACL;IACA,MAAM,EAAO,WAAW,SAAU,SAAmB,EAAM;IAC3D,OAAO,GAAG,EAAW,EAAM,KAAK,EAAE,GAAG,EAAO;IAC5C,OAAO,EAAO;IACd,WAAW,EAAM;IACjB,aAAa,EAAM;IACnB,WAAW,EAAO;GACpB,IAXS,CAAC;EAYZ,CAAC;EAOD,OAJI,EAAQ,WAAW,IACd,CAAC,IAGH;GACL,OAAO,EAAM;GACb,KAAK,EAAM;GACX;EACF;CACF,CAEK;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"generate-code-snippet.js","names":[],"sources":["../../../src/code-example/helpers/generate-code-snippet.ts"],"sourcesContent":["import type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport type { AvailableClient, ClientId, TargetId } from '@scalar/snippetz'\nimport type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type { XCodeSample } from '@scalar/workspace-store/schemas/extensions/operation'\nimport type { OperationObject, ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\nimport { type CustomCodeSampleId, getCustomClientIds } from './generate-client-options'\nimport { getSnippet } from './get-snippet'\nimport { operationToHar } from './operation-to-har/operation-to-har'\n\ntype GenerateCodeSnippetProps = {\n /** The selected client/language for code generation (e.g., 'node/fetch') or a custom code sample ID. */\n clientId: AvailableClient | CustomCodeSampleId | undefined\n /** The Content-Type header value for the request body (e.g., 'application/json'). */\n contentType: string | undefined\n /** Array of custom code samples defined in the OpenAPI x-codeSamples extension. */\n customCodeSamples: XCodeSample[]\n /** The specific example value to use when generating the code snippet. */\n example: string | undefined\n /** The HTTP method for the operation (e.g., GET, POST, PUT). */\n method: HttpMethod\n /** The OpenAPI operation object containing request/response details. */\n operation: OperationObject\n /** The API endpoint path (e.g., '/users/{id}'). */\n path: string\n /** Array of security schemes to apply to the request (e.g., API keys, OAuth). */\n securitySchemes: SecuritySchemeObjectSecret[]\n /** The server object defining the base URL for the API request. */\n server: ServerObject | null\n /** Workspace + document cookies */\n globalCookies?: XScalarCookie[]\n /** Whether to include default headers (e.g., Accept, Content-Type) automatically. */\n includeDefaultHeaders?: boolean\n /** Selected oneOf/anyOf variants for nested request body example generation. */\n requestBodyCompositionSelection?: Record<string, number>\n /** Whether to disable parameters by default. */\n defaultDisabledParameters?: boolean\n}\n\n/** Generate the code snippet for the selected example OR operation */\nexport const generateCodeSnippet = ({\n clientId,\n customCodeSamples,\n includeDefaultHeaders = false,\n operation,\n method,\n path,\n example,\n contentType,\n server,\n securitySchemes,\n globalCookies,\n requestBodyCompositionSelection,\n defaultDisabledParameters,\n}: GenerateCodeSnippetProps): string => {\n try {\n if (!clientId) {\n return ''\n }\n\n // Use the selected custom example, matched by its language-keyed id\n if (clientId.startsWith('custom')) {\n const ids = getCustomClientIds(customCodeSamples)\n const index = ids.indexOf(clientId as CustomCodeSampleId)\n\n return customCodeSamples[index]?.source ?? 'Custom example not found'\n }\n\n const harRequest = operationToHar({\n operation,\n contentType,\n method,\n path,\n server,\n securitySchemes,\n example,\n globalCookies,\n includeDefaultHeaders,\n requestBodyCompositionSelection,\n defaultDisabledParameters,\n })\n\n const [targetKey, clientKey] = clientId.split('/') as [TargetId, ClientId<TargetId>]\n\n const [error, payload] = getSnippet(targetKey, clientKey, harRequest)\n if (error) {\n console.error('[generateCodeSnippet]', error)\n return error.message ?? 'Error generating code snippet'\n }\n\n return payload\n } catch (error) {\n console.error('[generateCodeSnippet]', error)\n return 'Error generating code snippet'\n }\n}\n"],"mappings":";;;;AAyCA,IAAa,KAAuB,EAClC,aACA,sBACA,2BAAwB,IACxB,cACA,WACA,SACA,YACA,gBACA,WACA,oBACA,kBACA,oCACA,mCACsC;AACtC,KAAI;AACF,MAAI,CAAC,EACH,QAAO;AAIT,MAAI,EAAS,WAAW,SAAS,CAI/B,QAAO,EAHK,EAAmB,EAAkB,CAC/B,QAAQ,EAA+B,GAExB,UAAU;EAG7C,IAAM,IAAa,EAAe;GAChC;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAAC,EAEI,CAAC,GAAW,KAAa,EAAS,MAAM,IAAI,EAE5C,CAAC,GAAO,KAAW,EAAW,GAAW,GAAW,EAAW;AAMrE,SALI,KACF,QAAQ,MAAM,yBAAyB,EAAM,EACtC,EAAM,WAAW,mCAGnB;UACA,GAAO;AAEd,SADA,QAAQ,MAAM,yBAAyB,EAAM,EACtC"}
1
+ {"version":3,"file":"generate-code-snippet.js","names":[],"sources":["../../../src/code-example/helpers/generate-code-snippet.ts"],"sourcesContent":["import type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport type { AvailableClient, ClientId, TargetId } from '@scalar/snippetz'\nimport type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type { XCodeSample } from '@scalar/workspace-store/schemas/extensions/operation'\nimport type { OperationObject, ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\nimport { type CustomCodeSampleId, getCustomClientIds } from './generate-client-options'\nimport { getSnippet } from './get-snippet'\nimport { operationToHar } from './operation-to-har/operation-to-har'\n\ntype GenerateCodeSnippetProps = {\n /** The selected client/language for code generation (e.g., 'node/fetch') or a custom code sample ID. */\n clientId: AvailableClient | CustomCodeSampleId | undefined\n /** The Content-Type header value for the request body (e.g., 'application/json'). */\n contentType: string | undefined\n /** Array of custom code samples defined in the OpenAPI x-codeSamples extension. */\n customCodeSamples: XCodeSample[]\n /** The specific example value to use when generating the code snippet. */\n example: string | undefined\n /** The HTTP method for the operation (e.g., GET, POST, PUT). */\n method: HttpMethod\n /** The OpenAPI operation object containing request/response details. */\n operation: OperationObject\n /** The API endpoint path (e.g., '/users/{id}'). */\n path: string\n /** Array of security schemes to apply to the request (e.g., API keys, OAuth). */\n securitySchemes: SecuritySchemeObjectSecret[]\n /** The server object defining the base URL for the API request. */\n server: ServerObject | null\n /** Workspace + document cookies */\n globalCookies?: XScalarCookie[]\n /** Whether to include default headers (e.g., Accept, Content-Type) automatically. */\n includeDefaultHeaders?: boolean\n /** Selected oneOf/anyOf variants for nested request body example generation. */\n requestBodyCompositionSelection?: Record<string, number>\n /** Whether to disable parameters by default. */\n defaultDisabledParameters?: boolean\n}\n\n/** Generate the code snippet for the selected example OR operation */\nexport const generateCodeSnippet = ({\n clientId,\n customCodeSamples,\n includeDefaultHeaders = false,\n operation,\n method,\n path,\n example,\n contentType,\n server,\n securitySchemes,\n globalCookies,\n requestBodyCompositionSelection,\n defaultDisabledParameters,\n}: GenerateCodeSnippetProps): string => {\n try {\n if (!clientId) {\n return ''\n }\n\n // Use the selected custom example, matched by its language-keyed id\n if (clientId.startsWith('custom')) {\n const ids = getCustomClientIds(customCodeSamples)\n const index = ids.indexOf(clientId as CustomCodeSampleId)\n\n return customCodeSamples[index]?.source ?? 'Custom example not found'\n }\n\n const harRequest = operationToHar({\n operation,\n contentType,\n method,\n path,\n server,\n securitySchemes,\n example,\n globalCookies,\n includeDefaultHeaders,\n requestBodyCompositionSelection,\n defaultDisabledParameters,\n })\n\n const [targetKey, clientKey] = clientId.split('/') as [TargetId, ClientId<TargetId>]\n\n const [error, payload] = getSnippet(targetKey, clientKey, harRequest)\n if (error) {\n console.error('[generateCodeSnippet]', error)\n return error.message ?? 'Error generating code snippet'\n }\n\n return payload\n } catch (error) {\n console.error('[generateCodeSnippet]', error)\n return 'Error generating code snippet'\n }\n}\n"],"mappings":";;;;AAyCA,IAAa,KAAuB,EAClC,aACA,sBACA,2BAAwB,IACxB,cACA,WACA,SACA,YACA,gBACA,WACA,oBACA,kBACA,oCACA,mCACsC;CACtC,IAAI;EACF,IAAI,CAAC,GACH,OAAO;EAIT,IAAI,EAAS,WAAW,QAAQ,GAI9B,OAAO,EAHK,EAAmB,CACjB,CAAA,CAAI,QAAQ,CAED,EAAM,EAAE,UAAU;EAG7C,IAAM,IAAa,EAAe;GAChC;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAAC,GAEK,CAAC,GAAW,KAAa,EAAS,MAAM,GAAG,GAE3C,CAAC,GAAO,KAAW,EAAW,GAAW,GAAW,CAAU;EAMpE,OALI,KACF,QAAQ,MAAM,yBAAyB,CAAK,GACrC,EAAM,WAAW,mCAGnB;CACT,SAAS,GAAO;EAEd,OADA,QAAQ,MAAM,yBAAyB,CAAK,GACrC;CACT;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"get-clients.js","names":[],"sources":["../../../src/code-example/helpers/get-clients.ts"],"sourcesContent":["import type { TargetId } from '@scalar/types/snippetz'\nimport type { XCodeSample } from '@scalar/workspace-store/schemas/extensions/operation'\n\nimport { formatLanguage } from './format-language'\nimport { getCustomClientIds } from './generate-client-options'\nimport { CODE_EXAMPLES_GROUP_LABEL } from './get-custom-code-samples'\nimport type { ClientOptionGroup, CustomClientOption, CustomClientOptionGroup } from '../types'\n\n/**\n * Merges custom code samples with the client options\n *\n * @param customCodeSamples - The custom code samples from the operation to merge with the client options\n * @param clientOptions - The client options to merge with the custom code samples\n * @param label - The label for the custom samples group (e.g. \"SDK\" or \"Code Examples\")\n * @returns A list of client option groups\n */\nexport const getClients = (\n customCodeSamples: XCodeSample[],\n clientOptions: ClientOptionGroup[],\n label: string = CODE_EXAMPLES_GROUP_LABEL,\n): CustomClientOptionGroup[] => {\n // Handle custom code examples\n if (customCodeSamples.length) {\n // Language-keyed ids so the same sample can be selected across operations\n const ids = getCustomClientIds(customCodeSamples)\n\n const customClients = customCodeSamples.map((sample, index) => {\n const id = ids[index] ?? `custom/${index}`\n const label = sample.label || formatLanguage(sample.lang) || id\n const lang = (sample.lang as TargetId) || 'plaintext'\n\n return {\n id,\n lang,\n title: label,\n label,\n clientKey: 'custom',\n } satisfies CustomClientOption\n })\n\n return [\n {\n label,\n key: 'custom',\n options: customClients,\n },\n ...clientOptions,\n ]\n }\n\n return clientOptions\n}\n"],"mappings":";;;;AAgBA,IAAa,KACX,GACA,GACA,IAAgB,MACc;AAE9B,KAAI,EAAkB,QAAQ;EAE5B,IAAM,IAAM,EAAmB,EAAkB;AAgBjD,SAAO,CACL;GACE;GACA,KAAK;GACL,SAlBkB,EAAkB,KAAK,GAAQ,MAAU;IAC7D,IAAM,IAAK,EAAI,MAAU,UAAU,KAC7B,IAAQ,EAAO,SAAS,EAAe,EAAO,KAAK,IAAI;AAG7D,WAAO;KACL;KACA,MAJY,EAAO,QAAqB;KAKxC,OAAO;KACP;KACA,WAAW;KACZ;KACD;GAOC,EACD,GAAG,EACJ;;AAGH,QAAO"}
1
+ {"version":3,"file":"get-clients.js","names":[],"sources":["../../../src/code-example/helpers/get-clients.ts"],"sourcesContent":["import type { TargetId } from '@scalar/types/snippetz'\nimport type { XCodeSample } from '@scalar/workspace-store/schemas/extensions/operation'\n\nimport { formatLanguage } from './format-language'\nimport { getCustomClientIds } from './generate-client-options'\nimport { CODE_EXAMPLES_GROUP_LABEL } from './get-custom-code-samples'\nimport type { ClientOptionGroup, CustomClientOption, CustomClientOptionGroup } from '../types'\n\n/**\n * Merges custom code samples with the client options\n *\n * @param customCodeSamples - The custom code samples from the operation to merge with the client options\n * @param clientOptions - The client options to merge with the custom code samples\n * @param label - The label for the custom samples group (e.g. \"SDK\" or \"Code Examples\")\n * @returns A list of client option groups\n */\nexport const getClients = (\n customCodeSamples: XCodeSample[],\n clientOptions: ClientOptionGroup[],\n label: string = CODE_EXAMPLES_GROUP_LABEL,\n): CustomClientOptionGroup[] => {\n // Handle custom code examples\n if (customCodeSamples.length) {\n // Language-keyed ids so the same sample can be selected across operations\n const ids = getCustomClientIds(customCodeSamples)\n\n const customClients = customCodeSamples.map((sample, index) => {\n const id = ids[index] ?? `custom/${index}`\n const label = sample.label || formatLanguage(sample.lang) || id\n const lang = (sample.lang as TargetId) || 'plaintext'\n\n return {\n id,\n lang,\n title: label,\n label,\n clientKey: 'custom',\n } satisfies CustomClientOption\n })\n\n return [\n {\n label,\n key: 'custom',\n options: customClients,\n },\n ...clientOptions,\n ]\n }\n\n return clientOptions\n}\n"],"mappings":";;;;AAgBA,IAAa,KACX,GACA,GACA,IAAgB,MACc;CAE9B,IAAI,EAAkB,QAAQ;EAE5B,IAAM,IAAM,EAAmB,CAAiB;EAgBhD,OAAO,CACL;GACE;GACA,KAAK;GACL,SAlBkB,EAAkB,KAAK,GAAQ,MAAU;IAC7D,IAAM,IAAK,EAAI,MAAU,UAAU,KAC7B,IAAQ,EAAO,SAAS,EAAe,EAAO,IAAI,KAAK;IAG7D,OAAO;KACL;KACA,MAJY,EAAO,QAAqB;KAKxC,OAAO;KACP;KACA,WAAW;IACb;GACF,CAMa;EACX,GACA,GAAG,CACL;CACF;CAEA,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"get-custom-code-samples.js","names":[],"sources":["../../../src/code-example/helpers/get-custom-code-samples.ts"],"sourcesContent":["import type {\n XCodeSample,\n XLanguageExample,\n XReadmeCodeSample,\n} from '@scalar/workspace-store/schemas/extensions/operation'\nimport type { OperationObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\n/** Turns a `{ language: source }` map (x-stainless-snippets) into code samples. */\nconst fromSnippetMap = (snippets: Record<string, string> | undefined, label?: string): XCodeSample[] =>\n Object.entries(snippets ?? {}).map(([lang, source]) => ({ lang, source, ...(label ? { label } : {}) }))\n\n/**\n * Turns `x-stainless-examples` / `x-scalar-examples` into code samples.\n *\n * Each example carries per-language request snippets and an optional title that\n * we surface as the picker label. The response is only used for documentation,\n * so it is ignored here.\n */\nconst fromLanguageExamples = (examples: XLanguageExample | XLanguageExample[] | undefined): XCodeSample[] => {\n if (!examples) {\n return []\n }\n\n return (Array.isArray(examples) ? examples : [examples]).flatMap((example) =>\n fromSnippetMap(example.request, example.title),\n )\n}\n\n/** Turns ReadMe's `x-readme.code-samples` into code samples. */\nconst fromReadmeSamples = (samples: XReadmeCodeSample[] | undefined): XCodeSample[] =>\n (samples ?? []).map((sample) => ({\n lang: sample.language,\n source: sample.code,\n ...(sample.name ? { label: sample.name } : {}),\n }))\n\n/** Picker group label for samples generated by an SDK provider (Scalar, Stainless, …). */\nconst SDK_GROUP_LABEL = 'SDK'\n\n/** Picker group label for generic or docs-platform samples (the standard `x-codeSamples` family, ReadMe, …). */\nexport const CODE_EXAMPLES_GROUP_LABEL = 'Code Examples'\n\ntype CustomCodeSampleGroupLabel = typeof SDK_GROUP_LABEL | typeof CODE_EXAMPLES_GROUP_LABEL\n\ntype CustomCodeSamples = {\n /**\n * Group label for the code sample picker.\n *\n * Samples that come from an SDK provider extension (`x-scalar-examples`,\n * `x-stainless-snippets`, `x-stainless-examples`) surface under \"SDK\". Generic\n * or docs-platform samples (`x-readme`, the `x-codeSamples` family) surface\n * under \"Code Examples\".\n */\n label: CustomCodeSampleGroupLabel\n /** The custom code samples, in picker order. */\n samples: XCodeSample[]\n}\n\n/**\n * Grabs any custom code samples from the operation.\n *\n * Several tools write code samples into OpenAPI under different extensions. When\n * more than one is present we use the highest-priority source only, rather than\n * showing duplicates from every tool. Priority, highest first:\n *\n * 1. `x-scalar-examples` (SDK)\n * 2. `x-stainless-snippets` (SDK, overrides `x-stainless-examples`)\n * 3. `x-stainless-examples` (SDK)\n * 4. `x-readme.code-samples` (Code Examples)\n * 5. `x-codeSamples` / `x-code-samples` / `x-custom-examples` (Code Examples)\n *\n * The winning source also determines the picker group label: SDK-provider\n * extensions surface under \"SDK\", everything else under \"Code Examples\".\n *\n * Note that Speakeasy does not have its own extension — it writes into the\n * standard `x-codeSamples`, so its snippets surface under \"Code Examples\".\n *\n * @param operation - The operation to get the custom code samples from\n * @returns The picker group label and the custom code samples which exist in the operation\n */\nexport const getCustomCodeSamples = (operation: OperationObject): CustomCodeSamples => {\n const scalarExamples = operation['x-scalar-examples'] ?? []\n if (scalarExamples.length) {\n return { label: SDK_GROUP_LABEL, samples: scalarExamples }\n }\n\n const stainlessSnippets = fromSnippetMap(operation['x-stainless-snippets'])\n if (stainlessSnippets.length) {\n return { label: SDK_GROUP_LABEL, samples: stainlessSnippets }\n }\n\n const stainlessExamples = fromLanguageExamples(operation['x-stainless-examples'])\n if (stainlessExamples.length) {\n return { label: SDK_GROUP_LABEL, samples: stainlessExamples }\n }\n\n const readmeSamples = fromReadmeSamples(operation['x-readme']?.['code-samples'])\n if (readmeSamples.length) {\n return { label: CODE_EXAMPLES_GROUP_LABEL, samples: readmeSamples }\n }\n\n const customCodeKeys = ['x-custom-examples', 'x-codeSamples', 'x-code-samples'] as const\n return { label: CODE_EXAMPLES_GROUP_LABEL, samples: customCodeKeys.flatMap((key) => operation[key] ?? []) }\n}\n"],"mappings":";AAQA,IAAM,KAAkB,GAA8C,MACpE,OAAO,QAAQ,KAAY,EAAE,CAAC,CAAC,KAAK,CAAC,GAAM,QAAa;CAAE;CAAM;CAAQ,GAAI,IAAQ,EAAE,UAAO,GAAG,EAAE;CAAG,EAAE,EASnG,KAAwB,MACvB,KAIG,MAAM,QAAQ,EAAS,GAAG,IAAW,CAAC,EAAS,EAAE,SAAS,MAChE,EAAe,EAAQ,SAAS,EAAQ,MAAM,CAC/C,GALQ,EAAE,EASP,KAAqB,OACxB,KAAW,EAAE,EAAE,KAAK,OAAY;CAC/B,MAAM,EAAO;CACb,QAAQ,EAAO;CACf,GAAI,EAAO,OAAO,EAAE,OAAO,EAAO,MAAM,GAAG,EAAE;CAC9C,EAAE,EAGC,IAAkB,OAGX,IAA4B,iBAwC5B,KAAwB,MAAkD;CACrF,IAAM,IAAiB,EAAU,wBAAwB,EAAE;AAC3D,KAAI,EAAe,OACjB,QAAO;EAAE,OAAO;EAAiB,SAAS;EAAgB;CAG5D,IAAM,IAAoB,EAAe,EAAU,wBAAwB;AAC3E,KAAI,EAAkB,OACpB,QAAO;EAAE,OAAO;EAAiB,SAAS;EAAmB;CAG/D,IAAM,IAAoB,EAAqB,EAAU,wBAAwB;AACjF,KAAI,EAAkB,OACpB,QAAO;EAAE,OAAO;EAAiB,SAAS;EAAmB;CAG/D,IAAM,IAAgB,EAAkB,EAAU,cAAc,gBAAgB;AAMhF,QALI,EAAc,SACT;EAAE,OAAO;EAA2B,SAAS;EAAe,GAI9D;EAAE,OAAO;EAA2B,SADpB;GAAC;GAAqB;GAAiB;GAAiB,CACZ,SAAS,MAAQ,EAAU,MAAQ,EAAE,CAAC;EAAE"}
1
+ {"version":3,"file":"get-custom-code-samples.js","names":[],"sources":["../../../src/code-example/helpers/get-custom-code-samples.ts"],"sourcesContent":["import type {\n XCodeSample,\n XLanguageExample,\n XReadmeCodeSample,\n} from '@scalar/workspace-store/schemas/extensions/operation'\nimport type { OperationObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\n/** Turns a `{ language: source }` map (x-stainless-snippets) into code samples. */\nconst fromSnippetMap = (snippets: Record<string, string> | undefined, label?: string): XCodeSample[] =>\n Object.entries(snippets ?? {}).map(([lang, source]) => ({ lang, source, ...(label ? { label } : {}) }))\n\n/**\n * Turns `x-stainless-examples` / `x-scalar-examples` into code samples.\n *\n * Each example carries per-language request snippets and an optional title that\n * we surface as the picker label. The response is only used for documentation,\n * so it is ignored here.\n */\nconst fromLanguageExamples = (examples: XLanguageExample | XLanguageExample[] | undefined): XCodeSample[] => {\n if (!examples) {\n return []\n }\n\n return (Array.isArray(examples) ? examples : [examples]).flatMap((example) =>\n fromSnippetMap(example.request, example.title),\n )\n}\n\n/** Turns ReadMe's `x-readme.code-samples` into code samples. */\nconst fromReadmeSamples = (samples: XReadmeCodeSample[] | undefined): XCodeSample[] =>\n (samples ?? []).map((sample) => ({\n lang: sample.language,\n source: sample.code,\n ...(sample.name ? { label: sample.name } : {}),\n }))\n\n/** Picker group label for samples generated by an SDK provider (Scalar, Stainless, …). */\nconst SDK_GROUP_LABEL = 'SDK'\n\n/** Picker group label for generic or docs-platform samples (the standard `x-codeSamples` family, ReadMe, …). */\nexport const CODE_EXAMPLES_GROUP_LABEL = 'Code Examples'\n\ntype CustomCodeSampleGroupLabel = typeof SDK_GROUP_LABEL | typeof CODE_EXAMPLES_GROUP_LABEL\n\ntype CustomCodeSamples = {\n /**\n * Group label for the code sample picker.\n *\n * Samples that come from an SDK provider extension (`x-scalar-examples`,\n * `x-stainless-snippets`, `x-stainless-examples`) surface under \"SDK\". Generic\n * or docs-platform samples (`x-readme`, the `x-codeSamples` family) surface\n * under \"Code Examples\".\n */\n label: CustomCodeSampleGroupLabel\n /** The custom code samples, in picker order. */\n samples: XCodeSample[]\n}\n\n/**\n * Grabs any custom code samples from the operation.\n *\n * Several tools write code samples into OpenAPI under different extensions. When\n * more than one is present we use the highest-priority source only, rather than\n * showing duplicates from every tool. Priority, highest first:\n *\n * 1. `x-scalar-examples` (SDK)\n * 2. `x-stainless-snippets` (SDK, overrides `x-stainless-examples`)\n * 3. `x-stainless-examples` (SDK)\n * 4. `x-readme.code-samples` (Code Examples)\n * 5. `x-codeSamples` / `x-code-samples` / `x-custom-examples` (Code Examples)\n *\n * The winning source also determines the picker group label: SDK-provider\n * extensions surface under \"SDK\", everything else under \"Code Examples\".\n *\n * Note that Speakeasy does not have its own extension — it writes into the\n * standard `x-codeSamples`, so its snippets surface under \"Code Examples\".\n *\n * @param operation - The operation to get the custom code samples from\n * @returns The picker group label and the custom code samples which exist in the operation\n */\nexport const getCustomCodeSamples = (operation: OperationObject): CustomCodeSamples => {\n const scalarExamples = operation['x-scalar-examples'] ?? []\n if (scalarExamples.length) {\n return { label: SDK_GROUP_LABEL, samples: scalarExamples }\n }\n\n const stainlessSnippets = fromSnippetMap(operation['x-stainless-snippets'])\n if (stainlessSnippets.length) {\n return { label: SDK_GROUP_LABEL, samples: stainlessSnippets }\n }\n\n const stainlessExamples = fromLanguageExamples(operation['x-stainless-examples'])\n if (stainlessExamples.length) {\n return { label: SDK_GROUP_LABEL, samples: stainlessExamples }\n }\n\n const readmeSamples = fromReadmeSamples(operation['x-readme']?.['code-samples'])\n if (readmeSamples.length) {\n return { label: CODE_EXAMPLES_GROUP_LABEL, samples: readmeSamples }\n }\n\n const customCodeKeys = ['x-custom-examples', 'x-codeSamples', 'x-code-samples'] as const\n return { label: CODE_EXAMPLES_GROUP_LABEL, samples: customCodeKeys.flatMap((key) => operation[key] ?? []) }\n}\n"],"mappings":";AAQA,IAAM,KAAkB,GAA8C,MACpE,OAAO,QAAQ,KAAY,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAM,QAAa;CAAE;CAAM;CAAQ,GAAI,IAAQ,EAAE,SAAM,IAAI,CAAC;AAAG,EAAE,GASlG,KAAwB,MACvB,KAIG,MAAM,QAAQ,CAAQ,IAAI,IAAW,CAAC,CAAQ,EAAA,CAAG,SAAS,MAChE,EAAe,EAAQ,SAAS,EAAQ,KAAK,CAC/C,IALS,CAAC,GASN,KAAqB,OACxB,KAAW,CAAC,EAAA,CAAG,KAAK,OAAY;CAC/B,MAAM,EAAO;CACb,QAAQ,EAAO;CACf,GAAI,EAAO,OAAO,EAAE,OAAO,EAAO,KAAK,IAAI,CAAC;AAC9C,EAAE,GAGE,IAAkB,OAGX,IAA4B,iBAwC5B,KAAwB,MAAkD;CACrF,IAAM,IAAiB,EAAU,wBAAwB,CAAC;CAC1D,IAAI,EAAe,QACjB,OAAO;EAAE,OAAO;EAAiB,SAAS;CAAe;CAG3D,IAAM,IAAoB,EAAe,EAAU,uBAAuB;CAC1E,IAAI,EAAkB,QACpB,OAAO;EAAE,OAAO;EAAiB,SAAS;CAAkB;CAG9D,IAAM,IAAoB,EAAqB,EAAU,uBAAuB;CAChF,IAAI,EAAkB,QACpB,OAAO;EAAE,OAAO;EAAiB,SAAS;CAAkB;CAG9D,IAAM,IAAgB,EAAkB,EAAU,WAAW,GAAG,eAAe;CAM/E,OALI,EAAc,SACT;EAAE,OAAO;EAA2B,SAAS;CAAc,IAI7D;EAAE,OAAO;EAA2B,SAAS;GAD5B;GAAqB;GAAiB;EACV,CAAA,CAAe,SAAS,MAAQ,EAAU,MAAQ,CAAC,CAAC;CAAE;AAC5G"}
@@ -1 +1 @@
1
- {"version":3,"file":"get-secrets.js","names":[],"sources":["../../../src/code-example/helpers/get-secrets.ts"],"sourcesContent":["import type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport { encode } from 'js-base64'\n\n/** Extract secrets from security schemes */\nexport const getSecrets = (securitySchemes: SecuritySchemeObjectSecret[]): string[] =>\n securitySchemes\n .flatMap((scheme) => {\n if (scheme.type === 'apiKey') {\n return scheme['x-scalar-secret-token']\n }\n if (scheme?.type === 'http') {\n return [\n scheme['x-scalar-secret-token'],\n scheme['x-scalar-secret-username'],\n scheme['x-scalar-secret-password'],\n encode(`${scheme['x-scalar-secret-username']}:${scheme['x-scalar-secret-password']}`),\n ]\n }\n if (scheme.type === 'oauth2') {\n const flows = Object.values(scheme.flows)\n return flows.map((flow) => flow['x-scalar-secret-token'])\n }\n\n return []\n })\n .filter(Boolean)\n"],"mappings":";;AAIA,IAAa,KAAc,MACzB,EACG,SAAS,MACJ,EAAO,SAAS,WACX,EAAO,2BAEZ,GAAQ,SAAS,SACZ;CACL,EAAO;CACP,EAAO;CACP,EAAO;CACP,EAAO,GAAG,EAAO,4BAA4B,GAAG,EAAO,8BAA8B;CACtF,GAEC,EAAO,SAAS,WACJ,OAAO,OAAO,EAAO,MAAM,CAC5B,KAAK,MAAS,EAAK,yBAAyB,GAGpD,EAAE,CACT,CACD,OAAO,QAAQ"}
1
+ {"version":3,"file":"get-secrets.js","names":[],"sources":["../../../src/code-example/helpers/get-secrets.ts"],"sourcesContent":["import type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport { encode } from 'js-base64'\n\n/** Extract secrets from security schemes */\nexport const getSecrets = (securitySchemes: SecuritySchemeObjectSecret[]): string[] =>\n securitySchemes\n .flatMap((scheme) => {\n if (scheme.type === 'apiKey') {\n return scheme['x-scalar-secret-token']\n }\n if (scheme?.type === 'http') {\n return [\n scheme['x-scalar-secret-token'],\n scheme['x-scalar-secret-username'],\n scheme['x-scalar-secret-password'],\n encode(`${scheme['x-scalar-secret-username']}:${scheme['x-scalar-secret-password']}`),\n ]\n }\n if (scheme.type === 'oauth2') {\n const flows = Object.values(scheme.flows)\n return flows.map((flow) => flow['x-scalar-secret-token'])\n }\n\n return []\n })\n .filter(Boolean)\n"],"mappings":";;AAIA,IAAa,KAAc,MACzB,EACG,SAAS,MACJ,EAAO,SAAS,WACX,EAAO,2BAEZ,GAAQ,SAAS,SACZ;CACL,EAAO;CACP,EAAO;CACP,EAAO;CACP,EAAO,GAAG,EAAO,4BAA4B,GAAG,EAAO,6BAA6B;AACtF,IAEE,EAAO,SAAS,WACJ,OAAO,OAAO,EAAO,KAC5B,CAAA,CAAM,KAAK,MAAS,EAAK,wBAAwB,IAGnD,CAAC,CACT,CAAC,CACD,OAAO,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"get-snippet.js","names":[],"sources":["../../../src/code-example/helpers/get-snippet.ts"],"sourcesContent":["import type { ErrorResponse } from '@scalar/helpers/errors/normalize-error'\nimport { type ClientId, type TargetId, snippetz } from '@scalar/snippetz'\nimport type { Request as HarRequest } from 'har-format'\n\n/** Key used to hack around the invalid urls */\nconst INVALID_URLS_PREFIX = 'ws://replace.me'\n\n/**\n * Returns a code example for given operation\n */\nexport const getSnippet = <T extends TargetId>(\n target: T | 'javascript',\n client: ClientId<T>,\n harRequest: HarRequest,\n): ErrorResponse<string> => {\n try {\n if (!harRequest.url) {\n return [new Error('Please enter a URL to see a code snippet'), null]\n }\n\n const separator = harRequest.url.startsWith('/') ? '' : '/'\n\n // Hack to get around invalid URLS until we update the snippets lib\n try {\n new URL(harRequest.url)\n } catch {\n harRequest.url = `${INVALID_URLS_PREFIX}${separator}${harRequest.url}`\n }\n\n // Ensure we have valid JSON\n if (harRequest.postData?.mimeType === 'application/json') {\n try {\n JSON.parse(harRequest.postData.text || '{}')\n } catch (error) {\n console.error('[getSnippet] Invalid JSON body', error)\n return [new Error('Invalid JSON body'), null]\n }\n }\n // TODO: Fix this, use js (instead of javascript) everywhere\n const snippetzTargetKey = target.replace('javascript', 'js') as TargetId\n\n if (snippetz().hasPlugin(snippetzTargetKey, client)) {\n const payload = snippetz().print(snippetzTargetKey, client as ClientId<TargetId>, harRequest)\n if (!payload) {\n return [new Error('Error generating snippet'), null]\n }\n\n return [null, payload.replace(`${INVALID_URLS_PREFIX}${separator}`, '')]\n }\n } catch (error) {\n console.error('[getSnippet] Error generating snippet', error)\n return [new Error('Error generating snippet'), null]\n }\n\n return [new Error('No snippet found'), null]\n}\n"],"mappings":";;AAKA,IAAM,IAAsB,mBAKf,KACX,GACA,GACA,MAC0B;AAC1B,KAAI;AACF,MAAI,CAAC,EAAW,IACd,QAAO,CAAC,gBAAI,MAAM,2CAA2C,EAAE,KAAK;EAGtE,IAAM,IAAY,EAAW,IAAI,WAAW,IAAI,GAAG,KAAK;AAGxD,MAAI;AACF,OAAI,IAAI,EAAW,IAAI;UACjB;AACN,KAAW,MAAM,GAAG,IAAsB,IAAY,EAAW;;AAInE,MAAI,EAAW,UAAU,aAAa,mBACpC,KAAI;AACF,QAAK,MAAM,EAAW,SAAS,QAAQ,KAAK;WACrC,GAAO;AAEd,UADA,QAAQ,MAAM,kCAAkC,EAAM,EAC/C,CAAC,gBAAI,MAAM,oBAAoB,EAAE,KAAK;;EAIjD,IAAM,IAAoB,EAAO,QAAQ,cAAc,KAAK;AAE5D,MAAI,GAAU,CAAC,UAAU,GAAmB,EAAO,EAAE;GACnD,IAAM,IAAU,GAAU,CAAC,MAAM,GAAmB,GAA8B,EAAW;AAK7F,UAJK,IAIE,CAAC,MAAM,EAAQ,QAAQ,GAAG,IAAsB,KAAa,GAAG,CAAC,GAH/D,CAAC,gBAAI,MAAM,2BAA2B,EAAE,KAAK;;UAKjD,GAAO;AAEd,SADA,QAAQ,MAAM,yCAAyC,EAAM,EACtD,CAAC,gBAAI,MAAM,2BAA2B,EAAE,KAAK;;AAGtD,QAAO,CAAC,gBAAI,MAAM,mBAAmB,EAAE,KAAK"}
1
+ {"version":3,"file":"get-snippet.js","names":[],"sources":["../../../src/code-example/helpers/get-snippet.ts"],"sourcesContent":["import type { ErrorResponse } from '@scalar/helpers/errors/normalize-error'\nimport { type ClientId, type TargetId, snippetz } from '@scalar/snippetz'\nimport type { Request as HarRequest } from 'har-format'\n\n/** Key used to hack around the invalid urls */\nconst INVALID_URLS_PREFIX = 'ws://replace.me'\n\n/**\n * Returns a code example for given operation\n */\nexport const getSnippet = <T extends TargetId>(\n target: T | 'javascript',\n client: ClientId<T>,\n harRequest: HarRequest,\n): ErrorResponse<string> => {\n try {\n if (!harRequest.url) {\n return [new Error('Please enter a URL to see a code snippet'), null]\n }\n\n const separator = harRequest.url.startsWith('/') ? '' : '/'\n\n // Hack to get around invalid URLS until we update the snippets lib\n try {\n new URL(harRequest.url)\n } catch {\n harRequest.url = `${INVALID_URLS_PREFIX}${separator}${harRequest.url}`\n }\n\n // Ensure we have valid JSON\n if (harRequest.postData?.mimeType === 'application/json') {\n try {\n JSON.parse(harRequest.postData.text || '{}')\n } catch (error) {\n console.error('[getSnippet] Invalid JSON body', error)\n return [new Error('Invalid JSON body'), null]\n }\n }\n // TODO: Fix this, use js (instead of javascript) everywhere\n const snippetzTargetKey = target.replace('javascript', 'js') as TargetId\n\n if (snippetz().hasPlugin(snippetzTargetKey, client)) {\n const payload = snippetz().print(snippetzTargetKey, client as ClientId<TargetId>, harRequest)\n if (!payload) {\n return [new Error('Error generating snippet'), null]\n }\n\n return [null, payload.replace(`${INVALID_URLS_PREFIX}${separator}`, '')]\n }\n } catch (error) {\n console.error('[getSnippet] Error generating snippet', error)\n return [new Error('Error generating snippet'), null]\n }\n\n return [new Error('No snippet found'), null]\n}\n"],"mappings":";;AAKA,IAAM,IAAsB,mBAKf,KACX,GACA,GACA,MAC0B;CAC1B,IAAI;EACF,IAAI,CAAC,EAAW,KACd,OAAO,CAAC,gBAAI,MAAM,0CAA0C,GAAG,IAAI;EAGrE,IAAM,IAAY,EAAW,IAAI,WAAW,GAAG,IAAI,KAAK;EAGxD,IAAI;GACF,IAAI,IAAI,EAAW,GAAG;EACxB,QAAQ;GACN,EAAW,MAAM,GAAG,IAAsB,IAAY,EAAW;EACnE;EAGA,IAAI,EAAW,UAAU,aAAa,oBACpC,IAAI;GACF,KAAK,MAAM,EAAW,SAAS,QAAQ,IAAI;EAC7C,SAAS,GAAO;GAEd,OADA,QAAQ,MAAM,kCAAkC,CAAK,GAC9C,CAAC,gBAAI,MAAM,mBAAmB,GAAG,IAAI;EAC9C;EAGF,IAAM,IAAoB,EAAO,QAAQ,cAAc,IAAI;EAE3D,IAAI,EAAS,CAAC,CAAC,UAAU,GAAmB,CAAM,GAAG;GACnD,IAAM,IAAU,EAAS,CAAC,CAAC,MAAM,GAAmB,GAA8B,CAAU;GAK5F,OAJK,IAIE,CAAC,MAAM,EAAQ,QAAQ,GAAG,IAAsB,KAAa,EAAE,CAAC,IAH9D,CAAC,gBAAI,MAAM,0BAA0B,GAAG,IAAI;EAIvD;CACF,SAAS,GAAO;EAEd,OADA,QAAQ,MAAM,yCAAyC,CAAK,GACrD,CAAC,gBAAI,MAAM,0BAA0B,GAAG,IAAI;CACrD;CAEA,OAAO,CAAC,gBAAI,MAAM,kBAAkB,GAAG,IAAI;AAC7C"}
@@ -1 +1 @@
1
- {"version":3,"file":"operation-to-har.js","names":[],"sources":["../../../../src/code-example/helpers/operation-to-har/operation-to-har.ts"],"sourcesContent":["import { isElectron } from '@scalar/helpers/general/is-electron'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport {\n type SecuritySchemeObjectSecret,\n filterGlobalCookie,\n getDefaultHeaders,\n restoreConventionalDefaultHeaderNames,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type { OperationObject, ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport type { Request as HarRequest } from 'har-format'\n\nimport { APP_VERSION } from '@/constants'\n\nimport { processBody } from './process-body'\nimport { processParameters } from './process-parameters'\nimport { processSecuritySchemes } from './process-security-schemes'\nimport { processServerUrl } from './process-server-url'\n\nexport type OperationToHarProps = {\n /** OpenAPI Operation object */\n operation: OperationObject\n /** HTTP method of the operation */\n method: HttpMethod\n /** Path of the operation */\n path: string\n /**\n * Name of the currently selected operation example\n *\n * Applies to both the body and the parameters\n */\n example?: string\n /**\n * Content type of the operation\n *\n * Applies to both the body and the parameters (if applicable)\n * @defaults to the first content type in the MediaTypeObject\n */\n contentType?: string\n /** OpenAPI Server object */\n server?: ServerObject | null\n /** OpenAPI SecurityScheme objects which are applicable to the operation */\n securitySchemes?: SecuritySchemeObjectSecret[]\n /** Workspace + document cookies */\n globalCookies?: XScalarCookie[]\n /**\n * Whether to include default headers (e.g., Accept, Content-Type) automatically.\n * If false, default headers will be omitted from the HAR request.\n * @default true\n */\n includeDefaultHeaders?: boolean\n /**\n * Selected oneOf/anyOf variants for nested request body example generation\n * (e.g. from the schema dropdowns in the API reference).\n */\n requestBodyCompositionSelection?: Record<string, number>\n /**\n * Whether to disable parameters by default.\n * @default false\n */\n defaultDisabledParameters?: boolean\n}\n\n/**\n * Converts an OpenAPI Operation to a HarRequest format for generating HTTP request snippets.\n *\n * This function transforms OpenAPI 3.1 operation objects into HAR (HTTP Archive) format requests,\n * which can be used to generate code snippets for various programming languages and HTTP clients.\n *\n * The conversion handles:\n * - Server URL processing and path parameter substitution\n * - Query parameter formatting based on OpenAPI parameter styles\n * - Request body processing with content type handling\n * - Security scheme integration (API keys, etc.)\n *\n * The resulting HarRequest object follows the HAR specification and includes:\n * - HTTP method and URL\n * - Headers and query parameters\n * - Request body (if present)\n * - Cookie information\n * - Size calculations for headers and body\n *\n * @see https://w3c.github.io/web-performance/specs/HAR/Overview.html\n * @see https://spec.openapis.org/oas/v3.1.0#operation-object\n */\nexport const operationToHar = ({\n includeDefaultHeaders = false,\n operation,\n contentType,\n method,\n path,\n server = null,\n example,\n securitySchemes,\n globalCookies,\n requestBodyCompositionSelection,\n defaultDisabledParameters = false,\n}: OperationToHarProps): HarRequest => {\n const defaultHeaders = includeDefaultHeaders\n ? getDefaultHeaders({\n method,\n operation,\n exampleName: example ?? 'default',\n hideDisabledHeaders: true,\n hideOverriddenHeaders: true,\n options: { isElectron: isElectron(), appVersion: APP_VERSION },\n })\n : {}\n const defaultHeadersWithConventionalNames = restoreConventionalDefaultHeaderNames(defaultHeaders)\n\n const disabledGlobalCookies =\n operation['x-scalar-disable-parameters']?.['global-cookies']?.[example ?? 'default'] ?? {}\n\n const serverUrl = processServerUrl(server, path)\n\n // Initialize the HAR request with basic properties\n const harRequest: HarRequest = {\n method,\n url: serverUrl,\n headers: Object.entries(defaultHeadersWithConventionalNames).map(([name, value]) => ({ name, value })),\n queryString: [],\n postData: undefined,\n httpVersion: 'HTTP/1.1',\n cookies: [],\n headersSize: -1,\n bodySize: -1,\n }\n\n // Handle parameters\n if (operation.parameters) {\n const { url, headers, queryString, cookies } = processParameters({\n harRequest,\n parameters: operation.parameters,\n example,\n defaultDisabled: defaultDisabledParameters,\n })\n\n // Correctly filter the global cookies by the processed url\n const filteredGlobalCookies =\n globalCookies\n ?.filter((cookie) => filterGlobalCookie({ cookie, url, disabledGlobalCookies }))\n ?.map((cookie) => ({ name: cookie.name, value: cookie.value })) ?? []\n\n harRequest.url = url\n harRequest.headers = headers\n harRequest.queryString = queryString\n harRequest.cookies = [...filteredGlobalCookies, ...cookies]\n }\n\n const body = getResolvedRef(operation.requestBody)\n\n // Handle request body\n if (body?.content) {\n const postData = processBody({\n requestBody: body,\n contentType,\n example,\n requestBodyCompositionSelection,\n })\n\n if (postData) {\n harRequest.postData = postData\n harRequest.bodySize = postData.text?.length ?? -1\n\n // Add or update Content-Type header\n if (postData.mimeType) {\n const existingContentTypeHeader = harRequest.headers.find(\n (header) => header.name.toLowerCase() === 'content-type',\n )\n // Update existing header if it has an empty value\n if (existingContentTypeHeader && !existingContentTypeHeader.value) {\n existingContentTypeHeader.value = postData.mimeType\n }\n // Add new header if none exists\n else if (!existingContentTypeHeader) {\n harRequest.headers.push({\n name: 'Content-Type',\n value: postData.mimeType,\n })\n }\n }\n }\n }\n\n // Handle security schemes\n if (securitySchemes) {\n const { headers, queryString, cookies } = processSecuritySchemes(securitySchemes)\n harRequest.headers.push(...headers)\n harRequest.queryString.push(...queryString)\n harRequest.cookies.push(...cookies)\n }\n\n // Calculate headers size without allocating a large joined string\n let headersSize = 0\n for (const h of harRequest.headers) {\n // name + \": \" + value + \"\\r\\n\"\n headersSize += (h.name?.length ?? 0) + 2 + (h.value?.length ?? 0) + 2\n }\n harRequest.headersSize = headersSize\n\n return harRequest\n}\n"],"mappings":";;;;;;;;;AAsFA,IAAa,KAAkB,EAC7B,2BAAwB,IACxB,cACA,gBACA,WACA,SACA,YAAS,MACT,YACA,oBACA,kBACA,oCACA,+BAA4B,SACS;CAWrC,IAAM,IAAsC,EAVrB,IACnB,EAAkB;EAChB;EACA;EACA,aAAa,KAAW;EACxB,qBAAqB;EACrB,uBAAuB;EACvB,SAAS;GAAE,YAAY,GAAY;GAAE,YAAY;GAAa;EAC/D,CAAC,GACF,EAAE,CAC2F,EAE3F,IACJ,EAAU,iCAAiC,oBAAoB,KAAW,cAAc,EAAE,EAKtF,IAAyB;EAC7B;EACA,KALgB,EAAiB,GAAQ,EAAK;EAM9C,SAAS,OAAO,QAAQ,EAAoC,CAAC,KAAK,CAAC,GAAM,QAAY;GAAE;GAAM;GAAO,EAAE;EACtG,aAAa,EAAE;EACf,UAAU,KAAA;EACV,aAAa;EACb,SAAS,EAAE;EACX,aAAa;EACb,UAAU;EACX;AAGD,KAAI,EAAU,YAAY;EACxB,IAAM,EAAE,QAAK,YAAS,gBAAa,eAAY,EAAkB;GAC/D;GACA,YAAY,EAAU;GACtB;GACA,iBAAiB;GAClB,CAAC,EAGI,IACJ,GACI,QAAQ,MAAW,EAAmB;GAAE;GAAQ;GAAK;GAAuB,CAAC,CAAC,EAC9E,KAAK,OAAY;GAAE,MAAM,EAAO;GAAM,OAAO,EAAO;GAAO,EAAE,IAAI,EAAE;AAKzE,EAHA,EAAW,MAAM,GACjB,EAAW,UAAU,GACrB,EAAW,cAAc,GACzB,EAAW,UAAU,CAAC,GAAG,GAAuB,GAAG,EAAQ;;CAG7D,IAAM,IAAO,EAAe,EAAU,YAAY;AAGlD,KAAI,GAAM,SAAS;EACjB,IAAM,IAAW,EAAY;GAC3B,aAAa;GACb;GACA;GACA;GACD,CAAC;AAEF,MAAI,MACF,EAAW,WAAW,GACtB,EAAW,WAAW,EAAS,MAAM,UAAU,IAG3C,EAAS,WAAU;GACrB,IAAM,IAA4B,EAAW,QAAQ,MAClD,MAAW,EAAO,KAAK,aAAa,KAAK,eAC3C;AAED,GAAI,KAA6B,CAAC,EAA0B,QAC1D,EAA0B,QAAQ,EAAS,WAGnC,KACR,EAAW,QAAQ,KAAK;IACtB,MAAM;IACN,OAAO,EAAS;IACjB,CAAC;;;AAOV,KAAI,GAAiB;EACnB,IAAM,EAAE,YAAS,gBAAa,eAAY,EAAuB,EAAgB;AAGjF,EAFA,EAAW,QAAQ,KAAK,GAAG,EAAQ,EACnC,EAAW,YAAY,KAAK,GAAG,EAAY,EAC3C,EAAW,QAAQ,KAAK,GAAG,EAAQ;;CAIrC,IAAI,IAAc;AAClB,MAAK,IAAM,KAAK,EAAW,QAEzB,OAAgB,EAAE,MAAM,UAAU,KAAK,KAAK,EAAE,OAAO,UAAU,KAAK;AAItE,QAFA,EAAW,cAAc,GAElB"}
1
+ {"version":3,"file":"operation-to-har.js","names":[],"sources":["../../../../src/code-example/helpers/operation-to-har/operation-to-har.ts"],"sourcesContent":["import { isElectron } from '@scalar/helpers/general/is-electron'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport {\n type SecuritySchemeObjectSecret,\n filterGlobalCookie,\n getDefaultHeaders,\n restoreConventionalDefaultHeaderNames,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type { OperationObject, ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport type { Request as HarRequest } from 'har-format'\n\nimport { APP_VERSION } from '@/constants'\n\nimport { processBody } from './process-body'\nimport { processParameters } from './process-parameters'\nimport { processSecuritySchemes } from './process-security-schemes'\nimport { processServerUrl } from './process-server-url'\n\nexport type OperationToHarProps = {\n /** OpenAPI Operation object */\n operation: OperationObject\n /** HTTP method of the operation */\n method: HttpMethod\n /** Path of the operation */\n path: string\n /**\n * Name of the currently selected operation example\n *\n * Applies to both the body and the parameters\n */\n example?: string\n /**\n * Content type of the operation\n *\n * Applies to both the body and the parameters (if applicable)\n * @defaults to the first content type in the MediaTypeObject\n */\n contentType?: string\n /** OpenAPI Server object */\n server?: ServerObject | null\n /** OpenAPI SecurityScheme objects which are applicable to the operation */\n securitySchemes?: SecuritySchemeObjectSecret[]\n /** Workspace + document cookies */\n globalCookies?: XScalarCookie[]\n /**\n * Whether to include default headers (e.g., Accept, Content-Type) automatically.\n * If false, default headers will be omitted from the HAR request.\n * @default true\n */\n includeDefaultHeaders?: boolean\n /**\n * Selected oneOf/anyOf variants for nested request body example generation\n * (e.g. from the schema dropdowns in the API reference).\n */\n requestBodyCompositionSelection?: Record<string, number>\n /**\n * Whether to disable parameters by default.\n * @default false\n */\n defaultDisabledParameters?: boolean\n}\n\n/**\n * Converts an OpenAPI Operation to a HarRequest format for generating HTTP request snippets.\n *\n * This function transforms OpenAPI 3.1 operation objects into HAR (HTTP Archive) format requests,\n * which can be used to generate code snippets for various programming languages and HTTP clients.\n *\n * The conversion handles:\n * - Server URL processing and path parameter substitution\n * - Query parameter formatting based on OpenAPI parameter styles\n * - Request body processing with content type handling\n * - Security scheme integration (API keys, etc.)\n *\n * The resulting HarRequest object follows the HAR specification and includes:\n * - HTTP method and URL\n * - Headers and query parameters\n * - Request body (if present)\n * - Cookie information\n * - Size calculations for headers and body\n *\n * @see https://w3c.github.io/web-performance/specs/HAR/Overview.html\n * @see https://spec.openapis.org/oas/v3.1.0#operation-object\n */\nexport const operationToHar = ({\n includeDefaultHeaders = false,\n operation,\n contentType,\n method,\n path,\n server = null,\n example,\n securitySchemes,\n globalCookies,\n requestBodyCompositionSelection,\n defaultDisabledParameters = false,\n}: OperationToHarProps): HarRequest => {\n const defaultHeaders = includeDefaultHeaders\n ? getDefaultHeaders({\n method,\n operation,\n exampleName: example ?? 'default',\n hideDisabledHeaders: true,\n hideOverriddenHeaders: true,\n options: { isElectron: isElectron(), appVersion: APP_VERSION },\n })\n : {}\n const defaultHeadersWithConventionalNames = restoreConventionalDefaultHeaderNames(defaultHeaders)\n\n const disabledGlobalCookies =\n operation['x-scalar-disable-parameters']?.['global-cookies']?.[example ?? 'default'] ?? {}\n\n const serverUrl = processServerUrl(server, path)\n\n // Initialize the HAR request with basic properties\n const harRequest: HarRequest = {\n method,\n url: serverUrl,\n headers: Object.entries(defaultHeadersWithConventionalNames).map(([name, value]) => ({ name, value })),\n queryString: [],\n postData: undefined,\n httpVersion: 'HTTP/1.1',\n cookies: [],\n headersSize: -1,\n bodySize: -1,\n }\n\n // Handle parameters\n if (operation.parameters) {\n const { url, headers, queryString, cookies } = processParameters({\n harRequest,\n parameters: operation.parameters,\n example,\n defaultDisabled: defaultDisabledParameters,\n })\n\n // Correctly filter the global cookies by the processed url\n const filteredGlobalCookies =\n globalCookies\n ?.filter((cookie) => filterGlobalCookie({ cookie, url, disabledGlobalCookies }))\n ?.map((cookie) => ({ name: cookie.name, value: cookie.value })) ?? []\n\n harRequest.url = url\n harRequest.headers = headers\n harRequest.queryString = queryString\n harRequest.cookies = [...filteredGlobalCookies, ...cookies]\n }\n\n const body = getResolvedRef(operation.requestBody)\n\n // Handle request body\n if (body?.content) {\n const postData = processBody({\n requestBody: body,\n contentType,\n example,\n requestBodyCompositionSelection,\n })\n\n if (postData) {\n harRequest.postData = postData\n harRequest.bodySize = postData.text?.length ?? -1\n\n // Add or update Content-Type header\n if (postData.mimeType) {\n const existingContentTypeHeader = harRequest.headers.find(\n (header) => header.name.toLowerCase() === 'content-type',\n )\n // Update existing header if it has an empty value\n if (existingContentTypeHeader && !existingContentTypeHeader.value) {\n existingContentTypeHeader.value = postData.mimeType\n }\n // Add new header if none exists\n else if (!existingContentTypeHeader) {\n harRequest.headers.push({\n name: 'Content-Type',\n value: postData.mimeType,\n })\n }\n }\n }\n }\n\n // Handle security schemes\n if (securitySchemes) {\n const { headers, queryString, cookies } = processSecuritySchemes(securitySchemes)\n harRequest.headers.push(...headers)\n harRequest.queryString.push(...queryString)\n harRequest.cookies.push(...cookies)\n }\n\n // Calculate headers size without allocating a large joined string\n let headersSize = 0\n for (const h of harRequest.headers) {\n // name + \": \" + value + \"\\r\\n\"\n headersSize += (h.name?.length ?? 0) + 2 + (h.value?.length ?? 0) + 2\n }\n harRequest.headersSize = headersSize\n\n return harRequest\n}\n"],"mappings":";;;;;;;;;AAsFA,IAAa,KAAkB,EAC7B,2BAAwB,IACxB,cACA,gBACA,WACA,SACA,YAAS,MACT,YACA,oBACA,kBACA,oCACA,+BAA4B,SACS;CAWrC,IAAM,IAAsC,EAVrB,IACnB,EAAkB;EAChB;EACA;EACA,aAAa,KAAW;EACxB,qBAAqB;EACrB,uBAAuB;EACvB,SAAS;GAAE,YAAY,EAAW;GAAG,YAAY;EAAY;CAC/D,CAAC,IACD,CAAC,CAC2F,GAE1F,IACJ,EAAU,8BAA8B,GAAG,iBAAiB,GAAG,KAAW,cAAc,CAAC,GAKrF,IAAyB;EAC7B;EACA,KALgB,EAAiB,GAAQ,CAKpC;EACL,SAAS,OAAO,QAAQ,CAAmC,CAAC,CAAC,KAAK,CAAC,GAAM,QAAY;GAAE;GAAM;EAAM,EAAE;EACrG,aAAa,CAAC;EACd,UAAU,KAAA;EACV,aAAa;EACb,SAAS,CAAC;EACV,aAAa;EACb,UAAU;CACZ;CAGA,IAAI,EAAU,YAAY;EACxB,IAAM,EAAE,QAAK,YAAS,gBAAa,eAAY,EAAkB;GAC/D;GACA,YAAY,EAAU;GACtB;GACA,iBAAiB;EACnB,CAAC,GAGK,IACJ,GACI,QAAQ,MAAW,EAAmB;GAAE;GAAQ;GAAK;EAAsB,CAAC,CAAC,CAAC,EAC9E,KAAK,OAAY;GAAE,MAAM,EAAO;GAAM,OAAO,EAAO;EAAM,EAAE,KAAK,CAAC;EAKxE,AAHA,EAAW,MAAM,GACjB,EAAW,UAAU,GACrB,EAAW,cAAc,GACzB,EAAW,UAAU,CAAC,GAAG,GAAuB,GAAG,CAAO;CAC5D;CAEA,IAAM,IAAO,EAAe,EAAU,WAAW;CAGjD,IAAI,GAAM,SAAS;EACjB,IAAM,IAAW,EAAY;GAC3B,aAAa;GACb;GACA;GACA;EACF,CAAC;EAED,IAAI,MACF,EAAW,WAAW,GACtB,EAAW,WAAW,EAAS,MAAM,UAAU,IAG3C,EAAS,WAAU;GACrB,IAAM,IAA4B,EAAW,QAAQ,MAClD,MAAW,EAAO,KAAK,YAAY,MAAM,cAC5C;GAEA,AAAI,KAA6B,CAAC,EAA0B,QAC1D,EAA0B,QAAQ,EAAS,WAGnC,KACR,EAAW,QAAQ,KAAK;IACtB,MAAM;IACN,OAAO,EAAS;GAClB,CAAC;EAEL;CAEJ;CAGA,IAAI,GAAiB;EACnB,IAAM,EAAE,YAAS,gBAAa,eAAY,EAAuB,CAAe;EAGhF,AAFA,EAAW,QAAQ,KAAK,GAAG,CAAO,GAClC,EAAW,YAAY,KAAK,GAAG,CAAW,GAC1C,EAAW,QAAQ,KAAK,GAAG,CAAO;CACpC;CAGA,IAAI,IAAc;CAClB,KAAK,IAAM,KAAK,EAAW,SAEzB,MAAgB,EAAE,MAAM,UAAU,KAAK,KAAK,EAAE,OAAO,UAAU,KAAK;CAItE,OAFA,EAAW,cAAc,GAElB;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"process-body.js","names":[],"sources":["../../../../src/code-example/helpers/operation-to-har/process-body.ts"],"sourcesContent":["import { json2xml } from '@scalar/helpers/file/json2xml'\nimport { isObjectLike } from '@scalar/helpers/object/is-object'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { getResolvedRefDeep } from '@scalar/workspace-store/helpers/get-resolved-ref-deep'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getExample,\n getExampleFromSchema,\n serializeFormPropertyWithEncoding,\n} from '@scalar/workspace-store/request-example'\nimport type {\n MediaTypeObject,\n RequestBodyObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport type { Param, PostData } from 'har-format'\n\nimport type { OperationToHarProps } from './operation-to-har'\n\ntype ProcessBodyProps = Pick<OperationToHarProps, 'contentType' | 'example' | 'requestBodyCompositionSelection'> & {\n requestBody: RequestBodyObject\n}\n\ntype MultipartEncodingMap = MediaTypeObject['encoding']\n\n/**\n * Converts a form-data body into HAR `Param[]` entries for `multipart/form-data`\n * and `application/x-www-form-urlencoded` requests.\n *\n * Per OpenAPI 3.1.x Encoding Object, each property's serialization is governed\n * by an optional Encoding entry. When `style` / `explode` / `allowReserved` is\n * set, the value is serialized RFC6570-style and `contentType` is ignored.\n * When only `contentType` is set, the property becomes a single part with that\n * type. Otherwise spec defaults apply (object → `application/json` for multipart,\n * primitives → `text/plain`).\n *\n * @param obj - The form-data payload, either an object keyed by property name\n * or a HAR-style `{ name, value, isDisabled }[]` array.\n * @param encoding - The `encoding` map from the Media Type Object, if any.\n * Used only at the top level (`parentKey` undefined).\n * @param parentKey - When set, we are flattening a nested object inside another\n * property; encoding is ignored and keys are joined with `.` (legacy default).\n * @param isMultipart - True for `multipart/form-data`. Gates the spec defaults\n * for object/array properties that should become a single `application/json`\n * part. Urlencoded bodies skip those branches and fall through to flattening.\n */\nconst objectToFormParams = (\n obj: object | { name: string; value: unknown; isDisabled: boolean }[],\n encoding?: MultipartEncodingMap,\n parentKey?: string,\n isMultipart = false,\n): Param[] => {\n const params: Param[] = []\n\n /** Ensure we do not include disabled items */\n const entries: [string, unknown][] = Array.isArray(obj)\n ? obj.filter((item) => !item.isDisabled).map((item) => [String(item.name), item.value])\n : Object.entries(obj)\n\n for (const [key, value] of entries) {\n if (value === undefined || value === null) {\n continue\n }\n\n const partEncoding = parentKey ? undefined : encoding?.[key]\n /**\n * Per OpenAPI 3.1.1: when style, explode, or allowReserved is explicitly set on the\n * encoding entry, contentType (implicit or explicit) is ignored and the value is\n * serialized as if it were a query-style parameter.\n */\n const hasFormStyle =\n partEncoding &&\n (partEncoding.style !== undefined ||\n partEncoding.explode !== undefined ||\n partEncoding.allowReserved !== undefined)\n /**\n * Per OAS 3.1.x Encoding Object: `contentType` SHALL be ignored if the request body\n * media type is not a multipart. For `application/x-www-form-urlencoded` we still\n * honor `style`/`explode`/`allowReserved` (handled above), but a `contentType`-only\n * entry has no effect — values fall through to the dotted-key flattening default.\n */\n const explicitContentType = hasFormStyle || !isMultipart ? undefined : partEncoding?.contentType\n\n /**\n * When the encoding sets style/explode/allowReserved, serialize the value RFC6570-style\n * (bracket/exploded notation) and ignore contentType. See `serializeFormPropertyWithEncoding`\n * for the per-style rules; it returns null for primitives, Files, and arrays of Files, which\n * then fall through to the dedicated branches below. HAR represents multipart and urlencoded\n * the same way via `PostData.params`, so the resulting parts work for both.\n */\n const styleParams = parentKey ? null : serializeFormPropertyWithEncoding(key, value, partEncoding)\n if (styleParams) {\n for (const param of styleParams) {\n params.push({ name: param.key, value: param.value })\n }\n } else if (value instanceof File) {\n /**\n * File values render as `@filename` references, the conventional cURL syntax for an\n * attached file. Picked up by snippet renderers downstream (e.g. `--form 'x=@file.png'`).\n */\n const file = unpackProxyObject(value)\n params.push({\n name: key,\n value: `@${file.name}`,\n ...(explicitContentType ? { contentType: explicitContentType } : {}),\n })\n } else if (explicitContentType && typeof value === 'object') {\n /**\n * Per OAS 3.1.x Encoding Object: an explicit `encoding[key].contentType` on a\n * complex value overrides the default and emits a single part containing the value\n * JSON-stringified into that media type. Only reachable when style/explode/allowReserved\n * are unset (otherwise contentType is ignored — see the style branch above).\n */\n params.push({\n name: key,\n value: JSON.stringify(unpackProxyObject(value)),\n contentType: explicitContentType,\n })\n } else if (isMultipart && !parentKey && !hasFormStyle && typeof value === 'object' && !Array.isArray(value)) {\n /**\n * Per OpenAPI 3.x: a top-level multipart property whose value is an object (and not a File)\n * defaults to a single part encoded as application/json, rather than being flattened\n * into multiple parts with dotted keys.\n */\n params.push({\n name: key,\n value: JSON.stringify(unpackProxyObject(value)),\n contentType: 'application/json',\n })\n } else if (\n Array.isArray(value) &&\n isMultipart &&\n !parentKey &&\n !hasFormStyle &&\n value.some((item) => isObjectLike(item) && !(item instanceof File))\n ) {\n /**\n * Per OpenAPI 3.x: a top-level multipart array whose items are objects defaults to a single\n * `application/json` part containing the whole array. Serializing each item into its own part\n * would drop the enclosing array wrapper and emit a bare object (see issue #9688), so keep the\n * array intact and stringify it as one value.\n */\n params.push({\n name: key,\n value: JSON.stringify(unpackProxyObject(value)),\n contentType: 'application/json',\n })\n } else if (Array.isArray(value)) {\n for (const item of value) {\n if (item instanceof File) {\n const file = unpackProxyObject(item)\n params.push({ name: key, value: `@${file.name}` })\n } else {\n params.push({ name: key, value: String(item) })\n }\n }\n } else if (typeof value === 'object') {\n /**\n * Legacy fallback: flatten nested objects into dotted-key parts. Reached when the\n * multipart JSON-default branches above don't apply — i.e. either inside a recursive\n * call (`parentKey` set) or on `application/x-www-form-urlencoded` bodies without an\n * explicit encoding entry. Strict OAS 3.1.x would use `style: form, explode: true` as\n * the urlencoded default (inner keys become top-level params); we keep dotted keys for\n * backwards compatibility with consumers that already parse this shape.\n */\n const nestedParams = objectToFormParams(value, undefined, key)\n\n for (const param of nestedParams) {\n params.push({ name: `${key}.${param.name}`, value: param.value })\n }\n } else {\n params.push({\n name: key,\n value: String(value),\n ...(explicitContentType ? { contentType: explicitContentType } : {}),\n })\n }\n }\n\n return params\n}\n\n/**\n * Processes the request body and returns the processed data\n * Returns undefined if no example is found\n */\nexport const processBody = ({\n requestBody,\n contentType,\n example,\n requestBodyCompositionSelection,\n}: ProcessBodyProps): PostData | undefined => {\n const _contentType = contentType || Object.keys(requestBody.content)[0] || ''\n /** Empty when \"Other\" is selected so snippets do not inject `Content-Type: other`. */\n const harMimeType = _contentType === 'other' ? '' : _contentType\n const formatBinaryFile = (file: File) => {\n const unwrappedFile = unpackProxyObject(file)\n return `@${unwrappedFile.name || 'filename'}`\n }\n const encoding = requestBody.content[_contentType]?.encoding\n\n // Check if this is a form data content type\n const isFormData = _contentType === 'multipart/form-data' || _contentType === 'application/x-www-form-urlencoded'\n\n // Check if this is an XML content type\n const isXml = _contentType === 'application/xml'\n\n // Get the example value\n const _example = getExample(requestBody, example, contentType)?.value\n\n // Return the provided top level example\n if (typeof _example !== 'undefined') {\n const exampleValue = _example !== null && typeof _example === 'object' ? unpackProxyObject(_example) : _example\n\n if (isFormData && typeof exampleValue === 'object' && exampleValue !== null) {\n return {\n mimeType: harMimeType,\n params: objectToFormParams(exampleValue, encoding, undefined, _contentType === 'multipart/form-data'),\n }\n }\n\n if (isXml && typeof exampleValue === 'object' && exampleValue !== null) {\n return {\n mimeType: harMimeType,\n text: json2xml(exampleValue),\n }\n }\n\n if (exampleValue instanceof File) {\n return {\n mimeType: harMimeType,\n text: formatBinaryFile(exampleValue),\n }\n }\n\n return {\n mimeType: harMimeType,\n text: typeof exampleValue === 'string' ? exampleValue : JSON.stringify(exampleValue),\n }\n }\n\n // Try to extract examples from the schema\n const contentSchema = getResolvedRef(requestBody.content[_contentType]?.schema)\n if (typeof contentSchema !== 'undefined') {\n const resolvedContentSchema = getResolvedRefDeep(contentSchema) as SchemaObject\n const extractedExample = getExampleFromSchema(\n resolvedContentSchema,\n {\n compositionSelection: requestBodyCompositionSelection,\n mode: 'write',\n xml: isXml,\n },\n {\n schemaPath: ['requestBody'],\n },\n )\n\n if (extractedExample !== undefined) {\n if (isFormData && typeof extractedExample === 'object' && extractedExample !== null) {\n return {\n mimeType: harMimeType,\n params: objectToFormParams(extractedExample, encoding, undefined, _contentType === 'multipart/form-data'),\n }\n }\n\n if (isXml && typeof extractedExample === 'object' && extractedExample !== null) {\n return {\n mimeType: harMimeType,\n text: json2xml(extractedExample),\n }\n }\n\n return {\n mimeType: harMimeType,\n text: typeof extractedExample === 'string' ? extractedExample : JSON.stringify(extractedExample),\n }\n }\n }\n\n return undefined\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"process-body.js","names":[],"sources":["../../../../src/code-example/helpers/operation-to-har/process-body.ts"],"sourcesContent":["import { json2xml } from '@scalar/helpers/file/json2xml'\nimport { isObjectLike } from '@scalar/helpers/object/is-object'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { getResolvedRefDeep } from '@scalar/workspace-store/helpers/get-resolved-ref-deep'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getExample,\n getExampleFromSchema,\n serializeFormPropertyWithEncoding,\n} from '@scalar/workspace-store/request-example'\nimport type {\n MediaTypeObject,\n RequestBodyObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport type { Param, PostData } from 'har-format'\n\nimport type { OperationToHarProps } from './operation-to-har'\n\ntype ProcessBodyProps = Pick<OperationToHarProps, 'contentType' | 'example' | 'requestBodyCompositionSelection'> & {\n requestBody: RequestBodyObject\n}\n\ntype MultipartEncodingMap = MediaTypeObject['encoding']\n\n/**\n * Converts a form-data body into HAR `Param[]` entries for `multipart/form-data`\n * and `application/x-www-form-urlencoded` requests.\n *\n * Per OpenAPI 3.1.x Encoding Object, each property's serialization is governed\n * by an optional Encoding entry. When `style` / `explode` / `allowReserved` is\n * set, the value is serialized RFC6570-style and `contentType` is ignored.\n * When only `contentType` is set, the property becomes a single part with that\n * type. Otherwise spec defaults apply (object → `application/json` for multipart,\n * primitives → `text/plain`).\n *\n * @param obj - The form-data payload, either an object keyed by property name\n * or a HAR-style `{ name, value, isDisabled }[]` array.\n * @param encoding - The `encoding` map from the Media Type Object, if any.\n * Used only at the top level (`parentKey` undefined).\n * @param parentKey - When set, we are flattening a nested object inside another\n * property; encoding is ignored and keys are joined with `.` (legacy default).\n * @param isMultipart - True for `multipart/form-data`. Gates the spec defaults\n * for object/array properties that should become a single `application/json`\n * part. Urlencoded bodies skip those branches and fall through to flattening.\n */\nconst objectToFormParams = (\n obj: object | { name: string; value: unknown; isDisabled: boolean }[],\n encoding?: MultipartEncodingMap,\n parentKey?: string,\n isMultipart = false,\n): Param[] => {\n const params: Param[] = []\n\n /** Ensure we do not include disabled items */\n const entries: [string, unknown][] = Array.isArray(obj)\n ? obj.filter((item) => !item.isDisabled).map((item) => [String(item.name), item.value])\n : Object.entries(obj)\n\n for (const [key, value] of entries) {\n if (value === undefined || value === null) {\n continue\n }\n\n const partEncoding = parentKey ? undefined : encoding?.[key]\n /**\n * Per OpenAPI 3.1.1: when style, explode, or allowReserved is explicitly set on the\n * encoding entry, contentType (implicit or explicit) is ignored and the value is\n * serialized as if it were a query-style parameter.\n */\n const hasFormStyle =\n partEncoding &&\n (partEncoding.style !== undefined ||\n partEncoding.explode !== undefined ||\n partEncoding.allowReserved !== undefined)\n /**\n * Per OAS 3.1.x Encoding Object: `contentType` SHALL be ignored if the request body\n * media type is not a multipart. For `application/x-www-form-urlencoded` we still\n * honor `style`/`explode`/`allowReserved` (handled above), but a `contentType`-only\n * entry has no effect — values fall through to the dotted-key flattening default.\n */\n const explicitContentType = hasFormStyle || !isMultipart ? undefined : partEncoding?.contentType\n\n /**\n * When the encoding sets style/explode/allowReserved, serialize the value RFC6570-style\n * (bracket/exploded notation) and ignore contentType. See `serializeFormPropertyWithEncoding`\n * for the per-style rules; it returns null for primitives, Files, and arrays of Files, which\n * then fall through to the dedicated branches below. HAR represents multipart and urlencoded\n * the same way via `PostData.params`, so the resulting parts work for both.\n */\n const styleParams = parentKey ? null : serializeFormPropertyWithEncoding(key, value, partEncoding)\n if (styleParams) {\n for (const param of styleParams) {\n params.push({ name: param.key, value: param.value })\n }\n } else if (value instanceof File) {\n /**\n * File values render as `@filename` references, the conventional cURL syntax for an\n * attached file. Picked up by snippet renderers downstream (e.g. `--form 'x=@file.png'`).\n */\n const file = unpackProxyObject(value)\n params.push({\n name: key,\n value: `@${file.name}`,\n ...(explicitContentType ? { contentType: explicitContentType } : {}),\n })\n } else if (explicitContentType && typeof value === 'object') {\n /**\n * Per OAS 3.1.x Encoding Object: an explicit `encoding[key].contentType` on a\n * complex value overrides the default and emits a single part containing the value\n * JSON-stringified into that media type. Only reachable when style/explode/allowReserved\n * are unset (otherwise contentType is ignored — see the style branch above).\n */\n params.push({\n name: key,\n value: JSON.stringify(unpackProxyObject(value)),\n contentType: explicitContentType,\n })\n } else if (isMultipart && !parentKey && !hasFormStyle && typeof value === 'object' && !Array.isArray(value)) {\n /**\n * Per OpenAPI 3.x: a top-level multipart property whose value is an object (and not a File)\n * defaults to a single part encoded as application/json, rather than being flattened\n * into multiple parts with dotted keys.\n */\n params.push({\n name: key,\n value: JSON.stringify(unpackProxyObject(value)),\n contentType: 'application/json',\n })\n } else if (\n Array.isArray(value) &&\n isMultipart &&\n !parentKey &&\n !hasFormStyle &&\n value.some((item) => isObjectLike(item) && !(item instanceof File))\n ) {\n /**\n * Per OpenAPI 3.x: a top-level multipart array whose items are objects defaults to a single\n * `application/json` part containing the whole array. Serializing each item into its own part\n * would drop the enclosing array wrapper and emit a bare object (see issue #9688), so keep the\n * array intact and stringify it as one value.\n */\n params.push({\n name: key,\n value: JSON.stringify(unpackProxyObject(value)),\n contentType: 'application/json',\n })\n } else if (Array.isArray(value)) {\n for (const item of value) {\n if (item instanceof File) {\n const file = unpackProxyObject(item)\n params.push({ name: key, value: `@${file.name}` })\n } else {\n params.push({ name: key, value: String(item) })\n }\n }\n } else if (typeof value === 'object') {\n /**\n * Legacy fallback: flatten nested objects into dotted-key parts. Reached when the\n * multipart JSON-default branches above don't apply — i.e. either inside a recursive\n * call (`parentKey` set) or on `application/x-www-form-urlencoded` bodies without an\n * explicit encoding entry. Strict OAS 3.1.x would use `style: form, explode: true` as\n * the urlencoded default (inner keys become top-level params); we keep dotted keys for\n * backwards compatibility with consumers that already parse this shape.\n */\n const nestedParams = objectToFormParams(value, undefined, key)\n\n for (const param of nestedParams) {\n params.push({ name: `${key}.${param.name}`, value: param.value })\n }\n } else {\n params.push({\n name: key,\n value: String(value),\n ...(explicitContentType ? { contentType: explicitContentType } : {}),\n })\n }\n }\n\n return params\n}\n\n/**\n * Processes the request body and returns the processed data\n * Returns undefined if no example is found\n */\nexport const processBody = ({\n requestBody,\n contentType,\n example,\n requestBodyCompositionSelection,\n}: ProcessBodyProps): PostData | undefined => {\n const _contentType = contentType || Object.keys(requestBody.content)[0] || ''\n /** Empty when \"Other\" is selected so snippets do not inject `Content-Type: other`. */\n const harMimeType = _contentType === 'other' ? '' : _contentType\n const formatBinaryFile = (file: File) => {\n const unwrappedFile = unpackProxyObject(file)\n return `@${unwrappedFile.name || 'filename'}`\n }\n const encoding = requestBody.content[_contentType]?.encoding\n\n // Check if this is a form data content type\n const isFormData = _contentType === 'multipart/form-data' || _contentType === 'application/x-www-form-urlencoded'\n\n // Check if this is an XML content type\n const isXml = _contentType === 'application/xml'\n\n // Get the example value\n const _example = getExample(requestBody, example, contentType)?.value\n\n // Return the provided top level example\n if (typeof _example !== 'undefined') {\n const exampleValue = _example !== null && typeof _example === 'object' ? unpackProxyObject(_example) : _example\n\n if (isFormData && typeof exampleValue === 'object' && exampleValue !== null) {\n return {\n mimeType: harMimeType,\n params: objectToFormParams(exampleValue, encoding, undefined, _contentType === 'multipart/form-data'),\n }\n }\n\n if (isXml && typeof exampleValue === 'object' && exampleValue !== null) {\n return {\n mimeType: harMimeType,\n text: json2xml(exampleValue),\n }\n }\n\n if (exampleValue instanceof File) {\n return {\n mimeType: harMimeType,\n text: formatBinaryFile(exampleValue),\n }\n }\n\n return {\n mimeType: harMimeType,\n text: typeof exampleValue === 'string' ? exampleValue : JSON.stringify(exampleValue),\n }\n }\n\n // Try to extract examples from the schema\n const contentSchema = getResolvedRef(requestBody.content[_contentType]?.schema)\n if (typeof contentSchema !== 'undefined') {\n const resolvedContentSchema = getResolvedRefDeep(contentSchema) as SchemaObject\n const extractedExample = getExampleFromSchema(\n resolvedContentSchema,\n {\n compositionSelection: requestBodyCompositionSelection,\n mode: 'write',\n xml: isXml,\n },\n {\n schemaPath: ['requestBody'],\n },\n )\n\n if (extractedExample !== undefined) {\n if (isFormData && typeof extractedExample === 'object' && extractedExample !== null) {\n return {\n mimeType: harMimeType,\n params: objectToFormParams(extractedExample, encoding, undefined, _contentType === 'multipart/form-data'),\n }\n }\n\n if (isXml && typeof extractedExample === 'object' && extractedExample !== null) {\n return {\n mimeType: harMimeType,\n text: json2xml(extractedExample),\n }\n }\n\n return {\n mimeType: harMimeType,\n text: typeof extractedExample === 'string' ? extractedExample : JSON.stringify(extractedExample),\n }\n }\n }\n\n return undefined\n}\n"],"mappings":"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"}
@@ -4,7 +4,7 @@ import { deSerializeParameter as t, getExample as n, getExampleFromSchema as r,
4
4
  var f = (t) => (t ?? []).map((t) => e(t)), p = (e) => "allowReserved" in e && e.allowReserved !== void 0 ? e.allowReserved : "schema" in e && e.schema && typeof e.schema == "object" && "allowReserved" in e.schema ? e.schema.allowReserved === !0 : !1, m = (e, t) => p(t) ? e : encodeURIComponent(e), h = (e) => {
5
5
  if (e.in === "header") return {
6
6
  style: "simple",
7
- explode: "explode" in e && e.explode !== void 0 ? e.explode : !1
7
+ explode: "explode" in e && e.explode !== void 0 && e.explode
8
8
  };
9
9
  if (e.in === "cookie") return {
10
10
  style: "form",
@@ -1 +1 @@
1
- {"version":3,"file":"process-parameters.js","names":[],"sources":["../../../../src/code-example/helpers/operation-to-har/process-parameters.ts"],"sourcesContent":["import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport {\n deSerializeParameter,\n getExample,\n getExampleFromSchema,\n isParamDisabled,\n serializeContentValue,\n serializeDeepObjectStyle,\n serializeFormStyle,\n serializeFormStyleForCookies,\n serializePipeDelimitedStyle,\n serializeSimpleStyle,\n serializeSpaceDelimitedStyle,\n} from '@scalar/workspace-store/request-example'\nimport type { OperationObject, ParameterObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport type { Request as HarRequest } from 'har-format'\n\ntype ProcessedParameters = {\n url: string\n headers: HarRequest['headers']\n queryString: HarRequest['queryString']\n cookies: HarRequest['cookies']\n}\n\n/** Ensures we don't have any references in the parameters */\nconst deReferenceParams = (params: OperationObject['parameters']): ParameterObject[] =>\n (params ?? []).map((param) => getResolvedRef(param))\n\n/** Whether the parameter allows reserved characters (from param or schema). */\nconst isAllowReserved = (param: ParameterObject): boolean => {\n if ('allowReserved' in param && param.allowReserved !== undefined) {\n return param.allowReserved\n }\n if ('schema' in param && param.schema && typeof param.schema === 'object' && 'allowReserved' in param.schema) {\n return (param.schema as { allowReserved?: boolean }).allowReserved === true\n }\n return false\n}\n\n/** URL encode a value if allowReserved is not set to true. */\nconst encodeQueryValue = (value: string, param: ParameterObject): string => {\n if (isAllowReserved(param)) {\n return value\n }\n return encodeURIComponent(value)\n}\n\n/**\n * Get the style and explode values for a parameter according to OpenAPI 3.1.1 specification.\n * Handles defaults and validation for parameter location restrictions.\n */\nconst getParameterStyleAndExplode = (param: ParameterObject): { style: string; explode: boolean } => {\n // Headers only support 'simple' style\n if (param.in === 'header') {\n const explode = 'explode' in param && param.explode !== undefined ? param.explode : false\n return { style: 'simple', explode }\n }\n\n // Cookies only support 'form' style\n if (param.in === 'cookie') {\n const explode = 'explode' in param && param.explode !== undefined ? param.explode : true\n return { style: 'form', explode }\n }\n\n const defaultStyle = {\n path: 'simple',\n query: 'form',\n header: 'simple',\n cookie: 'form',\n }[param.in]\n\n // Use provided style or default based on location\n const style = 'style' in param && param.style ? param.style : defaultStyle\n\n // Determine explode value: use provided value or default based on style\n const explode = 'explode' in param && param.explode !== undefined ? param.explode : style === 'form'\n\n return { style, explode }\n}\n\n/**\n * Extract the value for a parameter from example data or schema.\n * Prioritizes example data over schema examples.\n * Returns null if the parameter is disabled so we can skip it.\n */\nconst getParameterValue = (\n param: ParameterObject,\n example: string | undefined,\n contentType: string | undefined,\n defaultDisabled: boolean,\n): unknown => {\n // Try to get value from example first\n const exampleValue = getExample(param, example, contentType)\n\n // If the parameter is disabled, return undefined so we can skip it.\n if (isParamDisabled(param, exampleValue, defaultDisabled)) {\n return undefined\n }\n\n // If the example value is set, return it.\n if (exampleValue?.value !== undefined) {\n return deSerializeParameter(exampleValue.value, param)\n }\n\n // Fall back to schema example if available\n if (!('schema' in param) || !param.schema) {\n return undefined\n }\n\n const options = param.in === 'path' ? { emptyString: `{${param.name}}` } : {}\n return getExampleFromSchema(getResolvedRef(param.schema), options)\n}\n\n/**\n * Process OpenAPI parameters and return the updated properties.\n * Handles path, query, and header parameters with various styles and explode options.\n *\n * @see https://spec.openapis.org/oas/latest.html#style-values\n */\nexport const processParameters = ({\n harRequest,\n parameters,\n example,\n defaultDisabled,\n}: {\n harRequest: HarRequest\n parameters: OperationObject['parameters']\n /** The name of the example to use */\n example?: string | undefined\n /** Whether to disable parameters by default. */\n defaultDisabled: boolean\n}): ProcessedParameters => {\n // Create copies of the arrays to avoid modifying the input\n const newHeaders = [...harRequest.headers]\n const newQueryString = [...harRequest.queryString]\n let newUrl = harRequest.url\n\n // Filter out references\n const deReferencedParams = deReferenceParams(parameters)\n\n for (const param of deReferencedParams) {\n if (!param.in || !param.name) {\n continue\n }\n\n const paramValue = getParameterValue(param, example, undefined, defaultDisabled)\n if (paramValue === undefined) {\n continue\n }\n\n const { style, explode } = getParameterStyleAndExplode(param)\n\n switch (param.in) {\n case 'path': {\n newUrl = processPathParameters(newUrl, param, paramValue, style, explode)\n break\n }\n\n case 'query': {\n // Content type parameters should be serialized according to the parameter's own content type\n if ('content' in param && param.content) {\n // We grab the first for now but eventually we should support selecting the content type per parameter\n const paramContentType = Object.keys(param.content)[0] ?? 'application/json'\n const serializedValue = serializeContentValue(paramValue, paramContentType)\n newQueryString.push({ name: param.name, value: encodeQueryValue(serializedValue, param) })\n break\n }\n\n // Handle query parameters\n switch (style) {\n case 'form': {\n const serialized = serializeFormStyle(paramValue, explode)\n\n // If serialized is an array of key-value pairs (exploded object or array)\n if (Array.isArray(serialized)) {\n for (const entry of serialized) {\n const key = entry.key || param.name\n newQueryString.push({ name: key, value: encodeQueryValue(String(entry.value), param) })\n }\n }\n // Otherwise, convert to string\n else {\n newQueryString.push({ name: param.name, value: encodeQueryValue(String(serialized), param) })\n }\n break\n }\n case 'spaceDelimited': {\n const serialized = serializeSpaceDelimitedStyle(paramValue)\n newQueryString.push({ name: param.name, value: encodeQueryValue(serialized, param) })\n break\n }\n case 'pipeDelimited': {\n const serialized = serializePipeDelimitedStyle(paramValue)\n newQueryString.push({ name: param.name, value: encodeQueryValue(serialized, param) })\n break\n }\n case 'deepObject': {\n // OAS marks deepObject-on-array and deepObject+explode:false as undefined.\n // Mirror process-body: fall back to form/explode:true for arrays and always\n // invoke the serializer for objects so authors get useful output instead of\n // a silently-dropped parameter.\n if (Array.isArray(paramValue)) {\n const serialized = serializeFormStyle(paramValue, true)\n if (Array.isArray(serialized)) {\n for (const entry of serialized) {\n const key = entry.key || param.name\n newQueryString.push({ name: key, value: encodeQueryValue(String(entry.value), param) })\n }\n } else {\n newQueryString.push({ name: param.name, value: encodeQueryValue(String(serialized), param) })\n }\n } else {\n const entries = serializeDeepObjectStyle(param.name, paramValue)\n for (const entry of entries) {\n newQueryString.push({ name: entry.key, value: encodeQueryValue(entry.value, param) })\n }\n }\n break\n }\n\n // Default to form style\n default:\n newQueryString.push({ name: param.name, value: encodeQueryValue(String(paramValue), param) })\n }\n break\n }\n\n // Headers only support 'simple' style according to OpenAPI 3.1.1\n // For arrays, simple style always produces comma-separated values regardless of explode\n // The explode parameter only affects object serialization\n case 'header': {\n const serialized = serializeSimpleStyle(paramValue, explode)\n newHeaders.push({ name: param.name, value: String(serialized) })\n break\n }\n\n // Cookies only support 'form' style according to OpenAPI 3.1.1\n case 'cookie': {\n const serialized = serializeFormStyleForCookies(paramValue, explode)\n\n // If serialized is an array of key-value pairs (exploded object or array)\n if (Array.isArray(serialized)) {\n for (const entry of serialized) {\n const key = entry.key || param.name\n const value = entry.value === null ? 'null' : String(entry.value)\n harRequest.cookies.push({ name: key, value })\n }\n }\n // Otherwise, convert to string\n else {\n const value = serialized === null ? 'null' : String(serialized)\n harRequest.cookies.push({ name: param.name, value })\n }\n break\n }\n }\n }\n\n return {\n url: newUrl,\n headers: newHeaders,\n queryString: newQueryString,\n cookies: harRequest.cookies,\n }\n}\n\n/**\n * Process path parameters according to OpenAPI specification.\n * Handles matrix, label, and simple styles with explode options.\n *\n * @param url - The URL to process\n * @param param - The parameter object\n * @param paramValue - The value of the parameter\n * @param style - The style of the parameter (matrix, label, simple)\n * @param explode - Whether to explode the parameter\n * @returns The updated URL with processed path parameters\n */\nconst processPathParameters = (\n url: string,\n param: ParameterObject,\n paramValue: unknown,\n style: string,\n explode: boolean,\n): string => {\n switch (style) {\n case 'matrix': {\n if (explode) {\n // Matrix explode array: ;color=blue;color=black;color=brown\n if (Array.isArray(paramValue)) {\n const values = (paramValue as unknown[]).map((v) => `${param.name}=${v}`).join(';')\n return url.replace(`{;${param.name}}`, `;${values}`)\n }\n\n // Matrix explode object: ;R=100;G=200;B=150\n if (typeof paramValue === 'object' && paramValue !== null) {\n const values = Object.entries(paramValue as Record<string, unknown>)\n .map(([k, v]) => `${k}=${v}`)\n .join(';')\n return url.replace(`{;${param.name}}`, `;${values}`)\n }\n\n // Matrix explode primitive: ;color=blue\n return url.replace(`{;${param.name}}`, `;${param.name}=${paramValue}`)\n }\n\n // Matrix no explode array: ;color=blue,black,brown\n if (Array.isArray(paramValue)) {\n return url.replace(`{;${param.name}}`, `;${param.name}=${(paramValue as unknown[]).join(',')}`)\n }\n\n // Matrix no explode object: ;color=R,100,G,200,B,150\n if (typeof paramValue === 'object' && paramValue !== null) {\n const values = Object.entries(paramValue as Record<string, unknown>)\n .map(([k, v]) => `${k},${v}`)\n .join(',')\n return url.replace(`{;${param.name}}`, `;${param.name}=${values}`)\n }\n\n // Matrix no explode primitive: ;color=blue\n return url.replace(`{;${param.name}}`, `;${param.name}=${paramValue}`)\n }\n case 'label': {\n if (explode) {\n // Label explode array: .blue.black.brown\n if (Array.isArray(paramValue)) {\n return url.replace(`{.${param.name}}`, `.${(paramValue as unknown[]).join('.')}`)\n }\n\n // Label explode object: .R=100.G=200.B=150\n if (typeof paramValue === 'object' && paramValue !== null) {\n const values = Object.entries(paramValue as Record<string, unknown>)\n .map(([k, v]) => `${k}=${v}`)\n .join('.')\n\n return url.replace(`{.${param.name}}`, `.${values}`)\n }\n\n // Label explode primitive: .blue\n return url.replace(`{.${param.name}}`, `.${paramValue}`)\n }\n\n // Label no explode array: .blue,black,brown\n if (Array.isArray(paramValue)) {\n return url.replace(`{.${param.name}}`, `.${(paramValue as unknown[]).join(',')}`)\n }\n\n // Label no explode object: .R,100,G,200,B,150\n if (typeof paramValue === 'object' && paramValue !== null) {\n const values = Object.entries(paramValue as Record<string, unknown>)\n .map(([k, v]) => `${k},${v}`)\n .join(',')\n\n return url.replace(`{.${param.name}}`, `.${values}`)\n }\n\n // Label no explode primitive: .blue\n return url.replace(`{.${param.name}}`, `.${paramValue}`)\n }\n\n case 'simple': {\n const serialized = serializeSimpleStyle(paramValue, explode)\n return url.replace(`{${param.name}}`, String(serialized))\n }\n\n // Default to simple style\n default:\n return url.replace(`{${param.name}}`, String(paramValue))\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"process-parameters.js","names":[],"sources":["../../../../src/code-example/helpers/operation-to-har/process-parameters.ts"],"sourcesContent":["import { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport {\n deSerializeParameter,\n getExample,\n getExampleFromSchema,\n isParamDisabled,\n serializeContentValue,\n serializeDeepObjectStyle,\n serializeFormStyle,\n serializeFormStyleForCookies,\n serializePipeDelimitedStyle,\n serializeSimpleStyle,\n serializeSpaceDelimitedStyle,\n} from '@scalar/workspace-store/request-example'\nimport type { OperationObject, ParameterObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport type { Request as HarRequest } from 'har-format'\n\ntype ProcessedParameters = {\n url: string\n headers: HarRequest['headers']\n queryString: HarRequest['queryString']\n cookies: HarRequest['cookies']\n}\n\n/** Ensures we don't have any references in the parameters */\nconst deReferenceParams = (params: OperationObject['parameters']): ParameterObject[] =>\n (params ?? []).map((param) => getResolvedRef(param))\n\n/** Whether the parameter allows reserved characters (from param or schema). */\nconst isAllowReserved = (param: ParameterObject): boolean => {\n if ('allowReserved' in param && param.allowReserved !== undefined) {\n return param.allowReserved\n }\n if ('schema' in param && param.schema && typeof param.schema === 'object' && 'allowReserved' in param.schema) {\n return (param.schema as { allowReserved?: boolean }).allowReserved === true\n }\n return false\n}\n\n/** URL encode a value if allowReserved is not set to true. */\nconst encodeQueryValue = (value: string, param: ParameterObject): string => {\n if (isAllowReserved(param)) {\n return value\n }\n return encodeURIComponent(value)\n}\n\n/**\n * Get the style and explode values for a parameter according to OpenAPI 3.1.1 specification.\n * Handles defaults and validation for parameter location restrictions.\n */\nconst getParameterStyleAndExplode = (param: ParameterObject): { style: string; explode: boolean } => {\n // Headers only support 'simple' style\n if (param.in === 'header') {\n const explode = 'explode' in param && param.explode !== undefined ? param.explode : false\n return { style: 'simple', explode }\n }\n\n // Cookies only support 'form' style\n if (param.in === 'cookie') {\n const explode = 'explode' in param && param.explode !== undefined ? param.explode : true\n return { style: 'form', explode }\n }\n\n const defaultStyle = {\n path: 'simple',\n query: 'form',\n header: 'simple',\n cookie: 'form',\n }[param.in]\n\n // Use provided style or default based on location\n const style = 'style' in param && param.style ? param.style : defaultStyle\n\n // Determine explode value: use provided value or default based on style\n const explode = 'explode' in param && param.explode !== undefined ? param.explode : style === 'form'\n\n return { style, explode }\n}\n\n/**\n * Extract the value for a parameter from example data or schema.\n * Prioritizes example data over schema examples.\n * Returns null if the parameter is disabled so we can skip it.\n */\nconst getParameterValue = (\n param: ParameterObject,\n example: string | undefined,\n contentType: string | undefined,\n defaultDisabled: boolean,\n): unknown => {\n // Try to get value from example first\n const exampleValue = getExample(param, example, contentType)\n\n // If the parameter is disabled, return undefined so we can skip it.\n if (isParamDisabled(param, exampleValue, defaultDisabled)) {\n return undefined\n }\n\n // If the example value is set, return it.\n if (exampleValue?.value !== undefined) {\n return deSerializeParameter(exampleValue.value, param)\n }\n\n // Fall back to schema example if available\n if (!('schema' in param) || !param.schema) {\n return undefined\n }\n\n const options = param.in === 'path' ? { emptyString: `{${param.name}}` } : {}\n return getExampleFromSchema(getResolvedRef(param.schema), options)\n}\n\n/**\n * Process OpenAPI parameters and return the updated properties.\n * Handles path, query, and header parameters with various styles and explode options.\n *\n * @see https://spec.openapis.org/oas/latest.html#style-values\n */\nexport const processParameters = ({\n harRequest,\n parameters,\n example,\n defaultDisabled,\n}: {\n harRequest: HarRequest\n parameters: OperationObject['parameters']\n /** The name of the example to use */\n example?: string | undefined\n /** Whether to disable parameters by default. */\n defaultDisabled: boolean\n}): ProcessedParameters => {\n // Create copies of the arrays to avoid modifying the input\n const newHeaders = [...harRequest.headers]\n const newQueryString = [...harRequest.queryString]\n let newUrl = harRequest.url\n\n // Filter out references\n const deReferencedParams = deReferenceParams(parameters)\n\n for (const param of deReferencedParams) {\n if (!param.in || !param.name) {\n continue\n }\n\n const paramValue = getParameterValue(param, example, undefined, defaultDisabled)\n if (paramValue === undefined) {\n continue\n }\n\n const { style, explode } = getParameterStyleAndExplode(param)\n\n switch (param.in) {\n case 'path': {\n newUrl = processPathParameters(newUrl, param, paramValue, style, explode)\n break\n }\n\n case 'query': {\n // Content type parameters should be serialized according to the parameter's own content type\n if ('content' in param && param.content) {\n // We grab the first for now but eventually we should support selecting the content type per parameter\n const paramContentType = Object.keys(param.content)[0] ?? 'application/json'\n const serializedValue = serializeContentValue(paramValue, paramContentType)\n newQueryString.push({ name: param.name, value: encodeQueryValue(serializedValue, param) })\n break\n }\n\n // Handle query parameters\n switch (style) {\n case 'form': {\n const serialized = serializeFormStyle(paramValue, explode)\n\n // If serialized is an array of key-value pairs (exploded object or array)\n if (Array.isArray(serialized)) {\n for (const entry of serialized) {\n const key = entry.key || param.name\n newQueryString.push({ name: key, value: encodeQueryValue(String(entry.value), param) })\n }\n }\n // Otherwise, convert to string\n else {\n newQueryString.push({ name: param.name, value: encodeQueryValue(String(serialized), param) })\n }\n break\n }\n case 'spaceDelimited': {\n const serialized = serializeSpaceDelimitedStyle(paramValue)\n newQueryString.push({ name: param.name, value: encodeQueryValue(serialized, param) })\n break\n }\n case 'pipeDelimited': {\n const serialized = serializePipeDelimitedStyle(paramValue)\n newQueryString.push({ name: param.name, value: encodeQueryValue(serialized, param) })\n break\n }\n case 'deepObject': {\n // OAS marks deepObject-on-array and deepObject+explode:false as undefined.\n // Mirror process-body: fall back to form/explode:true for arrays and always\n // invoke the serializer for objects so authors get useful output instead of\n // a silently-dropped parameter.\n if (Array.isArray(paramValue)) {\n const serialized = serializeFormStyle(paramValue, true)\n if (Array.isArray(serialized)) {\n for (const entry of serialized) {\n const key = entry.key || param.name\n newQueryString.push({ name: key, value: encodeQueryValue(String(entry.value), param) })\n }\n } else {\n newQueryString.push({ name: param.name, value: encodeQueryValue(String(serialized), param) })\n }\n } else {\n const entries = serializeDeepObjectStyle(param.name, paramValue)\n for (const entry of entries) {\n newQueryString.push({ name: entry.key, value: encodeQueryValue(entry.value, param) })\n }\n }\n break\n }\n\n // Default to form style\n default:\n newQueryString.push({ name: param.name, value: encodeQueryValue(String(paramValue), param) })\n }\n break\n }\n\n // Headers only support 'simple' style according to OpenAPI 3.1.1\n // For arrays, simple style always produces comma-separated values regardless of explode\n // The explode parameter only affects object serialization\n case 'header': {\n const serialized = serializeSimpleStyle(paramValue, explode)\n newHeaders.push({ name: param.name, value: String(serialized) })\n break\n }\n\n // Cookies only support 'form' style according to OpenAPI 3.1.1\n case 'cookie': {\n const serialized = serializeFormStyleForCookies(paramValue, explode)\n\n // If serialized is an array of key-value pairs (exploded object or array)\n if (Array.isArray(serialized)) {\n for (const entry of serialized) {\n const key = entry.key || param.name\n const value = entry.value === null ? 'null' : String(entry.value)\n harRequest.cookies.push({ name: key, value })\n }\n }\n // Otherwise, convert to string\n else {\n const value = serialized === null ? 'null' : String(serialized)\n harRequest.cookies.push({ name: param.name, value })\n }\n break\n }\n }\n }\n\n return {\n url: newUrl,\n headers: newHeaders,\n queryString: newQueryString,\n cookies: harRequest.cookies,\n }\n}\n\n/**\n * Process path parameters according to OpenAPI specification.\n * Handles matrix, label, and simple styles with explode options.\n *\n * @param url - The URL to process\n * @param param - The parameter object\n * @param paramValue - The value of the parameter\n * @param style - The style of the parameter (matrix, label, simple)\n * @param explode - Whether to explode the parameter\n * @returns The updated URL with processed path parameters\n */\nconst processPathParameters = (\n url: string,\n param: ParameterObject,\n paramValue: unknown,\n style: string,\n explode: boolean,\n): string => {\n switch (style) {\n case 'matrix': {\n if (explode) {\n // Matrix explode array: ;color=blue;color=black;color=brown\n if (Array.isArray(paramValue)) {\n const values = (paramValue as unknown[]).map((v) => `${param.name}=${v}`).join(';')\n return url.replace(`{;${param.name}}`, `;${values}`)\n }\n\n // Matrix explode object: ;R=100;G=200;B=150\n if (typeof paramValue === 'object' && paramValue !== null) {\n const values = Object.entries(paramValue as Record<string, unknown>)\n .map(([k, v]) => `${k}=${v}`)\n .join(';')\n return url.replace(`{;${param.name}}`, `;${values}`)\n }\n\n // Matrix explode primitive: ;color=blue\n return url.replace(`{;${param.name}}`, `;${param.name}=${paramValue}`)\n }\n\n // Matrix no explode array: ;color=blue,black,brown\n if (Array.isArray(paramValue)) {\n return url.replace(`{;${param.name}}`, `;${param.name}=${(paramValue as unknown[]).join(',')}`)\n }\n\n // Matrix no explode object: ;color=R,100,G,200,B,150\n if (typeof paramValue === 'object' && paramValue !== null) {\n const values = Object.entries(paramValue as Record<string, unknown>)\n .map(([k, v]) => `${k},${v}`)\n .join(',')\n return url.replace(`{;${param.name}}`, `;${param.name}=${values}`)\n }\n\n // Matrix no explode primitive: ;color=blue\n return url.replace(`{;${param.name}}`, `;${param.name}=${paramValue}`)\n }\n case 'label': {\n if (explode) {\n // Label explode array: .blue.black.brown\n if (Array.isArray(paramValue)) {\n return url.replace(`{.${param.name}}`, `.${(paramValue as unknown[]).join('.')}`)\n }\n\n // Label explode object: .R=100.G=200.B=150\n if (typeof paramValue === 'object' && paramValue !== null) {\n const values = Object.entries(paramValue as Record<string, unknown>)\n .map(([k, v]) => `${k}=${v}`)\n .join('.')\n\n return url.replace(`{.${param.name}}`, `.${values}`)\n }\n\n // Label explode primitive: .blue\n return url.replace(`{.${param.name}}`, `.${paramValue}`)\n }\n\n // Label no explode array: .blue,black,brown\n if (Array.isArray(paramValue)) {\n return url.replace(`{.${param.name}}`, `.${(paramValue as unknown[]).join(',')}`)\n }\n\n // Label no explode object: .R,100,G,200,B,150\n if (typeof paramValue === 'object' && paramValue !== null) {\n const values = Object.entries(paramValue as Record<string, unknown>)\n .map(([k, v]) => `${k},${v}`)\n .join(',')\n\n return url.replace(`{.${param.name}}`, `.${values}`)\n }\n\n // Label no explode primitive: .blue\n return url.replace(`{.${param.name}}`, `.${paramValue}`)\n }\n\n case 'simple': {\n const serialized = serializeSimpleStyle(paramValue, explode)\n return url.replace(`{${param.name}}`, String(serialized))\n }\n\n // Default to simple style\n default:\n return url.replace(`{${param.name}}`, String(paramValue))\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"process-security-schemes.js","names":[],"sources":["../../../../src/code-example/helpers/operation-to-har/process-security-schemes.ts"],"sourcesContent":["import type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport type { Request as HarRequest } from 'har-format'\nimport { encode } from 'js-base64'\n\ntype ProcessedSecuritySchemesReturn = {\n headers: HarRequest['headers']\n queryString: HarRequest['queryString']\n cookies: HarRequest['cookies']\n}\n\n/**\n * Process security schemes into whichever parameters they are applicable to\n *\n * TODO: we probably want to be able to disable YOUR_SECRET_TOKEN placeholder text + or allow it to be customzied\n */\nexport const processSecuritySchemes = (\n securitySchemes: SecuritySchemeObjectSecret[],\n): ProcessedSecuritySchemesReturn => {\n const result: ProcessedSecuritySchemesReturn = {\n headers: [],\n queryString: [],\n cookies: [],\n }\n\n for (const scheme of securitySchemes) {\n // Handle apiKey type\n if (scheme.type === 'apiKey') {\n const value = scheme['x-scalar-secret-token'] || 'YOUR_SECRET_TOKEN'\n if (!scheme.name) {\n continue\n }\n\n const param = { name: scheme.name, value }\n\n switch (scheme.in) {\n case 'header':\n result.headers.push(param)\n break\n case 'query':\n result.queryString.push(param)\n break\n case 'cookie':\n result.cookies.push(param)\n break\n }\n continue\n }\n\n // Handle http type\n if (scheme.type === 'http') {\n if (scheme.scheme === 'basic') {\n const username = scheme['x-scalar-secret-username'] || ''\n const password = scheme['x-scalar-secret-password'] || ''\n\n // The snippet is documentation, so we always show an Authorization header. When both\n // fields are empty we render a readable `username:password` placeholder, mirroring the\n // `YOUR_SECRET_TOKEN` placeholder used by the other schemes. (The real request omits the\n // header entirely in that case — see buildRequestSecurity.)\n const value = `${username}:${password}`\n const auth = value === ':' ? 'username:password' : encode(value)\n\n result.headers.push({\n name: 'Authorization',\n value: `Basic ${auth}`,\n })\n } else if (scheme.scheme === 'bearer') {\n const token = scheme['x-scalar-secret-token'] || 'YOUR_SECRET_TOKEN'\n\n result.headers.push({\n name: 'Authorization',\n value: `Bearer ${token}`,\n })\n }\n continue\n }\n\n // Handle oauth2 type\n if (scheme.type === 'oauth2' && scheme.flows) {\n const flows = Object.values(scheme.flows)\n\n // Find the first flow with a token\n const flow = flows.find((f) => f['x-scalar-secret-token'])\n const token = flow?.['x-scalar-secret-token'] || 'YOUR_SECRET_TOKEN'\n\n result.headers.push({\n name: 'Authorization',\n value: `Bearer ${token}`,\n })\n }\n }\n\n return result\n}\n"],"mappings":";;AAeA,IAAa,KACX,MACmC;CACnC,IAAM,IAAyC;EAC7C,SAAS,EAAE;EACX,aAAa,EAAE;EACf,SAAS,EAAE;EACZ;AAED,MAAK,IAAM,KAAU,GAAiB;AAEpC,MAAI,EAAO,SAAS,UAAU;GAC5B,IAAM,IAAQ,EAAO,4BAA4B;AACjD,OAAI,CAAC,EAAO,KACV;GAGF,IAAM,IAAQ;IAAE,MAAM,EAAO;IAAM;IAAO;AAE1C,WAAQ,EAAO,IAAf;IACE,KAAK;AACH,OAAO,QAAQ,KAAK,EAAM;AAC1B;IACF,KAAK;AACH,OAAO,YAAY,KAAK,EAAM;AAC9B;IACF,KAAK;AACH,OAAO,QAAQ,KAAK,EAAM;AAC1B;;AAEJ;;AAIF,MAAI,EAAO,SAAS,QAAQ;AAC1B,OAAI,EAAO,WAAW,SAAS;IAQ7B,IAAM,IAAQ,GAPG,EAAO,+BAA+B,GAO7B,GANT,EAAO,+BAA+B,MAOjD,IAAO,MAAU,MAAM,sBAAsB,EAAO,EAAM;AAEhE,MAAO,QAAQ,KAAK;KAClB,MAAM;KACN,OAAO,SAAS;KACjB,CAAC;cACO,EAAO,WAAW,UAAU;IACrC,IAAM,IAAQ,EAAO,4BAA4B;AAEjD,MAAO,QAAQ,KAAK;KAClB,MAAM;KACN,OAAO,UAAU;KAClB,CAAC;;AAEJ;;AAIF,MAAI,EAAO,SAAS,YAAY,EAAO,OAAO;GAK5C,IAAM,IAJQ,OAAO,OAAO,EAAO,MAAM,CAGtB,MAAM,MAAM,EAAE,yBAAyB,GACrC,4BAA4B;AAEjD,KAAO,QAAQ,KAAK;IAClB,MAAM;IACN,OAAO,UAAU;IAClB,CAAC;;;AAIN,QAAO"}
1
+ {"version":3,"file":"process-security-schemes.js","names":[],"sources":["../../../../src/code-example/helpers/operation-to-har/process-security-schemes.ts"],"sourcesContent":["import type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport type { Request as HarRequest } from 'har-format'\nimport { encode } from 'js-base64'\n\ntype ProcessedSecuritySchemesReturn = {\n headers: HarRequest['headers']\n queryString: HarRequest['queryString']\n cookies: HarRequest['cookies']\n}\n\n/**\n * Process security schemes into whichever parameters they are applicable to\n *\n * TODO: we probably want to be able to disable YOUR_SECRET_TOKEN placeholder text + or allow it to be customzied\n */\nexport const processSecuritySchemes = (\n securitySchemes: SecuritySchemeObjectSecret[],\n): ProcessedSecuritySchemesReturn => {\n const result: ProcessedSecuritySchemesReturn = {\n headers: [],\n queryString: [],\n cookies: [],\n }\n\n for (const scheme of securitySchemes) {\n // Handle apiKey type\n if (scheme.type === 'apiKey') {\n const value = scheme['x-scalar-secret-token'] || 'YOUR_SECRET_TOKEN'\n if (!scheme.name) {\n continue\n }\n\n const param = { name: scheme.name, value }\n\n switch (scheme.in) {\n case 'header':\n result.headers.push(param)\n break\n case 'query':\n result.queryString.push(param)\n break\n case 'cookie':\n result.cookies.push(param)\n break\n }\n continue\n }\n\n // Handle http type\n if (scheme.type === 'http') {\n if (scheme.scheme === 'basic') {\n const username = scheme['x-scalar-secret-username'] || ''\n const password = scheme['x-scalar-secret-password'] || ''\n\n // The snippet is documentation, so we always show an Authorization header. When both\n // fields are empty we render a readable `username:password` placeholder, mirroring the\n // `YOUR_SECRET_TOKEN` placeholder used by the other schemes. (The real request omits the\n // header entirely in that case — see buildRequestSecurity.)\n const value = `${username}:${password}`\n const auth = value === ':' ? 'username:password' : encode(value)\n\n result.headers.push({\n name: 'Authorization',\n value: `Basic ${auth}`,\n })\n } else if (scheme.scheme === 'bearer') {\n const token = scheme['x-scalar-secret-token'] || 'YOUR_SECRET_TOKEN'\n\n result.headers.push({\n name: 'Authorization',\n value: `Bearer ${token}`,\n })\n }\n continue\n }\n\n // Handle oauth2 type\n if (scheme.type === 'oauth2' && scheme.flows) {\n const flows = Object.values(scheme.flows)\n\n // Find the first flow with a token\n const flow = flows.find((f) => f['x-scalar-secret-token'])\n const token = flow?.['x-scalar-secret-token'] || 'YOUR_SECRET_TOKEN'\n\n result.headers.push({\n name: 'Authorization',\n value: `Bearer ${token}`,\n })\n }\n }\n\n return result\n}\n"],"mappings":";;AAeA,IAAa,KACX,MACmC;CACnC,IAAM,IAAyC;EAC7C,SAAS,CAAC;EACV,aAAa,CAAC;EACd,SAAS,CAAC;CACZ;CAEA,KAAK,IAAM,KAAU,GAAiB;EAEpC,IAAI,EAAO,SAAS,UAAU;GAC5B,IAAM,IAAQ,EAAO,4BAA4B;GACjD,IAAI,CAAC,EAAO,MACV;GAGF,IAAM,IAAQ;IAAE,MAAM,EAAO;IAAM;GAAM;GAEzC,QAAQ,EAAO,IAAf;IACE,KAAK;KACH,EAAO,QAAQ,KAAK,CAAK;KACzB;IACF,KAAK;KACH,EAAO,YAAY,KAAK,CAAK;KAC7B;IACF,KAAK;KACH,EAAO,QAAQ,KAAK,CAAK;KACzB;GACJ;GACA;EACF;EAGA,IAAI,EAAO,SAAS,QAAQ;GAC1B,IAAI,EAAO,WAAW,SAAS;IAQ7B,IAAM,IAAQ,GAPG,EAAO,+BAA+B,GAO7B,GANT,EAAO,+BAA+B,MAOjD,IAAO,MAAU,MAAM,sBAAsB,EAAO,CAAK;IAE/D,EAAO,QAAQ,KAAK;KAClB,MAAM;KACN,OAAO,SAAS;IAClB,CAAC;GACH,OAAO,IAAI,EAAO,WAAW,UAAU;IACrC,IAAM,IAAQ,EAAO,4BAA4B;IAEjD,EAAO,QAAQ,KAAK;KAClB,MAAM;KACN,OAAO,UAAU;IACnB,CAAC;GACH;GACA;EACF;EAGA,IAAI,EAAO,SAAS,YAAY,EAAO,OAAO;GAK5C,IAAM,IAJQ,OAAO,OAAO,EAAO,KAGtB,CAAA,CAAM,MAAM,MAAM,EAAE,wBACnB,CAAA,GAAO,4BAA4B;GAEjD,EAAO,QAAQ,KAAK;IAClB,MAAM;IACN,OAAO,UAAU;GACnB,CAAC;EACH;CACF;CAEA,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"process-server-url.js","names":[],"sources":["../../../../src/code-example/helpers/operation-to-har/process-server-url.ts"],"sourcesContent":["import { replaceVariables } from '@scalar/helpers/regex/replace-variables'\nimport { mergeUrls } from '@scalar/helpers/url/merge-urls'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\n/**\n * Processes a server URL by replacing variables with their default values and merging with the path\n */\nexport const processServerUrl = (server: ServerObject | null, path: string): string => {\n if (!server?.url) {\n return path\n }\n const serverUrl = server.url\n\n // Replace server variables with their default values\n if (server.variables) {\n const variables = Object.entries(server.variables)\n\n // Extract default values from server variables\n const defaultValues = variables.reduce(\n (defaults, [variableName, variableConfig]) => {\n if (variableConfig.default !== undefined) {\n defaults[variableName] = variableConfig.default\n }\n return defaults\n },\n {} as Record<string, string | number>,\n )\n\n // Replace variables in the server URL with their default values\n const serverUrlWithVars = replaceVariables(serverUrl, defaultValues)\n\n return mergeUrls(serverUrlWithVars, path)\n }\n\n return mergeUrls(serverUrl, path)\n}\n"],"mappings":";;;AAOA,IAAa,KAAoB,GAA6B,MAAyB;AACrF,KAAI,CAAC,GAAQ,IACX,QAAO;CAET,IAAM,IAAY,EAAO;AAuBzB,QApBI,EAAO,YAiBF,EAFmB,EAAiB,GAdzB,OAAO,QAAQ,EAAO,UAAU,CAGlB,QAC7B,GAAU,CAAC,GAAc,QACpB,EAAe,YAAY,KAAA,MAC7B,EAAS,KAAgB,EAAe,UAEnC,IAET,EAAE,CACH,CAGmE,EAEhC,EAAK,GAGpC,EAAU,GAAW,EAAK"}
1
+ {"version":3,"file":"process-server-url.js","names":[],"sources":["../../../../src/code-example/helpers/operation-to-har/process-server-url.ts"],"sourcesContent":["import { replaceVariables } from '@scalar/helpers/regex/replace-variables'\nimport { mergeUrls } from '@scalar/helpers/url/merge-urls'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\n/**\n * Processes a server URL by replacing variables with their default values and merging with the path\n */\nexport const processServerUrl = (server: ServerObject | null, path: string): string => {\n if (!server?.url) {\n return path\n }\n const serverUrl = server.url\n\n // Replace server variables with their default values\n if (server.variables) {\n const variables = Object.entries(server.variables)\n\n // Extract default values from server variables\n const defaultValues = variables.reduce(\n (defaults, [variableName, variableConfig]) => {\n if (variableConfig.default !== undefined) {\n defaults[variableName] = variableConfig.default\n }\n return defaults\n },\n {} as Record<string, string | number>,\n )\n\n // Replace variables in the server URL with their default values\n const serverUrlWithVars = replaceVariables(serverUrl, defaultValues)\n\n return mergeUrls(serverUrlWithVars, path)\n }\n\n return mergeUrls(serverUrl, path)\n}\n"],"mappings":";;;AAOA,IAAa,KAAoB,GAA6B,MAAyB;CACrF,IAAI,CAAC,GAAQ,KACX,OAAO;CAET,IAAM,IAAY,EAAO;CAuBzB,OApBI,EAAO,YAiBF,EAFmB,EAAiB,GAdzB,OAAO,QAAQ,EAAO,SAGlB,CAAA,CAAU,QAC7B,GAAU,CAAC,GAAc,QACpB,EAAe,YAAY,KAAA,MAC7B,EAAS,KAAgB,EAAe,UAEnC,IAET,CAAC,CAImD,CAErC,GAAmB,CAAI,IAGnC,EAAU,GAAW,CAAI;AAClC"}
@@ -1 +1 @@
1
- {"version":3,"file":"mount.js","names":[],"sources":["../../src/code-example/mount.ts"],"sourcesContent":["import { ScalarTeleportRoot } from '@scalar/components/teleport'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport type { AvailableClients } from '@scalar/snippetz'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { createWorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getFirstServer } from '@scalar/workspace-store/helpers/get-first-server'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { generateClientMutators } from '@scalar/workspace-store/mutators'\nimport type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport type { OperationObject, ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { createApp, h, reactive } from 'vue'\n\nimport CodeExample, { type CodeExampleProps } from './components/CodeExample.vue'\nimport { generateClientOptions } from './helpers/generate-client-options'\n\nexport type CreateCodeExampleOptions = {\n /** Workspace store that holds the OpenAPI document(s) to render from. */\n store: WorkspaceStore\n /** Path of the operation to render, e.g. '/users/{id}'. */\n path: string\n /** HTTP method of the operation to render. */\n method: HttpMethod\n /** Pre-selected client ID, e.g. 'shell/curl'. */\n selectedClient?: AvailableClients[number]\n /**\n * Server object override used to build the example request.\n *\n * When omitted, the server is derived from the active document (operation,\n * then path item, then document level), mirroring the API reference. Pass\n * `null` to force \"no server\".\n */\n selectedServer?: ServerObject | null\n /**\n * Pre-selected example key for parameters and the request body.\n *\n * The store is the source of truth once an example is picked, so\n * `x-scalar-default-example` wins over this initial seed and the selection\n * round-trips through the store like the client selection does.\n */\n selectedExample?: string\n /** Security schemes applicable to the operation. */\n securitySchemes?: SecuritySchemeObjectSecret[]\n /**\n * Force a color mode on the rendered block.\n *\n * When omitted, the block inherits the ambient theme of the host page.\n * Pass `true` for dark mode or `false` for light mode.\n */\n darkMode?: boolean\n}\n\n/**\n * Builds the wrapper classes for the mounted block.\n *\n * The `.scalar-app` class scopes the Tailwind utilities, and the optional\n * color-mode class lets consumers pin the block to dark or light.\n */\nconst getWrapperClass = (darkMode: boolean | undefined): string =>\n ['scalar-app', darkMode === true ? 'dark-mode' : darkMode === false ? 'light-mode' : ''].filter(Boolean).join(' ')\n\n/**\n * Mount the CodeExample block to a DOM element without Vue.\n *\n * The consumer creates and controls their own workspace store,\n * then passes it in along with the path and method to render.\n */\nexport const createCodeExample = (el: HTMLElement | string, options: CreateCodeExampleOptions) => {\n const element = typeof el === 'string' ? document.querySelector(el) : el\n if (!element) {\n throw new Error(`Element not found: ${el}`)\n }\n\n const eventBus = createWorkspaceEventBus()\n const clientOptions = generateClientOptions()\n\n // Persist client changes back to the store. The block emits\n // `workspace:update:selected-client` on its private bus when the user picks a\n // client; without this subscription the choice would never reach the store\n // and `x-scalar-default-client` (the source of truth read below) would stay\n // stale, so the selection would not survive a re-render or be shared with\n // other blocks reading from the same store.\n const mutators = generateClientMutators(options.store)\n const unsubscribeClient = eventBus.on('workspace:update:selected-client', (payload) =>\n mutators.workspace().workspace.updateSelectedClient(payload),\n )\n\n // Persist example changes back to the store as well, mirroring the client\n // round-trip above. The block emits `workspace:update:selected-example` when\n // the user picks an example; without this the choice would never reach\n // `x-scalar-default-example` (read below) and would neither survive a\n // re-render nor sync to other blocks reading from the same store.\n const unsubscribeExample = eventBus.on('workspace:update:selected-example', (payload) =>\n mutators.workspace().workspace.updateSelectedExample(payload),\n )\n\n type OperationContext = { operation: OperationObject; server: ServerObject | null }\n\n /**\n * Resolve the operation and its effective server from the active document.\n *\n * The server is resolved from the same document the operation came from\n * (operation, then path item, then document level), so a snippet never pairs\n * an operation with a server URL from a different spec.\n */\n const resolveContext = (): OperationContext | undefined => {\n // The active document may be an AsyncAPI document, which has no `paths`.\n const activeDocument = options.store.workspace.activeDocument\n if (!activeDocument || !('paths' in activeDocument)) {\n return undefined\n }\n const pathItem = getResolvedRef(activeDocument.paths?.[options.path])\n const operation = getResolvedRef(pathItem?.[options.method])\n if (!operation) {\n return undefined\n }\n const server = getFirstServer(operation.servers ?? null, pathItem?.servers ?? null, activeDocument.servers ?? null)\n return { operation, server }\n }\n\n // Fail loudly if the path and method do not point at an operation in the store,\n // mirroring the \"element not found\" guard above.\n if (!resolveContext()) {\n throw new Error(`Operation not found: ${options.method.toUpperCase()} ${options.path}`)\n }\n\n // Remember the last context that resolved so a transient miss (e.g. the active\n // document is swapped to one without this path or method after mount) keeps\n // rendering the previous operation, paired with the server it actually came\n // from, instead of feeding `undefined` to the block.\n let lastContext: OperationContext | undefined\n\n /** Current operation + server, falling back to the last good resolution on a transient miss. */\n const currentContext = (): OperationContext => {\n const context = resolveContext()\n if (context) {\n lastContext = context\n }\n return (context ?? lastContext) as OperationContext\n }\n\n // Props are getters so the block tracks the reactive store (active document,\n // `x-scalar-default-client`, `x-scalar-default-example`) live. Change the\n // client, example, or server through the store to drive re-renders.\n const props = reactive<CodeExampleProps>({\n get operation(): OperationObject {\n return currentContext().operation\n },\n get method() {\n return options.method\n },\n get path() {\n return options.path\n },\n clientOptions,\n eventBus,\n get securitySchemes() {\n return options.securitySchemes ?? []\n },\n get selectedClient() {\n // The store is the source of truth once the user picks a client, so it\n // wins over the initial `options.selectedClient` seed and the selection\n // round-trips through the subscription above.\n return options.store.workspace['x-scalar-default-client'] ?? options.selectedClient\n },\n get selectedExample() {\n // Same as the client: the store wins over the initial seed so the example\n // selection survives re-renders and syncs across blocks.\n return options.store.workspace['x-scalar-default-example'] ?? options.selectedExample\n },\n get selectedServer() {\n // An explicit option wins (including an explicit `null` for \"no server\");\n // otherwise derive it from the same document the operation resolved from.\n return options.selectedServer !== undefined ? options.selectedServer : currentContext().server\n },\n })\n\n // Render the operation path in the header by default. The reference renders\n // this via the `#header` slot too, so the standalone block matches its look.\n const renderHeader = () => h('span', { class: 'font-code text-c-2 min-w-0 truncate' }, options.path)\n\n // Wrap the block in its own teleport root so floating UI (the client picker\n // popover) renders inside the themed `.scalar-app` wrapper instead of escaping\n // to `body`, where it would miss the color-mode variables and lose its styling.\n const app = createApp(() =>\n h('div', { class: getWrapperClass(options.darkMode) }, [\n h(ScalarTeleportRoot, null, { default: () => h(CodeExample, props, { header: renderHeader }) }),\n ]),\n )\n\n app.mount(element)\n\n return {\n app,\n destroy: () => {\n unsubscribeClient()\n unsubscribeExample()\n app.unmount()\n },\n }\n}\n"],"mappings":";;;;;;;;;AAyDA,IAAM,KAAmB,MACvB,CAAC,cAAc,MAAa,KAAO,cAAc,MAAa,KAAQ,eAAe,GAAG,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI,EAQvG,KAAqB,GAA0B,MAAsC;CAChG,IAAM,IAAU,OAAO,KAAO,WAAW,SAAS,cAAc,EAAG,GAAG;AACtE,KAAI,CAAC,EACH,OAAU,MAAM,sBAAsB,IAAK;CAG7C,IAAM,IAAW,GAAyB,EACpC,IAAgB,GAAuB,EAQvC,IAAW,EAAuB,EAAQ,MAAM,EAChD,IAAoB,EAAS,GAAG,qCAAqC,MACzE,EAAS,WAAW,CAAC,UAAU,qBAAqB,EAAQ,CAC7D,EAOK,IAAqB,EAAS,GAAG,sCAAsC,MAC3E,EAAS,WAAW,CAAC,UAAU,sBAAsB,EAAQ,CAC9D,EAWK,UAAqD;EAEzD,IAAM,IAAiB,EAAQ,MAAM,UAAU;AAC/C,MAAI,CAAC,KAAkB,EAAE,WAAW,GAClC;EAEF,IAAM,IAAW,EAAe,EAAe,QAAQ,EAAQ,MAAM,EAC/D,IAAY,EAAe,IAAW,EAAQ,QAAQ;AACvD,QAIL,QAAO;GAAE;GAAW,QADL,EAAe,EAAU,WAAW,MAAM,GAAU,WAAW,MAAM,EAAe,WAAW,KAAK;GACvF;;AAK9B,KAAI,CAAC,GAAgB,CACnB,OAAU,MAAM,wBAAwB,EAAQ,OAAO,aAAa,CAAC,GAAG,EAAQ,OAAO;CAOzF,IAAI,GAGE,UAAyC;EAC7C,IAAM,IAAU,GAAgB;AAIhC,SAHI,MACF,IAAc,IAER,KAAW;IAMf,IAAQ,EAA2B;EACvC,IAAI,YAA6B;AAC/B,UAAO,GAAgB,CAAC;;EAE1B,IAAI,SAAS;AACX,UAAO,EAAQ;;EAEjB,IAAI,OAAO;AACT,UAAO,EAAQ;;EAEjB;EACA;EACA,IAAI,kBAAkB;AACpB,UAAO,EAAQ,mBAAmB,EAAE;;EAEtC,IAAI,iBAAiB;AAInB,UAAO,EAAQ,MAAM,UAAU,8BAA8B,EAAQ;;EAEvE,IAAI,kBAAkB;AAGpB,UAAO,EAAQ,MAAM,UAAU,+BAA+B,EAAQ;;EAExE,IAAI,iBAAiB;AAGnB,UAAO,EAAQ,mBAAmB,KAAA,IAAqC,GAAgB,CAAC,SAA1C,EAAQ;;EAEzD,CAAC,EAII,UAAqB,EAAE,QAAQ,EAAE,OAAO,uCAAuC,EAAE,EAAQ,KAAK,EAK9F,IAAM,QACV,EAAE,OAAO,EAAE,OAAO,EAAgB,EAAQ,SAAS,EAAE,EAAE,CACrD,EAAE,GAAoB,MAAM,EAAE,eAAe,EAAE,GAAa,GAAO,EAAE,QAAQ,GAAc,CAAC,EAAE,CAAC,CAChG,CAAC,CACH;AAID,QAFA,EAAI,MAAM,EAAQ,EAEX;EACL;EACA,eAAe;AAGb,GAFA,GAAmB,EACnB,GAAoB,EACpB,EAAI,SAAS;;EAEhB"}
1
+ {"version":3,"file":"mount.js","names":[],"sources":["../../src/code-example/mount.ts"],"sourcesContent":["import { ScalarTeleportRoot } from '@scalar/components/teleport'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport type { AvailableClients } from '@scalar/snippetz'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { createWorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getFirstServer } from '@scalar/workspace-store/helpers/get-first-server'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { generateClientMutators } from '@scalar/workspace-store/mutators'\nimport type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport type { OperationObject, ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { createApp, h, reactive } from 'vue'\n\nimport CodeExample, { type CodeExampleProps } from './components/CodeExample.vue'\nimport { generateClientOptions } from './helpers/generate-client-options'\n\nexport type CreateCodeExampleOptions = {\n /** Workspace store that holds the OpenAPI document(s) to render from. */\n store: WorkspaceStore\n /** Path of the operation to render, e.g. '/users/{id}'. */\n path: string\n /** HTTP method of the operation to render. */\n method: HttpMethod\n /** Pre-selected client ID, e.g. 'shell/curl'. */\n selectedClient?: AvailableClients[number]\n /**\n * Server object override used to build the example request.\n *\n * When omitted, the server is derived from the active document (operation,\n * then path item, then document level), mirroring the API reference. Pass\n * `null` to force \"no server\".\n */\n selectedServer?: ServerObject | null\n /**\n * Pre-selected example key for parameters and the request body.\n *\n * The store is the source of truth once an example is picked, so\n * `x-scalar-default-example` wins over this initial seed and the selection\n * round-trips through the store like the client selection does.\n */\n selectedExample?: string\n /** Security schemes applicable to the operation. */\n securitySchemes?: SecuritySchemeObjectSecret[]\n /**\n * Force a color mode on the rendered block.\n *\n * When omitted, the block inherits the ambient theme of the host page.\n * Pass `true` for dark mode or `false` for light mode.\n */\n darkMode?: boolean\n}\n\n/**\n * Builds the wrapper classes for the mounted block.\n *\n * The `.scalar-app` class scopes the Tailwind utilities, and the optional\n * color-mode class lets consumers pin the block to dark or light.\n */\nconst getWrapperClass = (darkMode: boolean | undefined): string =>\n ['scalar-app', darkMode === true ? 'dark-mode' : darkMode === false ? 'light-mode' : ''].filter(Boolean).join(' ')\n\n/**\n * Mount the CodeExample block to a DOM element without Vue.\n *\n * The consumer creates and controls their own workspace store,\n * then passes it in along with the path and method to render.\n */\nexport const createCodeExample = (el: HTMLElement | string, options: CreateCodeExampleOptions) => {\n const element = typeof el === 'string' ? document.querySelector(el) : el\n if (!element) {\n throw new Error(`Element not found: ${el}`)\n }\n\n const eventBus = createWorkspaceEventBus()\n const clientOptions = generateClientOptions()\n\n // Persist client changes back to the store. The block emits\n // `workspace:update:selected-client` on its private bus when the user picks a\n // client; without this subscription the choice would never reach the store\n // and `x-scalar-default-client` (the source of truth read below) would stay\n // stale, so the selection would not survive a re-render or be shared with\n // other blocks reading from the same store.\n const mutators = generateClientMutators(options.store)\n const unsubscribeClient = eventBus.on('workspace:update:selected-client', (payload) =>\n mutators.workspace().workspace.updateSelectedClient(payload),\n )\n\n // Persist example changes back to the store as well, mirroring the client\n // round-trip above. The block emits `workspace:update:selected-example` when\n // the user picks an example; without this the choice would never reach\n // `x-scalar-default-example` (read below) and would neither survive a\n // re-render nor sync to other blocks reading from the same store.\n const unsubscribeExample = eventBus.on('workspace:update:selected-example', (payload) =>\n mutators.workspace().workspace.updateSelectedExample(payload),\n )\n\n type OperationContext = { operation: OperationObject; server: ServerObject | null }\n\n /**\n * Resolve the operation and its effective server from the active document.\n *\n * The server is resolved from the same document the operation came from\n * (operation, then path item, then document level), so a snippet never pairs\n * an operation with a server URL from a different spec.\n */\n const resolveContext = (): OperationContext | undefined => {\n // The active document may be an AsyncAPI document, which has no `paths`.\n const activeDocument = options.store.workspace.activeDocument\n if (!activeDocument || !('paths' in activeDocument)) {\n return undefined\n }\n const pathItem = getResolvedRef(activeDocument.paths?.[options.path])\n const operation = getResolvedRef(pathItem?.[options.method])\n if (!operation) {\n return undefined\n }\n const server = getFirstServer(operation.servers ?? null, pathItem?.servers ?? null, activeDocument.servers ?? null)\n return { operation, server }\n }\n\n // Fail loudly if the path and method do not point at an operation in the store,\n // mirroring the \"element not found\" guard above.\n if (!resolveContext()) {\n throw new Error(`Operation not found: ${options.method.toUpperCase()} ${options.path}`)\n }\n\n // Remember the last context that resolved so a transient miss (e.g. the active\n // document is swapped to one without this path or method after mount) keeps\n // rendering the previous operation, paired with the server it actually came\n // from, instead of feeding `undefined` to the block.\n let lastContext: OperationContext | undefined\n\n /** Current operation + server, falling back to the last good resolution on a transient miss. */\n const currentContext = (): OperationContext => {\n const context = resolveContext()\n if (context) {\n lastContext = context\n }\n return (context ?? lastContext) as OperationContext\n }\n\n // Props are getters so the block tracks the reactive store (active document,\n // `x-scalar-default-client`, `x-scalar-default-example`) live. Change the\n // client, example, or server through the store to drive re-renders.\n const props = reactive<CodeExampleProps>({\n get operation(): OperationObject {\n return currentContext().operation\n },\n get method() {\n return options.method\n },\n get path() {\n return options.path\n },\n clientOptions,\n eventBus,\n get securitySchemes() {\n return options.securitySchemes ?? []\n },\n get selectedClient() {\n // The store is the source of truth once the user picks a client, so it\n // wins over the initial `options.selectedClient` seed and the selection\n // round-trips through the subscription above.\n return options.store.workspace['x-scalar-default-client'] ?? options.selectedClient\n },\n get selectedExample() {\n // Same as the client: the store wins over the initial seed so the example\n // selection survives re-renders and syncs across blocks.\n return options.store.workspace['x-scalar-default-example'] ?? options.selectedExample\n },\n get selectedServer() {\n // An explicit option wins (including an explicit `null` for \"no server\");\n // otherwise derive it from the same document the operation resolved from.\n return options.selectedServer !== undefined ? options.selectedServer : currentContext().server\n },\n })\n\n // Render the operation path in the header by default. The reference renders\n // this via the `#header` slot too, so the standalone block matches its look.\n const renderHeader = () => h('span', { class: 'font-code text-c-2 min-w-0 truncate' }, options.path)\n\n // Wrap the block in its own teleport root so floating UI (the client picker\n // popover) renders inside the themed `.scalar-app` wrapper instead of escaping\n // to `body`, where it would miss the color-mode variables and lose its styling.\n const app = createApp(() =>\n h('div', { class: getWrapperClass(options.darkMode) }, [\n h(ScalarTeleportRoot, null, { default: () => h(CodeExample, props, { header: renderHeader }) }),\n ]),\n )\n\n app.mount(element)\n\n return {\n app,\n destroy: () => {\n unsubscribeClient()\n unsubscribeExample()\n app.unmount()\n },\n }\n}\n"],"mappings":";;;;;;;;;AAyDA,IAAM,KAAmB,MACvB,CAAC,cAAc,MAAa,KAAO,cAAc,MAAa,KAAQ,eAAe,EAAE,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,GAQtG,KAAqB,GAA0B,MAAsC;CAChG,IAAM,IAAU,OAAO,KAAO,WAAW,SAAS,cAAc,CAAE,IAAI;CACtE,IAAI,CAAC,GACH,MAAU,MAAM,sBAAsB,GAAI;CAG5C,IAAM,IAAW,EAAwB,GACnC,IAAgB,EAAsB,GAQtC,IAAW,EAAuB,EAAQ,KAAK,GAC/C,IAAoB,EAAS,GAAG,qCAAqC,MACzE,EAAS,UAAU,CAAC,CAAC,UAAU,qBAAqB,CAAO,CAC7D,GAOM,IAAqB,EAAS,GAAG,sCAAsC,MAC3E,EAAS,UAAU,CAAC,CAAC,UAAU,sBAAsB,CAAO,CAC9D,GAWM,UAAqD;EAEzD,IAAM,IAAiB,EAAQ,MAAM,UAAU;EAC/C,IAAI,CAAC,KAAkB,EAAE,WAAW,IAClC;EAEF,IAAM,IAAW,EAAe,EAAe,QAAQ,EAAQ,KAAK,GAC9D,IAAY,EAAe,IAAW,EAAQ,OAAO;EACtD,OAIL,OAAO;GAAE;GAAW,QADL,EAAe,EAAU,WAAW,MAAM,GAAU,WAAW,MAAM,EAAe,WAAW,IAC1F;EAAO;CAC7B;CAIA,IAAI,CAAC,EAAe,GAClB,MAAU,MAAM,wBAAwB,EAAQ,OAAO,YAAY,EAAE,GAAG,EAAQ,MAAM;CAOxF,IAAI,GAGE,UAAyC;EAC7C,IAAM,IAAU,EAAe;EAI/B,OAHI,MACF,IAAc,IAER,KAAW;CACrB,GAKM,IAAQ,EAA2B;EACvC,IAAI,YAA6B;GAC/B,OAAO,EAAe,CAAC,CAAC;EAC1B;EACA,IAAI,SAAS;GACX,OAAO,EAAQ;EACjB;EACA,IAAI,OAAO;GACT,OAAO,EAAQ;EACjB;EACA;EACA;EACA,IAAI,kBAAkB;GACpB,OAAO,EAAQ,mBAAmB,CAAC;EACrC;EACA,IAAI,iBAAiB;GAInB,OAAO,EAAQ,MAAM,UAAU,8BAA8B,EAAQ;EACvE;EACA,IAAI,kBAAkB;GAGpB,OAAO,EAAQ,MAAM,UAAU,+BAA+B,EAAQ;EACxE;EACA,IAAI,iBAAiB;GAGnB,OAAO,EAAQ,mBAAmB,KAAA,IAAqC,EAAe,CAAC,CAAC,SAA1C,EAAQ;EACxD;CACF,CAAC,GAIK,UAAqB,EAAE,QAAQ,EAAE,OAAO,sCAAsC,GAAG,EAAQ,IAAI,GAK7F,IAAM,QACV,EAAE,OAAO,EAAE,OAAO,EAAgB,EAAQ,QAAQ,EAAE,GAAG,CACrD,EAAE,GAAoB,MAAM,EAAE,eAAe,EAAE,GAAa,GAAO,EAAE,QAAQ,EAAa,CAAC,EAAE,CAAC,CAChG,CAAC,CACH;CAIA,OAFA,EAAI,MAAM,CAAO,GAEV;EACL;EACA,eAAe;GAGb,AAFA,EAAkB,GAClB,EAAmB,GACnB,EAAI,QAAQ;EACd;CACF;AACF"}
package/dist/constants.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region src/constants.ts
2
- var e = typeof OVERRIDE_PACKAGE_VERSION < "u" ? OVERRIDE_PACKAGE_VERSION : "0.1.9";
2
+ var e = typeof OVERRIDE_PACKAGE_VERSION < "u" ? OVERRIDE_PACKAGE_VERSION : "0.1.11";
3
3
  //#endregion
4
4
  export { e as APP_VERSION };
5
5
 
package/dist/style.css CHANGED
@@ -1,4 +1,4 @@
1
- /*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
1
+ /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
2
2
  @layer properties {
3
3
  @supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
4
4
  *, :before, :after, ::backdrop {
@@ -690,6 +690,10 @@
690
690
  }
691
691
  }
692
692
 
693
+ .scalar-app .hljs-regexp, .scalar-app .hljs-string, .scalar-app .hljs-built_in, .scalar-app .hljs-subst, .scalar-app .hljs-name, .scalar-app .hljs-doctag, .scalar-app .hljs-section, .scalar-app .hljs-title {
694
+ color: var(--scalar-color-blue);
695
+ }
696
+
693
697
  .scalar-code-block pre {
694
698
  font-variant-ligatures: none;
695
699
  }
@@ -1675,7 +1679,7 @@
1675
1679
  margin-bottom: -1px;
1676
1680
  }
1677
1681
 
1678
- :where(body) > .scalar-tooltip {
1682
+ :where(body, dialog) > .scalar-tooltip {
1679
1683
  --scalar-tooltip-padding-x: 8px;
1680
1684
  --scalar-tooltip-padding-y: 6px;
1681
1685
  padding: var(--scalar-tooltip-padding-y) var(--scalar-tooltip-padding-x);
@@ -1689,23 +1693,23 @@
1689
1693
  color: var(--scalar-tooltip-color);
1690
1694
  }
1691
1695
 
1692
- :where(body) > .scalar-tooltip[data-side="top"] {
1696
+ :where(body, dialog) > .scalar-tooltip[data-side="top"] {
1693
1697
  padding-bottom: calc(var(--scalar-tooltip-padding-y) + var(--scalar-tooltip-offset));
1694
1698
  }
1695
1699
 
1696
- :where(body) > .scalar-tooltip[data-side="bottom"] {
1700
+ :where(body, dialog) > .scalar-tooltip[data-side="bottom"] {
1697
1701
  padding-top: calc(var(--scalar-tooltip-padding-y) + var(--scalar-tooltip-offset));
1698
1702
  }
1699
1703
 
1700
- :where(body) > .scalar-tooltip[data-side="left"] {
1704
+ :where(body, dialog) > .scalar-tooltip[data-side="left"] {
1701
1705
  padding-right: calc(var(--scalar-tooltip-padding-x) + var(--scalar-tooltip-offset));
1702
1706
  }
1703
1707
 
1704
- :where(body) > .scalar-tooltip[data-side="right"] {
1708
+ :where(body, dialog) > .scalar-tooltip[data-side="right"] {
1705
1709
  padding-left: calc(var(--scalar-tooltip-padding-x) + var(--scalar-tooltip-offset));
1706
1710
  }
1707
1711
 
1708
- :where(body) > .scalar-tooltip:before {
1712
+ :where(body, dialog) > .scalar-tooltip:before {
1709
1713
  content: "";
1710
1714
  z-index: calc(1 * -1);
1711
1715
  border-radius: var(--scalar-radius-lg);
@@ -1721,19 +1725,19 @@
1721
1725
  inset: 0;
1722
1726
  }
1723
1727
 
1724
- :where(body) > .scalar-tooltip[data-side="top"]:before {
1728
+ :where(body, dialog) > .scalar-tooltip[data-side="top"]:before {
1725
1729
  bottom: var(--scalar-tooltip-offset);
1726
1730
  }
1727
1731
 
1728
- :where(body) > .scalar-tooltip[data-side="bottom"]:before {
1732
+ :where(body, dialog) > .scalar-tooltip[data-side="bottom"]:before {
1729
1733
  top: var(--scalar-tooltip-offset);
1730
1734
  }
1731
1735
 
1732
- :where(body) > .scalar-tooltip[data-side="left"]:before {
1736
+ :where(body, dialog) > .scalar-tooltip[data-side="left"]:before {
1733
1737
  right: var(--scalar-tooltip-offset);
1734
1738
  }
1735
1739
 
1736
- :where(body) > .scalar-tooltip[data-side="right"]:before {
1740
+ :where(body, dialog) > .scalar-tooltip[data-side="right"]:before {
1737
1741
  left: var(--scalar-tooltip-offset);
1738
1742
  }
1739
1743
 
@@ -1966,22 +1970,6 @@
1966
1970
  inset-block: 2px;
1967
1971
  }
1968
1972
 
1969
- .scalar-app .-start {
1970
- inset-inline-start: -4px;
1971
- }
1972
-
1973
- .scalar-app .start {
1974
- inset-inline-start: 4px;
1975
- }
1976
-
1977
- .scalar-app .-end {
1978
- inset-inline-end: -4px;
1979
- }
1980
-
1981
- .scalar-app .end {
1982
- inset-inline-end: 4px;
1983
- }
1984
-
1985
1973
  .scalar-app .-top-1 {
1986
1974
  top: -4px;
1987
1975
  }
@@ -2100,7 +2088,6 @@
2100
2088
 
2101
2089
  .scalar-app .z-10 {
2102
2090
  z-index: 10;
2103
- z-index: 10;
2104
2091
  }
2105
2092
 
2106
2093
  .scalar-app .z-context {
@@ -2659,7 +2646,7 @@
2659
2646
  }
2660
2647
 
2661
2648
  .scalar-app .translate-x-0 {
2662
- --tw-translate-x: calc(4px * 0);
2649
+ --tw-translate-x: 0px;
2663
2650
  translate: var(--tw-translate-x) var(--tw-translate-y);
2664
2651
  }
2665
2652
 
@@ -2694,7 +2681,7 @@
2694
2681
  }
2695
2682
 
2696
2683
  .scalar-app .translate-y-0 {
2697
- --tw-translate-y: calc(4px * 0);
2684
+ --tw-translate-y: 0px;
2698
2685
  translate: var(--tw-translate-x) var(--tw-translate-y);
2699
2686
  }
2700
2687
 
@@ -3569,7 +3556,7 @@
3569
3556
  }
3570
3557
 
3571
3558
  .scalar-app .shadow-border {
3572
- --tw-shadow: inset 0 0 0 var(--tw-shadow-color, var(--scalar-border-width)) var(--scalar-border-color);
3559
+ --tw-shadow: inset 0 0 0 var(--scalar-border-width) var(--scalar-border-color);
3573
3560
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
3574
3561
  }
3575
3562
 
@@ -3800,6 +3787,16 @@
3800
3787
  .scalar-app .group-hover\/button\:text-c-header-1:is(:where(.group\/button):hover *) {
3801
3788
  color: var(--scalar-header-color-1, var(--scalar-color-1));
3802
3789
  }
3790
+
3791
+ .scalar-app .group-hover\/copy-button\:bg-b-1\.5:is(:where(.group\/copy-button):hover *) {
3792
+ background-color: var(--scalar-background-1);
3793
+ }
3794
+
3795
+ @supports (color: color-mix(in lab, red, red)) {
3796
+ .scalar-app .group-hover\/copy-button\:bg-b-1\.5:is(:where(.group\/copy-button):hover *) {
3797
+ background-color: color-mix(in srgb, var(--scalar-background-1), var(--scalar-background-2));
3798
+ }
3799
+ }
3803
3800
  }
3804
3801
 
3805
3802
  .scalar-app .group-focus-visible\/toggle\:outline:is(:where(.group\/toggle):focus-visible *) {
@@ -3860,16 +3857,22 @@
3860
3857
  border-bottom-left-radius: inherit;
3861
3858
  }
3862
3859
 
3863
- .scalar-app .focus-within\:bg-b-1:focus-within {
3864
- background-color: var(--scalar-background-1);
3865
- }
3866
-
3867
3860
  .scalar-app .focus-within\:outline-none:focus-within {
3868
3861
  --tw-outline-style: none;
3869
3862
  outline-style: none;
3870
3863
  }
3871
3864
 
3872
3865
  @media (hover: hover) {
3866
+ .scalar-app .hover\:bg-b-1\.5:hover {
3867
+ background-color: var(--scalar-background-1);
3868
+ }
3869
+
3870
+ @supports (color: color-mix(in lab, red, red)) {
3871
+ .scalar-app .hover\:bg-b-1\.5:hover {
3872
+ background-color: color-mix(in srgb, var(--scalar-background-1), var(--scalar-background-2));
3873
+ }
3874
+ }
3875
+
3873
3876
  .scalar-app .hover\:bg-b-2:hover {
3874
3877
  background-color: var(--scalar-background-2);
3875
3878
  }
@@ -4024,6 +4027,20 @@
4024
4027
  background-color: var(--bg-dark);
4025
4028
  }
4026
4029
 
4030
+ .scalar-app .dark\:bg-b-1\.5:where(.dark-mode, .dark-mode *) {
4031
+ background-color: var(--scalar-background-1);
4032
+ }
4033
+
4034
+ @supports (color: color-mix(in lab, red, red)) {
4035
+ .scalar-app .dark\:bg-b-1\.5:where(.dark-mode, .dark-mode *) {
4036
+ background-color: color-mix(in srgb, var(--scalar-background-1), var(--scalar-background-2));
4037
+ }
4038
+ }
4039
+
4040
+ .scalar-app .dark\:bg-b-2:where(.dark-mode, .dark-mode *) {
4041
+ background-color: var(--scalar-background-2);
4042
+ }
4043
+
4027
4044
  .scalar-app .dark\:bg-b-3:where(.dark-mode, .dark-mode *) {
4028
4045
  background-color: var(--scalar-background-3);
4029
4046
  }
@@ -4047,6 +4064,20 @@
4047
4064
  }
4048
4065
 
4049
4066
  @media (hover: hover) {
4067
+ .scalar-app .dark\:group-hover\/copy-button\:bg-b-1\.5:where(.dark-mode, .dark-mode *):is(:where(.group\/copy-button):hover *) {
4068
+ background-color: var(--scalar-background-1);
4069
+ }
4070
+
4071
+ @supports (color: color-mix(in lab, red, red)) {
4072
+ .scalar-app .dark\:group-hover\/copy-button\:bg-b-1\.5:where(.dark-mode, .dark-mode *):is(:where(.group\/copy-button):hover *) {
4073
+ background-color: color-mix(in srgb, var(--scalar-background-1), var(--scalar-background-2));
4074
+ }
4075
+ }
4076
+
4077
+ .scalar-app .dark\:hover\:bg-b-2:where(.dark-mode, .dark-mode *):hover {
4078
+ background-color: var(--scalar-background-2);
4079
+ }
4080
+
4050
4081
  .scalar-app .dark\:hover\:bg-b-3:where(.dark-mode, .dark-mode *):hover {
4051
4082
  background-color: var(--scalar-background-3);
4052
4083
  }
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "blocks",
18
18
  "docs"
19
19
  ],
20
- "version": "0.1.9",
20
+ "version": "0.1.11",
21
21
  "engines": {
22
22
  "node": ">=22"
23
23
  },
@@ -39,27 +39,27 @@
39
39
  "dependencies": {
40
40
  "@types/har-format": "^1.2.16",
41
41
  "js-base64": "^3.7.8",
42
- "vue": "^3.5.30",
43
- "@scalar/components": "0.27.10",
44
- "@scalar/helpers": "0.9.2",
45
- "@scalar/snippetz": "0.9.24",
42
+ "vue": "^3.5.40",
43
+ "@scalar/components": "0.27.11",
44
+ "@scalar/helpers": "0.10.0",
46
45
  "@scalar/icons": "0.7.5",
46
+ "@scalar/snippetz": "0.9.26",
47
47
  "@scalar/themes": "0.17.2",
48
- "@scalar/types": "0.17.0",
49
- "@scalar/workspace-store": "0.56.0"
48
+ "@scalar/types": "0.18.0",
49
+ "@scalar/workspace-store": "0.57.0"
50
50
  },
51
51
  "devDependencies": {
52
- "@tailwindcss/cli": "^4.2.4",
53
- "@tailwindcss/vite": "^4.2.0",
54
- "@vitejs/plugin-vue": "^6.0.3",
55
- "@vue/test-utils": "2.4.6",
52
+ "@tailwindcss/cli": "^4.3.3",
53
+ "@tailwindcss/vite": "^4.3.3",
54
+ "@vitejs/plugin-vue": "^6.0.8",
55
+ "@vue/test-utils": "2.4.11",
56
56
  "@vueuse/core": "13.9.0",
57
57
  "jsdom": "27.4.0",
58
- "tailwindcss": "^4.1.18",
59
- "vite": "8.0.0",
60
- "vitest": "4.1.0",
58
+ "tailwindcss": "^4.3.3",
59
+ "vite": "8.1.5",
60
+ "vitest": "4.1.10",
61
61
  "vue-router": "5.0.4",
62
- "vue-tsc": "^3.2.4"
62
+ "vue-tsc": "^3.3.8"
63
63
  },
64
64
  "scripts": {
65
65
  "build": "vite build && pnpm build:styles && vue-tsc -p tsconfig.build.json",