@scalar/api-reference 1.52.1 → 1.52.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/blocks/scalar-client-selector-block/components/ClientDropdown.vue.d.ts +1 -1
- package/dist/blocks/scalar-client-selector-block/components/ClientDropdown.vue.d.ts.map +1 -1
- package/dist/blocks/scalar-client-selector-block/components/ClientDropdown.vue.js +1 -1
- package/dist/blocks/scalar-client-selector-block/components/ClientDropdown.vue.js.map +1 -1
- package/dist/blocks/scalar-client-selector-block/components/ClientDropdown.vue.script.js +1 -1
- package/dist/blocks/scalar-client-selector-block/components/ClientDropdown.vue.script.js.map +1 -1
- package/dist/blocks/scalar-client-selector-block/components/ClientSelector.vue.d.ts +2 -2
- package/dist/blocks/scalar-client-selector-block/components/ClientSelector.vue.d.ts.map +1 -1
- package/dist/blocks/scalar-client-selector-block/components/ClientSelector.vue.js +1 -1
- package/dist/blocks/scalar-client-selector-block/components/ClientSelector.vue.js.map +1 -1
- package/dist/blocks/scalar-client-selector-block/components/ClientSelector.vue.script.js +1 -1
- package/dist/blocks/scalar-client-selector-block/components/ClientSelector.vue.script.js.map +1 -1
- package/dist/blocks/scalar-client-selector-block/helpers/featured-clients.d.ts +1 -1
- package/dist/blocks/scalar-client-selector-block/helpers/featured-clients.d.ts.map +1 -1
- package/dist/blocks/scalar-client-selector-block/helpers/featured-clients.js.map +1 -1
- package/dist/blocks/scalar-server-selector-block/components/ServerSelector.vue.js.map +1 -1
- package/dist/blocks/scalar-server-selector-block/components/ServerSelector.vue.script.js +2 -2
- package/dist/blocks/scalar-server-selector-block/components/ServerSelector.vue.script.js.map +1 -1
- package/dist/browser/standalone.js +414 -422
- package/dist/browser/webpack-stats.json +1 -1
- package/dist/components/AgentScalar/OpenMCPButton.vue.js +1 -1
- package/dist/components/AgentScalar/OpenMCPButton.vue.js.map +1 -1
- package/dist/components/AgentScalar/OpenMCPButton.vue.script.js +1 -1
- package/dist/components/AgentScalar/OpenMCPButton.vue.script.js.map +1 -1
- package/dist/components/ApiReference.vue.d.ts.map +1 -1
- package/dist/components/ApiReference.vue.js +1 -1
- package/dist/components/ApiReference.vue.js.map +1 -1
- package/dist/components/ApiReference.vue.script.js +26 -9
- package/dist/components/ApiReference.vue.script.js.map +1 -1
- package/dist/components/Content/Auth/Auth.vue.js.map +1 -1
- package/dist/components/Content/Auth/Auth.vue.script.js +1 -1
- package/dist/components/Content/Auth/Auth.vue.script.js.map +1 -1
- package/dist/components/Content/Content.vue.d.ts +1 -1
- package/dist/components/Content/Content.vue.d.ts.map +1 -1
- package/dist/components/Content/Content.vue.js.map +1 -1
- package/dist/components/Content/Content.vue.script.js +2 -2
- package/dist/components/Content/Content.vue.script.js.map +1 -1
- package/dist/components/Content/Models/Model.vue.d.ts +1 -1
- package/dist/components/Content/Models/Model.vue.d.ts.map +1 -1
- package/dist/components/Content/Models/Model.vue.js.map +1 -1
- package/dist/components/Content/Models/Model.vue.script.js.map +1 -1
- package/dist/components/Content/Models/components/ClassicLayout.vue.d.ts +1 -1
- package/dist/components/Content/Models/components/ClassicLayout.vue.d.ts.map +1 -1
- package/dist/components/Content/Models/components/ClassicLayout.vue.js +1 -1
- package/dist/components/Content/Models/components/ClassicLayout.vue.js.map +1 -1
- package/dist/components/Content/Models/components/ClassicLayout.vue.script.js +4 -0
- package/dist/components/Content/Models/components/ClassicLayout.vue.script.js.map +1 -1
- package/dist/components/Content/Models/components/ModernLayout.vue.d.ts +1 -0
- package/dist/components/Content/Models/components/ModernLayout.vue.d.ts.map +1 -1
- package/dist/components/Content/Models/components/ModernLayout.vue.js.map +1 -1
- package/dist/components/Content/Models/components/ModernLayout.vue.script.js +2 -1
- package/dist/components/Content/Models/components/ModernLayout.vue.script.js.map +1 -1
- package/dist/components/Content/Operations/TraversedEntry.vue.d.ts +2 -2
- package/dist/components/Content/Operations/TraversedEntry.vue.d.ts.map +1 -1
- package/dist/components/Content/Operations/TraversedEntry.vue.js.map +1 -1
- package/dist/components/Content/Operations/TraversedEntry.vue.script.js.map +1 -1
- package/dist/components/Content/Schema/SchemaComposition.vue.d.ts +2 -0
- package/dist/components/Content/Schema/SchemaComposition.vue.d.ts.map +1 -1
- package/dist/components/Content/Schema/SchemaComposition.vue.js.map +1 -1
- package/dist/components/Content/Schema/SchemaComposition.vue.script.js +5 -0
- package/dist/components/Content/Schema/SchemaComposition.vue.script.js.map +1 -1
- package/dist/components/Content/Schema/SchemaObjectExampleCodeBlock.vue.js.map +1 -1
- package/dist/components/Content/Schema/SchemaObjectExampleCodeBlock.vue.script.js +1 -1
- package/dist/components/Content/Schema/SchemaObjectExampleCodeBlock.vue.script.js.map +1 -1
- package/dist/components/Content/Schema/SchemaProperty.vue.d.ts.map +1 -1
- package/dist/components/Content/Schema/SchemaProperty.vue.js +1 -1
- package/dist/components/Content/Schema/SchemaProperty.vue.js.map +1 -1
- package/dist/components/Content/Schema/SchemaProperty.vue.script.js +16 -10
- package/dist/components/Content/Schema/SchemaProperty.vue.script.js.map +1 -1
- package/dist/features/Operation/Operation.vue.d.ts +2 -2
- package/dist/features/Operation/Operation.vue.d.ts.map +1 -1
- package/dist/features/Operation/Operation.vue.js.map +1 -1
- package/dist/features/Operation/Operation.vue.script.js.map +1 -1
- package/dist/features/Operation/components/OperationParameters.vue.d.ts +1 -1
- package/dist/features/Operation/components/OperationParameters.vue.d.ts.map +1 -1
- package/dist/features/Operation/components/OperationParameters.vue.js.map +1 -1
- package/dist/features/Operation/components/OperationParameters.vue.script.js +1 -1
- package/dist/features/Operation/components/OperationParameters.vue.script.js.map +1 -1
- package/dist/features/Operation/components/OperationResponses.vue.d.ts +1 -1
- package/dist/features/Operation/components/OperationResponses.vue.d.ts.map +1 -1
- package/dist/features/Operation/components/OperationResponses.vue.js.map +1 -1
- package/dist/features/Operation/components/OperationResponses.vue.script.js.map +1 -1
- package/dist/features/Operation/components/ParameterList.vue.d.ts +1 -1
- package/dist/features/Operation/components/ParameterList.vue.d.ts.map +1 -1
- package/dist/features/Operation/components/ParameterList.vue.js.map +1 -1
- package/dist/features/Operation/components/ParameterList.vue.script.js.map +1 -1
- package/dist/features/Operation/components/ParameterListItem.vue.d.ts +1 -1
- package/dist/features/Operation/components/ParameterListItem.vue.d.ts.map +1 -1
- package/dist/features/Operation/components/ParameterListItem.vue.js +1 -1
- package/dist/features/Operation/components/ParameterListItem.vue.js.map +1 -1
- package/dist/features/Operation/components/ParameterListItem.vue.script.js.map +1 -1
- package/dist/features/Operation/components/RequestBody.vue.d.ts +1 -0
- package/dist/features/Operation/components/RequestBody.vue.d.ts.map +1 -1
- package/dist/features/Operation/components/RequestBody.vue.js +1 -1
- package/dist/features/Operation/components/RequestBody.vue.js.map +1 -1
- package/dist/features/Operation/components/RequestBody.vue.script.js.map +1 -1
- package/dist/features/Operation/components/callbacks/Callback.vue.d.ts +1 -1
- package/dist/features/Operation/components/callbacks/Callback.vue.d.ts.map +1 -1
- package/dist/features/Operation/components/callbacks/Callback.vue.js +1 -1
- package/dist/features/Operation/components/callbacks/Callback.vue.js.map +1 -1
- package/dist/features/Operation/components/callbacks/Callback.vue.script.js.map +1 -1
- package/dist/features/Operation/components/callbacks/Callbacks.vue.d.ts +1 -1
- package/dist/features/Operation/components/callbacks/Callbacks.vue.d.ts.map +1 -1
- package/dist/features/Operation/components/callbacks/Callbacks.vue.js.map +1 -1
- package/dist/features/Operation/components/callbacks/Callbacks.vue.script.js.map +1 -1
- package/dist/features/Operation/helpers/filter-selected-security.js +3 -3
- package/dist/features/Operation/helpers/filter-selected-security.js.map +1 -1
- package/dist/features/Operation/helpers/operation-stability.d.ts +19 -0
- package/dist/features/Operation/helpers/operation-stability.d.ts.map +1 -0
- package/dist/features/Operation/helpers/operation-stability.js +25 -0
- package/dist/features/Operation/helpers/operation-stability.js.map +1 -0
- package/dist/features/Operation/helpers/should-ignore-entity.d.ts +8 -0
- package/dist/features/Operation/helpers/should-ignore-entity.d.ts.map +1 -0
- package/dist/features/Operation/helpers/should-ignore-entity.js +9 -0
- package/dist/features/Operation/helpers/should-ignore-entity.js.map +1 -0
- package/dist/features/Operation/layouts/ClassicLayout.vue.d.ts.map +1 -1
- package/dist/features/Operation/layouts/ClassicLayout.vue.js +1 -1
- package/dist/features/Operation/layouts/ClassicLayout.vue.js.map +1 -1
- package/dist/features/Operation/layouts/ClassicLayout.vue.script.js +3 -3
- package/dist/features/Operation/layouts/ClassicLayout.vue.script.js.map +1 -1
- package/dist/features/Operation/layouts/ModernLayout.vue.d.ts.map +1 -1
- package/dist/features/Operation/layouts/ModernLayout.vue.js +1 -1
- package/dist/features/Operation/layouts/ModernLayout.vue.js.map +1 -1
- package/dist/features/Operation/layouts/ModernLayout.vue.script.js +2 -2
- package/dist/features/Operation/layouts/ModernLayout.vue.script.js.map +1 -1
- package/dist/features/Search/components/SearchModal.vue.js +1 -1
- package/dist/features/Search/components/SearchModal.vue.js.map +1 -1
- package/dist/features/Search/components/SearchModal.vue.script.js +1 -1
- package/dist/features/Search/components/SearchModal.vue.script.js.map +1 -1
- package/dist/features/Search/hooks/useSearchIndex.d.ts.map +1 -1
- package/dist/features/Search/hooks/useSearchIndex.js +3 -2
- package/dist/features/Search/hooks/useSearchIndex.js.map +1 -1
- package/dist/features/example-responses/ExampleResponse.vue.js +1 -1
- package/dist/features/example-responses/ExampleResponse.vue.js.map +1 -1
- package/dist/features/example-responses/ExampleResponse.vue.script.js +1 -1
- package/dist/features/example-responses/ExampleResponse.vue.script.js.map +1 -1
- package/dist/features/example-responses/ExampleResponses.vue.d.ts.map +1 -1
- package/dist/features/example-responses/ExampleResponses.vue.js +1 -1
- package/dist/features/example-responses/ExampleResponses.vue.js.map +1 -1
- package/dist/features/example-responses/ExampleResponses.vue.script.js +5 -4
- package/dist/features/example-responses/ExampleResponses.vue.script.js.map +1 -1
- package/dist/features/example-responses/ExampleSchema.vue.js.map +1 -1
- package/dist/features/example-responses/ExampleSchema.vue.script.js +1 -1
- package/dist/features/example-responses/ExampleSchema.vue.script.js.map +1 -1
- package/dist/features/example-responses/helpers/has-response-content.d.ts.map +1 -0
- package/dist/features/example-responses/{has-response-content.js → helpers/has-response-content.js} +4 -3
- package/dist/features/example-responses/helpers/has-response-content.js.map +1 -0
- package/dist/features/example-responses/helpers/normalize-mime-type-object.d.ts +8 -0
- package/dist/features/example-responses/helpers/normalize-mime-type-object.d.ts.map +1 -0
- package/dist/features/example-responses/helpers/normalize-mime-type-object.js +20 -0
- package/dist/features/example-responses/helpers/normalize-mime-type-object.js.map +1 -0
- package/dist/features/example-responses/helpers/normalize-mime-type.d.ts +10 -0
- package/dist/features/example-responses/helpers/normalize-mime-type.d.ts.map +1 -0
- package/dist/features/example-responses/helpers/normalize-mime-type.js +9 -0
- package/dist/features/example-responses/helpers/normalize-mime-type.js.map +1 -0
- package/dist/features/multiple-documents/DocumentSelector.vue.js.map +1 -1
- package/dist/features/multiple-documents/DocumentSelector.vue.script.js +1 -1
- package/dist/features/multiple-documents/DocumentSelector.vue.script.js.map +1 -1
- package/dist/helpers/load-from-perssistance.js +1 -1
- package/dist/helpers/load-from-perssistance.js.map +1 -1
- package/dist/helpers/map-config-plugins.d.ts.map +1 -1
- package/dist/helpers/map-config-plugins.js +2 -1
- package/dist/helpers/map-config-plugins.js.map +1 -1
- package/dist/helpers/map-config-to-workspace-store.js +1 -1
- package/dist/helpers/map-config-to-workspace-store.js.map +1 -1
- package/dist/helpers/normalize-configurations.js +1 -1
- package/dist/hooks/use-intersection.d.ts +12 -1
- package/dist/hooks/use-intersection.d.ts.map +1 -1
- package/dist/hooks/use-intersection.js +7 -5
- package/dist/hooks/use-intersection.js.map +1 -1
- package/dist/plugins/plugin-manager.d.ts +17 -0
- package/dist/plugins/plugin-manager.d.ts.map +1 -1
- package/dist/plugins/plugin-manager.js +14 -0
- package/dist/plugins/plugin-manager.js.map +1 -1
- package/dist/plugins/posthog/index.d.ts +16 -0
- package/dist/plugins/posthog/index.d.ts.map +1 -0
- package/dist/plugins/posthog/index.js +54 -0
- package/dist/plugins/posthog/index.js.map +1 -0
- package/dist/style.css +4748 -6033
- package/package.json +21 -16
- package/dist/features/example-responses/has-response-content.d.ts.map +0 -1
- package/dist/features/example-responses/has-response-content.js.map +0 -1
- /package/dist/features/example-responses/{has-response-content.d.ts → helpers/has-response-content.d.ts} +0 -0
|
@@ -3,14 +3,15 @@ import ExampleSchema_default from "./ExampleSchema.vue.js";
|
|
|
3
3
|
import ExampleResponse_default from "./ExampleResponse.vue.js";
|
|
4
4
|
import ExampleResponseTab_default from "./ExampleResponseTab.vue.js";
|
|
5
5
|
import ExampleResponseTabList_default from "./ExampleResponseTabList.vue.js";
|
|
6
|
-
import {
|
|
6
|
+
import { normalizeMimeTypeObject } from "./helpers/normalize-mime-type-object.js";
|
|
7
|
+
import { hasResponseContent } from "./helpers/has-response-content.js";
|
|
7
8
|
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, openBlock, ref, renderList, toDisplayString, toValue, unref, useId, vModelCheckbox, watch, withCtx, withDirectives } from "vue";
|
|
8
9
|
import { ScalarCard, ScalarCardFooter, ScalarCardSection, ScalarIcon, ScalarMarkdown } from "@scalar/components";
|
|
9
10
|
import { useClipboard } from "@scalar/use-hooks/useClipboard";
|
|
10
11
|
import { getExample } from "@scalar/workspace-store/request-example";
|
|
11
|
-
import {
|
|
12
|
-
import { ExamplePicker } from "@scalar/api-client/v2/blocks/operation-code-sample";
|
|
12
|
+
import { ExamplePicker } from "@scalar/api-client/blocks/operation-code-sample";
|
|
13
13
|
import { getResolvedRef } from "@scalar/workspace-store/helpers/get-resolved-ref";
|
|
14
|
+
import { objectKeys } from "@scalar/helpers/object/object-keys";
|
|
14
15
|
//#region src/features/example-responses/ExampleResponses.vue?vue&type=script&setup=true&lang.ts
|
|
15
16
|
var _hoisted_1 = {
|
|
16
17
|
key: 1,
|
|
@@ -54,7 +55,7 @@ var ExampleResponses_vue_vue_type_script_setup_true_lang_default = /* @__PURE__
|
|
|
54
55
|
const currentResponseContent = computed(() => {
|
|
55
56
|
const normalizedContent = normalizeMimeTypeObject(currentResponse.value?.content);
|
|
56
57
|
/** All the keys of the normalized content */
|
|
57
|
-
const keys =
|
|
58
|
+
const keys = objectKeys(normalizedContent ?? {});
|
|
58
59
|
return normalizedContent?.[keys[0] ?? ""];
|
|
59
60
|
});
|
|
60
61
|
const hasMultipleExamples = computed(() => !!currentResponseContent.value?.examples && Object.keys(currentResponseContent.value?.examples ?? {}).length > 1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExampleResponses.vue.script.js","names":[],"sources":["../../../src/features/example-responses/ExampleResponses.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { ExamplePicker } from '@scalar/api-client/v2/blocks/operation-code-sample'\nimport {\n ScalarCard,\n ScalarCardFooter,\n ScalarCardSection,\n ScalarIcon,\n ScalarMarkdown,\n} from '@scalar/components'\nimport {\n getObjectKeys,\n normalizeMimeTypeObject,\n} from '@scalar/oas-utils/helpers'\nimport { useClipboard } from '@scalar/use-hooks/useClipboard'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { getExample } from '@scalar/workspace-store/request-example'\nimport type {\n MediaTypeObject,\n ResponsesObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, toValue, useId, watch } from 'vue'\n\nimport ScreenReader from '@/components/ScreenReader.vue'\nimport ExampleSchema from '@/features/example-responses/ExampleSchema.vue'\n\nimport ExampleResponse from './ExampleResponse.vue'\nimport ExampleResponseTab from './ExampleResponseTab.vue'\nimport ExampleResponseTabList from './ExampleResponseTabList.vue'\nimport { hasResponseContent } from './has-response-content'\n\n/**\n * TODO: copyToClipboard isn't using the right content if there are multiple examples\n */\n\nconst { responses } = defineProps<{\n responses: ResponsesObject\n}>()\n\nconst id = useId()\nconst { copyToClipboard } = useClipboard()\n\n// Bring the status codes in the right order.\nconst orderedStatusCodes = computed<string[]>(() =>\n Object.keys(responses ?? {}).sort(),\n)\n\n// Filter to only valid response keys that should render in the example responses panel\nconst statusCodesWithContent = computed<string[]>(() =>\n orderedStatusCodes.value.filter((statusCode) =>\n hasResponseContent(getResolvedRef(responses?.[statusCode]), statusCode),\n ),\n)\n\n// Keep track of the current selected tab\nconst selectedResponseIndex = ref<number>(0)\n\n/**\n * Clamp the selected index when the filtered list shrinks.\n * Without this, the index can become out of bounds and cause a mismatch\n * between the visible tabs and the displayed content.\n *\n * We also reset `selectedExampleKey` to match the behavior of `changeTab`,\n * since the new response may not have the same example keys.\n */\nwatch(statusCodesWithContent, (codes) => {\n if (codes.length === 0) {\n selectedResponseIndex.value = 0\n selectedExampleKey.value = ''\n } else if (selectedResponseIndex.value >= codes.length) {\n selectedResponseIndex.value = codes.length - 1\n selectedExampleKey.value = ''\n }\n})\n\n// Return the whole response object\nconst currentResponse = computed(() => {\n const currentStatusCode =\n toValue(statusCodesWithContent)[toValue(selectedResponseIndex)] ?? ''\n\n return getResolvedRef(responses?.[currentStatusCode])\n})\n\nconst currentResponseContent = computed<MediaTypeObject | undefined>(() => {\n const normalizedContent = normalizeMimeTypeObject(\n currentResponse.value?.content,\n )\n\n /** All the keys of the normalized content */\n const keys = getObjectKeys(normalizedContent ?? {})\n return normalizedContent?.[keys[0] ?? '']\n})\n\nconst hasMultipleExamples = computed<boolean>(\n () =>\n !!currentResponseContent.value?.examples &&\n Object.keys(currentResponseContent.value?.examples ?? {}).length > 1,\n)\n\nconst selectedExampleKey = ref<string>(\n Object.keys(currentResponseContent.value?.examples ?? {})[0] ?? '',\n)\n\n/** Get the current example to display */\nconst currentExample = computed(() => {\n if (!currentResponseContent.value) {\n return undefined\n }\n\n // When multiple examples exist and one is selected, we access it directly\n if (hasMultipleExamples.value && selectedExampleKey.value) {\n return currentResponseContent.value.examples?.[selectedExampleKey.value]\n }\n\n // Otherwise, we use getExample with an undefined exampleKey to handle fallbacks\n return getExample(currentResponseContent.value, undefined, undefined)\n})\n\nconst changeTab = (index: number) => {\n selectedResponseIndex.value = index\n selectedExampleKey.value = ''\n}\n\nconst showSchema = ref(false)\n</script>\n<template>\n <ScalarCard\n v-if=\"statusCodesWithContent.length\"\n aria-label=\"Example Responses\"\n class=\"response-card\"\n role=\"region\">\n <ExampleResponseTabList @change=\"changeTab\">\n <ExampleResponseTab\n v-for=\"statusCode in statusCodesWithContent\"\n :key=\"statusCode\"\n :aria-controls=\"id\">\n <ScreenReader>Status:</ScreenReader>\n {{ statusCode }}\n </ExampleResponseTab>\n\n <template #actions>\n <button\n v-if=\"currentResponseContent?.example\"\n class=\"code-copy\"\n type=\"button\"\n @click=\"() => copyToClipboard(currentResponseContent?.example)\">\n <ScalarIcon\n icon=\"Clipboard\"\n width=\"12px\" />\n </button>\n <label\n v-if=\"currentResponseContent?.schema\"\n class=\"scalar-card-checkbox\">\n Show Schema\n <input\n v-model=\"showSchema\"\n :aria-controls=\"id\"\n class=\"scalar-card-checkbox-input\"\n type=\"checkbox\" />\n <span class=\"scalar-card-checkbox-checkmark\" />\n </label>\n </template>\n </ExampleResponseTabList>\n <ScalarCardSection class=\"grid flex-1\">\n <!-- Schema -->\n <ExampleSchema\n v-if=\"currentResponseContent?.schema && showSchema\"\n :id=\"id\"\n :schema=\"currentResponseContent?.schema\" />\n\n <!-- Example -->\n <ExampleResponse\n v-else\n :id=\"id\"\n :example=\"currentExample\"\n :response=\"currentResponseContent\" />\n </ScalarCardSection>\n <ScalarCardFooter\n v-if=\"currentResponse?.description || hasMultipleExamples\"\n class=\"response-card-footer\">\n <ExamplePicker\n v-if=\"hasMultipleExamples\"\n v-model=\"selectedExampleKey\"\n class=\"response-example-selector px-0\"\n :examples=\"currentResponseContent?.examples\" />\n <div class=\"response-description\">\n <ScalarMarkdown\n v-if=\"currentResponse?.description\"\n class=\"response-description-markdown\"\n :value=\"currentResponse.description\" />\n </div>\n </ScalarCardFooter>\n </ScalarCard>\n</template>\n\n<style scoped>\n.response-card {\n font-size: var(--scalar-font-size-3);\n}\n\n.code-copy {\n display: flex;\n align-items: center;\n justify-content: center;\n appearance: none;\n -webkit-appearance: none;\n outline: none;\n background: transparent;\n cursor: pointer;\n color: var(--scalar-color-3);\n border: none;\n padding: 0;\n margin-right: 12px;\n}\n.code-copy:hover {\n color: var(--scalar-color-1);\n}\n.code-copy svg {\n width: 13px;\n height: 13px;\n}\n.response-card-footer {\n display: flex;\n flex-direction: row-reverse;\n flex-wrap: wrap;\n justify-content: start;\n flex-shrink: 0;\n padding: 7px 12px;\n column-gap: 8px;\n}\n.response-example-selector {\n flex-shrink: 0;\n margin: -4px;\n}\n.response-description {\n font-weight: var(--scalar-semibold);\n font-size: var(--scalar-small);\n color: var(--scalar-color--1);\n\n box-sizing: border-box;\n\n flex-grow: 1;\n}\n.response-description-markdown {\n max-height: 3lh;\n}\n\n.response-description-markdown :deep(*) {\n margin: 0;\n}\n.schema-type {\n font-size: var(--scalar-micro);\n color: var(--scalar-color-2);\n font-weight: var(--scalar-semibold);\n background: var(--scalar-background-3);\n padding: 2px 4px;\n border-radius: 4px;\n margin-right: 4px;\n}\n.schema-example {\n font-size: var(--scalar-micro);\n color: var(--scalar-color-2);\n font-weight: var(--scalar-semibold);\n}\n\n.example-response-tab {\n display: block;\n margin: 6px;\n}\n\n.scalar-card-checkbox {\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n min-height: 17px;\n cursor: pointer;\n user-select: none;\n font-size: var(--scalar-small);\n font-weight: var(--scalar-font-normal);\n color: var(--scalar-color-2);\n width: fit-content;\n white-space: nowrap;\n gap: 6px;\n padding: 7px 6px;\n}\n.scalar-card-checkbox:has(.scalar-card-checkbox-input:focus-visible)\n .scalar-card-checkbox-checkmark {\n outline: 1px solid var(--scalar-color-accent);\n}\n.scalar-card-checkbox:hover {\n color: var(--scalar-color--1);\n}\n.scalar-card-checkbox .scalar-card-checkbox-input {\n position: absolute;\n opacity: 0;\n cursor: pointer;\n height: 0;\n width: 0;\n}\n\n.scalar-card-checkbox-checkmark {\n height: 16px;\n width: 16px;\n border-radius: var(--scalar-radius);\n background-color: transparent;\n background-color: var(--scalar-background-3);\n box-shadow: inset 0 0 0 var(--scalar-border-width) var(--scalar-border-color);\n}\n.scalar-card-checkbox:has(.scalar-card-checkbox-input:checked) {\n color: var(--scalar-color-1);\n font-weight: var(--scalar-semibold);\n}\n\n.scalar-card-checkbox\n .scalar-card-checkbox-input:checked\n ~ .scalar-card-checkbox-checkmark {\n background-color: var(--scalar-button-1);\n box-shadow: none;\n}\n\n.scalar-card-checkbox-checkmark:after {\n content: '';\n position: absolute;\n display: none;\n}\n\n.scalar-card-checkbox\n .scalar-card-checkbox-input:checked\n ~ .scalar-card-checkbox-checkmark:after {\n display: block;\n}\n\n.scalar-card-checkbox .scalar-card-checkbox-checkmark:after {\n right: 11.5px;\n top: 12.5px;\n width: 5px;\n height: 9px;\n border: solid 1px var(--scalar-button-1-color);\n border-width: 0 1.5px 1.5px 0;\n transform: rotate(45deg);\n}\n</style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ExampleResponses.vue.script.js","names":[],"sources":["../../../src/features/example-responses/ExampleResponses.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { ExamplePicker } from '@scalar/api-client/blocks/operation-code-sample'\nimport {\n ScalarCard,\n ScalarCardFooter,\n ScalarCardSection,\n ScalarIcon,\n ScalarMarkdown,\n} from '@scalar/components'\nimport { objectKeys } from '@scalar/helpers/object/object-keys'\nimport { useClipboard } from '@scalar/use-hooks/useClipboard'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { getExample } from '@scalar/workspace-store/request-example'\nimport type {\n MediaTypeObject,\n ResponsesObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, toValue, useId, watch } from 'vue'\n\nimport ScreenReader from '@/components/ScreenReader.vue'\nimport ExampleSchema from '@/features/example-responses/ExampleSchema.vue'\n\nimport ExampleResponse from './ExampleResponse.vue'\nimport ExampleResponseTab from './ExampleResponseTab.vue'\nimport ExampleResponseTabList from './ExampleResponseTabList.vue'\nimport { hasResponseContent } from './helpers/has-response-content'\nimport { normalizeMimeTypeObject } from './helpers/normalize-mime-type-object'\n\n/**\n * TODO: copyToClipboard isn't using the right content if there are multiple examples\n */\n\nconst { responses } = defineProps<{\n responses: ResponsesObject\n}>()\n\nconst id = useId()\nconst { copyToClipboard } = useClipboard()\n\n// Bring the status codes in the right order.\nconst orderedStatusCodes = computed<string[]>(() =>\n Object.keys(responses ?? {}).sort(),\n)\n\n// Filter to only valid response keys that should render in the example responses panel\nconst statusCodesWithContent = computed<string[]>(() =>\n orderedStatusCodes.value.filter((statusCode) =>\n hasResponseContent(getResolvedRef(responses?.[statusCode]), statusCode),\n ),\n)\n\n// Keep track of the current selected tab\nconst selectedResponseIndex = ref<number>(0)\n\n/**\n * Clamp the selected index when the filtered list shrinks.\n * Without this, the index can become out of bounds and cause a mismatch\n * between the visible tabs and the displayed content.\n *\n * We also reset `selectedExampleKey` to match the behavior of `changeTab`,\n * since the new response may not have the same example keys.\n */\nwatch(statusCodesWithContent, (codes) => {\n if (codes.length === 0) {\n selectedResponseIndex.value = 0\n selectedExampleKey.value = ''\n } else if (selectedResponseIndex.value >= codes.length) {\n selectedResponseIndex.value = codes.length - 1\n selectedExampleKey.value = ''\n }\n})\n\n// Return the whole response object\nconst currentResponse = computed(() => {\n const currentStatusCode =\n toValue(statusCodesWithContent)[toValue(selectedResponseIndex)] ?? ''\n\n return getResolvedRef(responses?.[currentStatusCode])\n})\n\nconst currentResponseContent = computed<MediaTypeObject | undefined>(() => {\n const normalizedContent = normalizeMimeTypeObject(\n currentResponse.value?.content,\n )\n\n /** All the keys of the normalized content */\n const keys = objectKeys(normalizedContent ?? {})\n return normalizedContent?.[keys[0] ?? '']\n})\n\nconst hasMultipleExamples = computed<boolean>(\n () =>\n !!currentResponseContent.value?.examples &&\n Object.keys(currentResponseContent.value?.examples ?? {}).length > 1,\n)\n\nconst selectedExampleKey = ref<string>(\n Object.keys(currentResponseContent.value?.examples ?? {})[0] ?? '',\n)\n\n/** Get the current example to display */\nconst currentExample = computed(() => {\n if (!currentResponseContent.value) {\n return undefined\n }\n\n // When multiple examples exist and one is selected, we access it directly\n if (hasMultipleExamples.value && selectedExampleKey.value) {\n return currentResponseContent.value.examples?.[selectedExampleKey.value]\n }\n\n // Otherwise, we use getExample with an undefined exampleKey to handle fallbacks\n return getExample(currentResponseContent.value, undefined, undefined)\n})\n\nconst changeTab = (index: number) => {\n selectedResponseIndex.value = index\n selectedExampleKey.value = ''\n}\n\nconst showSchema = ref(false)\n</script>\n<template>\n <ScalarCard\n v-if=\"statusCodesWithContent.length\"\n aria-label=\"Example Responses\"\n class=\"response-card\"\n role=\"region\">\n <ExampleResponseTabList @change=\"changeTab\">\n <ExampleResponseTab\n v-for=\"statusCode in statusCodesWithContent\"\n :key=\"statusCode\"\n :aria-controls=\"id\">\n <ScreenReader>Status:</ScreenReader>\n {{ statusCode }}\n </ExampleResponseTab>\n\n <template #actions>\n <button\n v-if=\"currentResponseContent?.example\"\n class=\"code-copy\"\n type=\"button\"\n @click=\"() => copyToClipboard(currentResponseContent?.example)\">\n <ScalarIcon\n icon=\"Clipboard\"\n width=\"12px\" />\n </button>\n <label\n v-if=\"currentResponseContent?.schema\"\n class=\"scalar-card-checkbox\">\n Show Schema\n <input\n v-model=\"showSchema\"\n :aria-controls=\"id\"\n class=\"scalar-card-checkbox-input\"\n type=\"checkbox\" />\n <span class=\"scalar-card-checkbox-checkmark\" />\n </label>\n </template>\n </ExampleResponseTabList>\n <ScalarCardSection class=\"grid flex-1\">\n <!-- Schema -->\n <ExampleSchema\n v-if=\"currentResponseContent?.schema && showSchema\"\n :id=\"id\"\n :schema=\"currentResponseContent?.schema\" />\n\n <!-- Example -->\n <ExampleResponse\n v-else\n :id=\"id\"\n :example=\"currentExample\"\n :response=\"currentResponseContent\" />\n </ScalarCardSection>\n <ScalarCardFooter\n v-if=\"currentResponse?.description || hasMultipleExamples\"\n class=\"response-card-footer\">\n <ExamplePicker\n v-if=\"hasMultipleExamples\"\n v-model=\"selectedExampleKey\"\n class=\"response-example-selector px-0\"\n :examples=\"currentResponseContent?.examples\" />\n <div class=\"response-description\">\n <ScalarMarkdown\n v-if=\"currentResponse?.description\"\n class=\"response-description-markdown\"\n :value=\"currentResponse.description\" />\n </div>\n </ScalarCardFooter>\n </ScalarCard>\n</template>\n\n<style scoped>\n.response-card {\n font-size: var(--scalar-font-size-3);\n}\n\n.code-copy {\n display: flex;\n align-items: center;\n justify-content: center;\n appearance: none;\n -webkit-appearance: none;\n outline: none;\n background: transparent;\n cursor: pointer;\n color: var(--scalar-color-3);\n border: none;\n padding: 0;\n margin-right: 12px;\n}\n.code-copy:hover {\n color: var(--scalar-color-1);\n}\n.code-copy svg {\n width: 13px;\n height: 13px;\n}\n.response-card-footer {\n display: flex;\n flex-direction: row-reverse;\n flex-wrap: wrap;\n justify-content: start;\n flex-shrink: 0;\n padding: 7px 12px;\n column-gap: 8px;\n}\n.response-example-selector {\n flex-shrink: 0;\n margin: -4px;\n}\n.response-description {\n font-weight: var(--scalar-semibold);\n font-size: var(--scalar-small);\n color: var(--scalar-color--1);\n\n box-sizing: border-box;\n\n flex-grow: 1;\n}\n.response-description-markdown {\n max-height: 3lh;\n}\n\n.response-description-markdown :deep(*) {\n margin: 0;\n}\n.schema-type {\n font-size: var(--scalar-micro);\n color: var(--scalar-color-2);\n font-weight: var(--scalar-semibold);\n background: var(--scalar-background-3);\n padding: 2px 4px;\n border-radius: 4px;\n margin-right: 4px;\n}\n.schema-example {\n font-size: var(--scalar-micro);\n color: var(--scalar-color-2);\n font-weight: var(--scalar-semibold);\n}\n\n.example-response-tab {\n display: block;\n margin: 6px;\n}\n\n.scalar-card-checkbox {\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n min-height: 17px;\n cursor: pointer;\n user-select: none;\n font-size: var(--scalar-small);\n font-weight: var(--scalar-font-normal);\n color: var(--scalar-color-2);\n width: fit-content;\n white-space: nowrap;\n gap: 6px;\n padding: 7px 6px;\n}\n.scalar-card-checkbox:has(.scalar-card-checkbox-input:focus-visible)\n .scalar-card-checkbox-checkmark {\n outline: 1px solid var(--scalar-color-accent);\n}\n.scalar-card-checkbox:hover {\n color: var(--scalar-color--1);\n}\n.scalar-card-checkbox .scalar-card-checkbox-input {\n position: absolute;\n opacity: 0;\n cursor: pointer;\n height: 0;\n width: 0;\n}\n\n.scalar-card-checkbox-checkmark {\n height: 16px;\n width: 16px;\n border-radius: var(--scalar-radius);\n background-color: transparent;\n background-color: var(--scalar-background-3);\n box-shadow: inset 0 0 0 var(--scalar-border-width) var(--scalar-border-color);\n}\n.scalar-card-checkbox:has(.scalar-card-checkbox-input:checked) {\n color: var(--scalar-color-1);\n font-weight: var(--scalar-semibold);\n}\n\n.scalar-card-checkbox\n .scalar-card-checkbox-input:checked\n ~ .scalar-card-checkbox-checkmark {\n background-color: var(--scalar-button-1);\n box-shadow: none;\n}\n\n.scalar-card-checkbox-checkmark:after {\n content: '';\n position: absolute;\n display: none;\n}\n\n.scalar-card-checkbox\n .scalar-card-checkbox-input:checked\n ~ .scalar-card-checkbox-checkmark:after {\n display: block;\n}\n\n.scalar-card-checkbox .scalar-card-checkbox-checkmark:after {\n right: 11.5px;\n top: 12.5px;\n width: 5px;\n height: 9px;\n border: solid 1px var(--scalar-button-1-color);\n border-width: 0 1.5px 1.5px 0;\n transform: rotate(45deg);\n}\n</style>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExampleSchema.vue.js","names":[],"sources":["../../../src/features/example-responses/ExampleSchema.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { getResolvedRefDeep } from '@scalar/api-client/
|
|
1
|
+
{"version":3,"file":"ExampleSchema.vue.js","names":[],"sources":["../../../src/features/example-responses/ExampleSchema.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { getResolvedRefDeep } from '@scalar/api-client/blocks/operation-code-sample'\nimport { ScalarCodeBlock, ScalarVirtualText } from '@scalar/components'\nimport { prettyPrintJson } from '@scalar/helpers/json/pretty-print-json'\nimport type { ReferenceType } from '@scalar/workspace-store/schemas/v3.1/strict/reference'\nimport type { SchemaObject } from '@scalar/workspace-store/schemas/v3.1/strict/schema'\nimport { computed } from 'vue'\n\nconst { id, schema } = defineProps<{\n id: string\n schema: ReferenceType<SchemaObject>\n}>()\n\nconst schemaContent = computed(() => {\n if (!schema) {\n return undefined\n }\n\n return prettyPrintJson(getResolvedRefDeep(schema))\n})\n\nconst VIRTUALIZATION_THRESHOLD = 20_000\n\nconst shouldVirtualizeSchema = computed(() => {\n return (schemaContent.value?.length ?? 0) > VIRTUALIZATION_THRESHOLD\n})\n</script>\n\n<template>\n <ScalarCodeBlock\n v-if=\"!shouldVirtualizeSchema\"\n :id=\"id\"\n class=\"bg-b-2\"\n lang=\"json\"\n :prettyPrintedContent=\"schemaContent ?? ''\" />\n <ScalarVirtualText\n v-else\n :id=\"id\"\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\"\n :lineHeight=\"20\"\n :text=\"schemaContent ?? ''\" />\n</template>\n"],"mappings":""}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { computed, createBlock, defineComponent, openBlock, unref } from "vue";
|
|
2
2
|
import { ScalarCodeBlock, ScalarVirtualText } from "@scalar/components";
|
|
3
|
-
import { getResolvedRefDeep } from "@scalar/api-client/
|
|
3
|
+
import { getResolvedRefDeep } from "@scalar/api-client/blocks/operation-code-sample";
|
|
4
4
|
import { prettyPrintJson } from "@scalar/helpers/json/pretty-print-json";
|
|
5
5
|
//#region src/features/example-responses/ExampleSchema.vue?vue&type=script&setup=true&lang.ts
|
|
6
6
|
var VIRTUALIZATION_THRESHOLD = 2e4;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExampleSchema.vue.script.js","names":[],"sources":["../../../src/features/example-responses/ExampleSchema.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { getResolvedRefDeep } from '@scalar/api-client/
|
|
1
|
+
{"version":3,"file":"ExampleSchema.vue.script.js","names":[],"sources":["../../../src/features/example-responses/ExampleSchema.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { getResolvedRefDeep } from '@scalar/api-client/blocks/operation-code-sample'\nimport { ScalarCodeBlock, ScalarVirtualText } from '@scalar/components'\nimport { prettyPrintJson } from '@scalar/helpers/json/pretty-print-json'\nimport type { ReferenceType } from '@scalar/workspace-store/schemas/v3.1/strict/reference'\nimport type { SchemaObject } from '@scalar/workspace-store/schemas/v3.1/strict/schema'\nimport { computed } from 'vue'\n\nconst { id, schema } = defineProps<{\n id: string\n schema: ReferenceType<SchemaObject>\n}>()\n\nconst schemaContent = computed(() => {\n if (!schema) {\n return undefined\n }\n\n return prettyPrintJson(getResolvedRefDeep(schema))\n})\n\nconst VIRTUALIZATION_THRESHOLD = 20_000\n\nconst shouldVirtualizeSchema = computed(() => {\n return (schemaContent.value?.length ?? 0) > VIRTUALIZATION_THRESHOLD\n})\n</script>\n\n<template>\n <ScalarCodeBlock\n v-if=\"!shouldVirtualizeSchema\"\n :id=\"id\"\n class=\"bg-b-2\"\n lang=\"json\"\n :prettyPrintedContent=\"schemaContent ?? ''\" />\n <ScalarVirtualText\n v-else\n :id=\"id\"\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\"\n :lineHeight=\"20\"\n :text=\"schemaContent ?? ''\" />\n</template>\n"],"mappings":";;;;;AAqBA,IAAM,2BAA2B;;;;;;;;EARjC,MAAM,gBAAgB,eAAe;AACnC,OAAI,CAAC,QAAA,OACH;AAGF,UAAO,gBAAgB,mBAAmB,QAAA,OAAO,CAAA;IAClD;EAID,MAAM,yBAAyB,eAAe;AAC5C,WAAQ,cAAc,OAAO,UAAU,KAAK;IAC7C;;WAKU,uBAAA,SAAA,WAAA,EADT,YAKgD,MAAA,gBAAA,EAAA;;IAH7C,IAAI,QAAA;IACL,OAAM;IACN,MAAK;IACJ,sBAAsB,cAAA,SAAa;gEACtC,YAMgC,MAAA,kBAAA,EAAA;;IAJ7B,IAAI,QAAA;IACL,gBAAe;IACf,cAAa;IACZ,YAAY;IACZ,MAAM,cAAA,SAAa"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"has-response-content.d.ts","sourceRoot":"","sources":["../../../../src/features/example-responses/helpers/has-response-content.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmB,cAAc,EAAE,MAAM,8DAA8D,CAAA;AA4BnH;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAqBtG"}
|
package/dist/features/example-responses/{has-response-content.js → helpers/has-response-content.js}
RENAMED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { normalizeMimeTypeObject } from "./normalize-mime-type-object.js";
|
|
2
|
+
import { objectKeys } from "@scalar/helpers/object/object-keys";
|
|
3
|
+
//#region src/features/example-responses/helpers/has-response-content.ts
|
|
3
4
|
/**
|
|
4
5
|
* Checks if a media type object has any displayable content.
|
|
5
6
|
* This includes having a schema, a single example, or multiple examples.
|
|
@@ -28,7 +29,7 @@ function hasResponseContent(response, responseKey) {
|
|
|
28
29
|
return Boolean(response);
|
|
29
30
|
}
|
|
30
31
|
const normalizedContent = normalizeMimeTypeObject(response?.content);
|
|
31
|
-
const keys =
|
|
32
|
+
const keys = objectKeys(normalizedContent ?? {});
|
|
32
33
|
return hasMediaTypeContent(normalizedContent?.["application/json"] ?? normalizedContent?.["application/xml"] ?? normalizedContent?.["text/plain"] ?? normalizedContent?.["text/html"] ?? normalizedContent?.["*/*"] ?? normalizedContent?.[keys[0] ?? ""]);
|
|
33
34
|
}
|
|
34
35
|
//#endregion
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"has-response-content.js","names":[],"sources":["../../../../src/features/example-responses/helpers/has-response-content.ts"],"sourcesContent":["import { objectKeys } from '@scalar/helpers/object/object-keys'\nimport type { MediaTypeObject, ResponseObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\nimport { normalizeMimeTypeObject } from './normalize-mime-type-object'\n\n/**\n * Checks if a media type object has any displayable content.\n * This includes having a schema, a single example, or multiple examples.\n *\n * Note: We use explicit property checks for `example` because falsy values\n * like `0`, `false`, and `\"\"` are valid JSON examples that should be displayed.\n * We still treat `null` as \"no content\" since it explicitly indicates absence.\n */\nfunction hasMediaTypeContent(mediaType: MediaTypeObject | undefined): boolean {\n if (!mediaType) {\n return false\n }\n\n const hasSchema = Boolean(mediaType.schema)\n const hasExample = 'example' in mediaType && mediaType.example !== null\n const hasExamples = Boolean(mediaType.examples)\n\n return hasSchema || hasExample || hasExamples\n}\n\nfunction isResponseKey(responseKey: string): boolean {\n return responseKey === 'default' || /^[1-5][0-9]{2}$/.test(responseKey) || /^[1-5]XX$/.test(responseKey)\n}\n\n/**\n * Checks if a response object has body content (schema, example, or examples).\n * Looks through common media types in priority order.\n */\nexport function hasResponseContent(response: ResponseObject | undefined, responseKey?: string): boolean {\n if (responseKey !== undefined) {\n if (!isResponseKey(responseKey)) {\n return false\n }\n\n return Boolean(response)\n }\n\n const normalizedContent = normalizeMimeTypeObject(response?.content)\n const keys = objectKeys(normalizedContent ?? {})\n\n const mediaType =\n normalizedContent?.['application/json'] ??\n normalizedContent?.['application/xml'] ??\n normalizedContent?.['text/plain'] ??\n normalizedContent?.['text/html'] ??\n normalizedContent?.['*/*'] ??\n normalizedContent?.[keys[0] ?? '']\n\n return hasMediaTypeContent(mediaType)\n}\n"],"mappings":";;;;;;;;;;;AAaA,SAAS,oBAAoB,WAAiD;AAC5E,KAAI,CAAC,UACH,QAAO;CAGT,MAAM,YAAY,QAAQ,UAAU,OAAO;CAC3C,MAAM,aAAa,aAAa,aAAa,UAAU,YAAY;CACnE,MAAM,cAAc,QAAQ,UAAU,SAAS;AAE/C,QAAO,aAAa,cAAc;;AAGpC,SAAS,cAAc,aAA8B;AACnD,QAAO,gBAAgB,aAAa,kBAAkB,KAAK,YAAY,IAAI,YAAY,KAAK,YAAY;;;;;;AAO1G,SAAgB,mBAAmB,UAAsC,aAA+B;AACtG,KAAI,gBAAgB,KAAA,GAAW;AAC7B,MAAI,CAAC,cAAc,YAAY,CAC7B,QAAO;AAGT,SAAO,QAAQ,SAAS;;CAG1B,MAAM,oBAAoB,wBAAwB,UAAU,QAAQ;CACpE,MAAM,OAAO,WAAW,qBAAqB,EAAE,CAAC;AAUhD,QAAO,oBAPL,oBAAoB,uBACpB,oBAAoB,sBACpB,oBAAoB,iBACpB,oBAAoB,gBACpB,oBAAoB,UACpB,oBAAoB,KAAK,MAAM,IAEI"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ResponseObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document';
|
|
2
|
+
/**
|
|
3
|
+
* Remove charset from content types
|
|
4
|
+
*
|
|
5
|
+
* Example: `application/json; charset=utf-8` -> `application/json`
|
|
6
|
+
*/
|
|
7
|
+
export declare function normalizeMimeTypeObject(content?: ResponseObject['content']): ResponseObject['content'];
|
|
8
|
+
//# sourceMappingURL=normalize-mime-type-object.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-mime-type-object.d.ts","sourceRoot":"","sources":["../../../../src/features/example-responses/helpers/normalize-mime-type-object.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8DAA8D,CAAA;AAIlG;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,GAAG,cAAc,CAAC,SAAS,CAAC,CAiBtG"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { normalizeMimeType } from "./normalize-mime-type.js";
|
|
2
|
+
//#region src/features/example-responses/helpers/normalize-mime-type-object.ts
|
|
3
|
+
/**
|
|
4
|
+
* Remove charset from content types
|
|
5
|
+
*
|
|
6
|
+
* Example: `application/json; charset=utf-8` -> `application/json`
|
|
7
|
+
*/
|
|
8
|
+
function normalizeMimeTypeObject(content) {
|
|
9
|
+
if (!content) return content;
|
|
10
|
+
const newContent = { ...content };
|
|
11
|
+
Object.entries(newContent).forEach(([key, value]) => {
|
|
12
|
+
const normalizedKey = normalizeMimeType(key);
|
|
13
|
+
if (normalizedKey) newContent[normalizedKey] = value;
|
|
14
|
+
});
|
|
15
|
+
return newContent;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { normalizeMimeTypeObject };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=normalize-mime-type-object.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-mime-type-object.js","names":[],"sources":["../../../../src/features/example-responses/helpers/normalize-mime-type-object.ts"],"sourcesContent":["import type { ResponseObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\nimport { normalizeMimeType } from './normalize-mime-type'\n\n/**\n * Remove charset from content types\n *\n * Example: `application/json; charset=utf-8` -> `application/json`\n */\nexport function normalizeMimeTypeObject(content?: ResponseObject['content']): ResponseObject['content'] {\n if (!content) {\n return content\n }\n\n const newContent: ResponseObject['content'] = {\n ...content,\n }\n\n Object.entries(newContent).forEach(([key, value]) => {\n const normalizedKey = normalizeMimeType(key)\n if (normalizedKey) {\n newContent[normalizedKey] = value\n }\n })\n\n return newContent\n}\n"],"mappings":";;;;;;;AASA,SAAgB,wBAAwB,SAAgE;AACtG,KAAI,CAAC,QACH,QAAO;CAGT,MAAM,aAAwC,EAC5C,GAAG,SACJ;AAED,QAAO,QAAQ,WAAW,CAAC,SAAS,CAAC,KAAK,WAAW;EACnD,MAAM,gBAAgB,kBAAkB,IAAI;AAC5C,MAAI,cACF,YAAW,iBAAiB;GAE9B;AAEF,QAAO"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ContentType } from '@scalar/types/legacy';
|
|
2
|
+
/**
|
|
3
|
+
* Normalizes a MIME type to a standard format.
|
|
4
|
+
*
|
|
5
|
+
* Input: application/problem+json; charset=utf-8
|
|
6
|
+
* Output: application/json
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeMimeType(contentType: undefined): undefined;
|
|
9
|
+
export declare function normalizeMimeType(contentType: string): ContentType;
|
|
10
|
+
//# sourceMappingURL=normalize-mime-type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-mime-type.d.ts","sourceRoot":"","sources":["../../../../src/features/example-responses/helpers/normalize-mime-type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAEvD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,SAAS,GAAG,SAAS,CAAA;AACpE,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/features/example-responses/helpers/normalize-mime-type.ts
|
|
2
|
+
function normalizeMimeType(contentType) {
|
|
3
|
+
if (typeof contentType !== "string") return;
|
|
4
|
+
return contentType.replace(/;.*$/, "").replace(/\/(?!.*vnd\.|fhir\+).*\+/, "/").trim();
|
|
5
|
+
}
|
|
6
|
+
//#endregion
|
|
7
|
+
export { normalizeMimeType };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=normalize-mime-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-mime-type.js","names":[],"sources":["../../../../src/features/example-responses/helpers/normalize-mime-type.ts"],"sourcesContent":["import type { ContentType } from '@scalar/types/legacy'\n\n/**\n * Normalizes a MIME type to a standard format.\n *\n * Input: application/problem+json; charset=utf-8\n * Output: application/json\n */\nexport function normalizeMimeType(contentType: undefined): undefined\nexport function normalizeMimeType(contentType: string): ContentType\nexport function normalizeMimeType(contentType: string | undefined): ContentType | undefined {\n if (typeof contentType !== 'string') {\n return undefined\n }\n\n return (\n contentType\n // Remove '; charset=utf-8'\n .replace(/;.*$/, '')\n // Remove 'problem+' but keep vendor-specific vnd and fhir mime types\n .replace(/\\/(?!.*vnd\\.|fhir\\+).*\\+/, '/')\n // Remove whitespace\n .trim() as ContentType\n )\n}\n"],"mappings":";AAUA,SAAgB,kBAAkB,aAA0D;AAC1F,KAAI,OAAO,gBAAgB,SACzB;AAGF,QACE,YAEG,QAAQ,QAAQ,GAAG,CAEnB,QAAQ,4BAA4B,IAAI,CAExC,MAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentSelector.vue.js","names":[],"sources":["../../../src/features/multiple-documents/DocumentSelector.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarListbox } from '@scalar/components'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport { computed } from 'vue'\n\nconst props = defineProps<{\n options: { label: string; id: string }[]\n modelValue?: string\n}>()\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', id: string): void\n}>()\n\nconst formattedOptions = computed(() =>\n props.options.map((o) => ({ id: o.id, label: o.label })),\n)\n\nconst selected = computed(() =>\n formattedOptions.value.find((o) => o.id === props.modelValue),\n)\n</script>\n\n<template>\n <div\n v-if=\"options.length > 1\"\n class=\"document-selector
|
|
1
|
+
{"version":3,"file":"DocumentSelector.vue.js","names":[],"sources":["../../../src/features/multiple-documents/DocumentSelector.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarListbox } from '@scalar/components'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport { computed } from 'vue'\n\nconst props = defineProps<{\n options: { label: string; id: string }[]\n modelValue?: string\n}>()\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', id: string): void\n}>()\n\nconst formattedOptions = computed(() =>\n props.options.map((o) => ({ id: o.id, label: o.label })),\n)\n\nconst selected = computed(() =>\n formattedOptions.value.find((o) => o.id === props.modelValue),\n)\n</script>\n\n<template>\n <div\n v-if=\"options.length > 1\"\n class=\"document-selector px-3 pt-3\">\n <ScalarListbox\n v-slot=\"{ open }\"\n :modelValue=\"selected\"\n :options=\"formattedOptions\"\n resize\n @update:modelValue=\"(e) => emit('update:modelValue', e.id)\">\n <button\n class=\"group/dropdown-label text-c-2 hover:text-c-1 flex w-full cursor-pointer items-center gap-1 font-medium\"\n type=\"button\">\n <span class=\"overflow-hidden text-base text-ellipsis\">\n {{ selected?.label || 'Select API' }}\n </span>\n <ScalarIconCaretDown\n class=\"size-3 text-current transition-transform\"\n :class=\"{ 'rotate-180': open }\"\n weight=\"bold\" />\n </button>\n </ScalarListbox>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -4,7 +4,7 @@ import { ScalarIconCaretDown } from "@scalar/icons";
|
|
|
4
4
|
//#region src/features/multiple-documents/DocumentSelector.vue?vue&type=script&setup=true&lang.ts
|
|
5
5
|
var _hoisted_1 = {
|
|
6
6
|
key: 0,
|
|
7
|
-
class: "document-selector
|
|
7
|
+
class: "document-selector px-3 pt-3"
|
|
8
8
|
};
|
|
9
9
|
var _hoisted_2 = {
|
|
10
10
|
class: "group/dropdown-label text-c-2 hover:text-c-1 flex w-full cursor-pointer items-center gap-1 font-medium",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentSelector.vue.script.js","names":[],"sources":["../../../src/features/multiple-documents/DocumentSelector.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarListbox } from '@scalar/components'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport { computed } from 'vue'\n\nconst props = defineProps<{\n options: { label: string; id: string }[]\n modelValue?: string\n}>()\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', id: string): void\n}>()\n\nconst formattedOptions = computed(() =>\n props.options.map((o) => ({ id: o.id, label: o.label })),\n)\n\nconst selected = computed(() =>\n formattedOptions.value.find((o) => o.id === props.modelValue),\n)\n</script>\n\n<template>\n <div\n v-if=\"options.length > 1\"\n class=\"document-selector
|
|
1
|
+
{"version":3,"file":"DocumentSelector.vue.script.js","names":[],"sources":["../../../src/features/multiple-documents/DocumentSelector.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarListbox } from '@scalar/components'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport { computed } from 'vue'\n\nconst props = defineProps<{\n options: { label: string; id: string }[]\n modelValue?: string\n}>()\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', id: string): void\n}>()\n\nconst formattedOptions = computed(() =>\n props.options.map((o) => ({ id: o.id, label: o.label })),\n)\n\nconst selected = computed(() =>\n formattedOptions.value.find((o) => o.id === props.modelValue),\n)\n</script>\n\n<template>\n <div\n v-if=\"options.length > 1\"\n class=\"document-selector px-3 pt-3\">\n <ScalarListbox\n v-slot=\"{ open }\"\n :modelValue=\"selected\"\n :options=\"formattedOptions\"\n resize\n @update:modelValue=\"(e) => emit('update:modelValue', e.id)\">\n <button\n class=\"group/dropdown-label text-c-2 hover:text-c-1 flex w-full cursor-pointer items-center gap-1 font-medium\"\n type=\"button\">\n <span class=\"overflow-hidden text-base text-ellipsis\">\n {{ selected?.label || 'Select API' }}\n </span>\n <ScalarIconCaretDown\n class=\"size-3 text-current transition-transform\"\n :class=\"{ 'rotate-180': open }\"\n weight=\"bold\" />\n </button>\n </ScalarListbox>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAKA,MAAM,QAAQ;EAKd,MAAM,OAAO;EAIb,MAAM,mBAAmB,eACvB,MAAM,QAAQ,KAAK,OAAO;GAAE,IAAI,EAAE;GAAI,OAAO,EAAE;GAAO,EAAE,CAC1D;EAEA,MAAM,WAAW,eACf,iBAAiB,MAAM,MAAM,MAAM,EAAE,OAAO,MAAM,WAAW,CAC/D;;UAKU,QAAA,QAAQ,SAAM,KAAA,WAAA,EADtB,mBAqBM,OArBN,YAqBM,CAlBJ,YAiBgB,MAAA,cAAA,EAAA;IAfb,YAAY,SAAA;IACZ,SAAS,iBAAA;IACV,QAAA;IACC,uBAAiB,OAAA,OAAA,OAAA,MAAG,MAAM,KAAI,qBAAsB,EAAE,GAAE;;sBAWhD,EAfC,WAAI,CAKd,mBAUS,UAVT,YAUS,CAPP,mBAEO,QAFP,YAEO,gBADF,SAAA,OAAU,SAAK,aAAA,EAAA,EAAA,EAEpB,YAGkB,MAAA,oBAAA,EAAA;KAFhB,OAAK,eAAA,CAAC,4CAA0C,EAAA,cACxB,MAAI,CAAA,CAAA;KAC5B,QAAO"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { authStorage, clientStorage } from "./storage.js";
|
|
2
|
-
import { isClient } from "@scalar/api-client/
|
|
2
|
+
import { isClient } from "@scalar/api-client/blocks/operation-code-sample";
|
|
3
3
|
//#region src/helpers/load-from-perssistance.ts
|
|
4
4
|
/**
|
|
5
5
|
* Loads the default HTTP client from storage and applies it to the workspace.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-from-perssistance.js","names":[],"sources":["../../src/helpers/load-from-perssistance.ts"],"sourcesContent":["import { isClient } from '@scalar/api-client/
|
|
1
|
+
{"version":3,"file":"load-from-perssistance.js","names":[],"sources":["../../src/helpers/load-from-perssistance.ts"],"sourcesContent":["import { isClient } from '@scalar/api-client/blocks/operation-code-sample'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\n\nimport { authStorage, clientStorage } from '@/helpers/storage'\n\n/**\n * Loads the default HTTP client from storage and applies it to the workspace.\n * Only updates if no default client is already set.\n */\nexport const loadClientFromStorage = (store: WorkspaceStore): void => {\n const storedClient = clientStorage().get()\n\n if (isClient(storedClient) && !store.workspace['x-scalar-default-client']) {\n store.update('x-scalar-default-client', storedClient)\n }\n}\n\n/**\n * Loads the authentication data from storage and applies it to the workspace.\n * Only updates if no authentication data is already set.\n */\nexport const loadAuthFromStorage = (store: WorkspaceStore, slug: string): void => {\n const authPersistence = authStorage()\n const auth = authPersistence.getAuth(slug)\n store.auth.load({ [slug]: auth })\n}\n"],"mappings":";;;;;;;AASA,IAAa,yBAAyB,UAAgC;CACpE,MAAM,eAAe,eAAe,CAAC,KAAK;AAE1C,KAAI,SAAS,aAAa,IAAI,CAAC,MAAM,UAAU,2BAC7C,OAAM,OAAO,2BAA2B,aAAa;;;;;;AAQzD,IAAa,uBAAuB,OAAuB,SAAuB;CAEhF,MAAM,OADkB,aAAa,CACR,QAAQ,KAAK;AAC1C,OAAM,KAAK,KAAK,GAAG,OAAO,MAAM,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map-config-plugins.d.ts","sourceRoot":"","sources":["../../src/helpers/map-config-plugins.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"map-config-plugins.d.ts","sourceRoot":"","sources":["../../src/helpers/map-config-plugins.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAA;AAE5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AACnH,OAAO,EAAE,KAAK,WAAW,EAAS,MAAM,KAAK,CAAA;AAE7C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,WAAW,CAAC,yBAAyB,CAAC,EAC9C,aAAa,WAAW,CAAC,kBAAkB,CAAC,KAC3C,YAAY,EAwCd,CAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { watch } from "vue";
|
|
2
2
|
import { buildRequest, getEnvironmentVariables } from "@scalar/workspace-store/request-example";
|
|
3
|
+
import { buildSafeBodyRequest } from "@scalar/helpers/http/can-method-have-body";
|
|
3
4
|
//#region src/helpers/map-config-plugins.ts
|
|
4
5
|
/**
|
|
5
6
|
* Maps API reference configuration callbacks to client plugins.
|
|
@@ -27,7 +28,7 @@ var mapConfigPlugins = (config, environment) => {
|
|
|
27
28
|
if (!plugin.hooks) plugin.hooks = {};
|
|
28
29
|
plugin.hooks.beforeRequest = onBeforeRequest ? async (payload) => {
|
|
29
30
|
await onBeforeRequest({
|
|
30
|
-
request: buildRequest(payload.requestBuilder, { envVariables }).
|
|
31
|
+
request: buildSafeBodyRequest(...buildRequest(payload.requestBuilder, { envVariables }).requestPayload),
|
|
31
32
|
requestBuilder: payload.requestBuilder,
|
|
32
33
|
envVariables
|
|
33
34
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map-config-plugins.js","names":[],"sources":["../../src/helpers/map-config-plugins.ts"],"sourcesContent":["import type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { ApiReferenceConfiguration } from '@scalar/types/api-reference'\nimport { buildRequest, getEnvironmentVariables } from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { type ComputedRef, watch } from 'vue'\n\n/**\n * Maps API reference configuration callbacks to client plugins.\n *\n * This function transforms the legacy onBeforeRequest and onRequestSent callbacks\n * into the new plugin hook system. The mapping is reactive, so changes to the\n * configuration will automatically update the plugin hooks.\n *\n * Note: onRequestSent is mapped to responseReceived hook. This is not a perfect\n * one-to-one mapping, but it maintains backward compatibility with the old API.\n * The old callback receives only the URL string, while the new hook receives\n * the full response object.\n *\n * @param config - Reactive configuration object containing optional hook callbacks\n * @returns Array containing a single plugin with the mapped hooks\n */\nexport const mapConfigPlugins = (\n config: ComputedRef<ApiReferenceConfiguration>,\n environment: ComputedRef<XScalarEnvironment>,\n): ClientPlugin[] => {\n // Create a new plugin with the hooks which is going to be updated by the watcher when config changes\n const plugin: ClientPlugin = { hooks: {} }\n\n watch(\n [() => config.value.onBeforeRequest, () => config.value.onRequestSent, () => environment.value],\n ([onBeforeRequest, onRequestSent, environment]) => {\n // Get the environment variables for the current environment\n const envVariables = getEnvironmentVariables(environment)\n\n // Initialize the hooks object if it doesn't exist\n if (!plugin.hooks) {\n plugin.hooks = {}\n }\n\n plugin.hooks.beforeRequest = onBeforeRequest\n ? async (payload) => {\n await onBeforeRequest({\n // We need to build the request to get the fetch `Request`\n request: buildRequest(payload.requestBuilder, { envVariables }).
|
|
1
|
+
{"version":3,"file":"map-config-plugins.js","names":[],"sources":["../../src/helpers/map-config-plugins.ts"],"sourcesContent":["import { buildSafeBodyRequest } from '@scalar/helpers/http/can-method-have-body'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { ApiReferenceConfiguration } from '@scalar/types/api-reference'\nimport { buildRequest, getEnvironmentVariables } from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { type ComputedRef, watch } from 'vue'\n\n/**\n * Maps API reference configuration callbacks to client plugins.\n *\n * This function transforms the legacy onBeforeRequest and onRequestSent callbacks\n * into the new plugin hook system. The mapping is reactive, so changes to the\n * configuration will automatically update the plugin hooks.\n *\n * Note: onRequestSent is mapped to responseReceived hook. This is not a perfect\n * one-to-one mapping, but it maintains backward compatibility with the old API.\n * The old callback receives only the URL string, while the new hook receives\n * the full response object.\n *\n * @param config - Reactive configuration object containing optional hook callbacks\n * @returns Array containing a single plugin with the mapped hooks\n */\nexport const mapConfigPlugins = (\n config: ComputedRef<ApiReferenceConfiguration>,\n environment: ComputedRef<XScalarEnvironment>,\n): ClientPlugin[] => {\n // Create a new plugin with the hooks which is going to be updated by the watcher when config changes\n const plugin: ClientPlugin = { hooks: {} }\n\n watch(\n [() => config.value.onBeforeRequest, () => config.value.onRequestSent, () => environment.value],\n ([onBeforeRequest, onRequestSent, environment]) => {\n // Get the environment variables for the current environment\n const envVariables = getEnvironmentVariables(environment)\n\n // Initialize the hooks object if it doesn't exist\n if (!plugin.hooks) {\n plugin.hooks = {}\n }\n\n plugin.hooks.beforeRequest = onBeforeRequest\n ? async (payload) => {\n await onBeforeRequest({\n // We need to build the request to get the fetch `Request`\n request: buildSafeBodyRequest(...buildRequest(payload.requestBuilder, { envVariables }).requestPayload),\n requestBuilder: payload.requestBuilder,\n envVariables,\n })\n }\n : undefined\n\n /**\n * Maps onRequestSent to responseReceived hook.\n * The old API only passed the URL string, so we extract it from the request.\n */\n plugin.hooks.responseReceived = onRequestSent\n ? (payload) => {\n onRequestSent(payload.request.url)\n }\n : undefined\n },\n { immediate: true },\n )\n\n return [plugin]\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAsBA,IAAa,oBACX,QACA,gBACmB;CAEnB,MAAM,SAAuB,EAAE,OAAO,EAAE,EAAE;AAE1C,OACE;QAAO,OAAO,MAAM;QAAuB,OAAO,MAAM;QAAqB,YAAY;EAAM,GAC9F,CAAC,iBAAiB,eAAe,iBAAiB;EAEjD,MAAM,eAAe,wBAAwB,YAAY;AAGzD,MAAI,CAAC,OAAO,MACV,QAAO,QAAQ,EAAE;AAGnB,SAAO,MAAM,gBAAgB,kBACzB,OAAO,YAAY;AACjB,SAAM,gBAAgB;IAEpB,SAAS,qBAAqB,GAAG,aAAa,QAAQ,gBAAgB,EAAE,cAAc,CAAC,CAAC,eAAe;IACvG,gBAAgB,QAAQ;IACxB;IACD,CAAC;MAEJ,KAAA;;;;;AAMJ,SAAO,MAAM,mBAAmB,iBAC3B,YAAY;AACX,iBAAc,QAAQ,QAAQ,IAAI;MAEpC,KAAA;IAEN,EAAE,WAAW,MAAM,CACpB;AAED,QAAO,CAAC,OAAO"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { computed, toValue, watch } from "vue";
|
|
2
2
|
import { useFavicon } from "@vueuse/core";
|
|
3
|
-
import { isClient } from "@scalar/api-client/
|
|
3
|
+
import { isClient } from "@scalar/api-client/blocks/operation-code-sample";
|
|
4
4
|
import { useSeoMeta } from "@unhead/vue";
|
|
5
5
|
//#region src/helpers/map-config-to-workspace-store.ts
|
|
6
6
|
var mapConfigToWorkspaceStore = ({ config, store, isDarkMode }) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map-config-to-workspace-store.js","names":[],"sources":["../../src/helpers/map-config-to-workspace-store.ts"],"sourcesContent":["import { isClient } from '@scalar/api-client/
|
|
1
|
+
{"version":3,"file":"map-config-to-workspace-store.js","names":[],"sources":["../../src/helpers/map-config-to-workspace-store.ts"],"sourcesContent":["import { isClient } from '@scalar/api-client/blocks/operation-code-sample'\nimport type { ApiReferenceConfigurationRaw } from '@scalar/types/api-reference'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { useSeoMeta } from '@unhead/vue'\nimport { useFavicon } from '@vueuse/core'\nimport { type MaybeRefOrGetter, type Ref, computed, toValue, watch } from 'vue'\n\nexport const mapConfigToWorkspaceStore = ({\n config,\n store,\n isDarkMode,\n}: {\n config: MaybeRefOrGetter<ApiReferenceConfigurationRaw>\n store: WorkspaceStore\n isDarkMode: Ref<boolean>\n}) => {\n // Update the workspace store if default client changes\n watch(\n () => toValue(config).defaultHttpClient,\n (newValue) => {\n if (newValue) {\n const { targetKey, clientKey } = newValue\n\n const clientId = `${targetKey}/${clientKey}`\n if (isClient(clientId)) {\n store.update('x-scalar-default-client', clientId)\n }\n }\n },\n { immediate: true },\n )\n\n /** Update the dark mode state when props change */\n watch(\n () => toValue(config).darkMode,\n (isDark) => store.update('x-scalar-color-mode', isDark ? 'dark' : 'light'),\n )\n\n // Temporary mapping of isDarkMode until we update the standalone component\n watch(\n () => isDarkMode.value,\n (newIsDark) => store.update('x-scalar-color-mode', newIsDark ? 'dark' : 'light'),\n { immediate: true },\n )\n\n if (toValue(config).metaData) {\n useSeoMeta(toValue(config).metaData)\n }\n\n // Update the active proxy when the proxyUrl changes\n watch(\n () => toValue(config).proxyUrl,\n (newProxyUrl) => store.update('x-scalar-active-proxy', newProxyUrl),\n { immediate: true },\n )\n\n const favicon = computed(() => toValue(config).favicon)\n useFavicon(favicon)\n}\n"],"mappings":";;;;;AAOA,IAAa,6BAA6B,EACxC,QACA,OACA,iBAKI;AAEJ,aACQ,QAAQ,OAAO,CAAC,oBACrB,aAAa;AACZ,MAAI,UAAU;GACZ,MAAM,EAAE,WAAW,cAAc;GAEjC,MAAM,WAAW,GAAG,UAAU,GAAG;AACjC,OAAI,SAAS,SAAS,CACpB,OAAM,OAAO,2BAA2B,SAAS;;IAIvD,EAAE,WAAW,MAAM,CACpB;;AAGD,aACQ,QAAQ,OAAO,CAAC,WACrB,WAAW,MAAM,OAAO,uBAAuB,SAAS,SAAS,QAAQ,CAC3E;AAGD,aACQ,WAAW,QAChB,cAAc,MAAM,OAAO,uBAAuB,YAAY,SAAS,QAAQ,EAChF,EAAE,WAAW,MAAM,CACpB;AAED,KAAI,QAAQ,OAAO,CAAC,SAClB,YAAW,QAAQ,OAAO,CAAC,SAAS;AAItC,aACQ,QAAQ,OAAO,CAAC,WACrB,gBAAgB,MAAM,OAAO,yBAAyB,YAAY,EACnE,EAAE,WAAW,MAAM,CACpB;AAGD,YADgB,eAAe,QAAQ,OAAO,CAAC,QAAQ,CACpC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { apiReferenceConfigurationWithSourceSchema, isConfigurationWithSources } from "@scalar/types/api-reference";
|
|
2
|
-
import { parseJsonOrYaml } from "@scalar/oas-utils/helpers";
|
|
3
2
|
import GithubSlugger from "github-slugger";
|
|
3
|
+
import { parseJsonOrYaml } from "@scalar/oas-utils/helpers";
|
|
4
4
|
//#region src/helpers/normalize-configurations.ts
|
|
5
5
|
/**
|
|
6
6
|
* Take any configuration and return a flat array of configurations.
|
|
@@ -1,3 +1,14 @@
|
|
|
1
1
|
import { type TemplateRef } from 'vue';
|
|
2
|
-
|
|
2
|
+
type UseIntersectionOptions = {
|
|
3
|
+
/** Called when the element stops intersecting. */
|
|
4
|
+
onExit?: () => void;
|
|
5
|
+
/**
|
|
6
|
+
* Whether to immediately fire the intersection as soon as the element is on the screen.
|
|
7
|
+
*
|
|
8
|
+
* When false (default) we use a root margin that is 2% of the viewport height on the middle of the viewport.
|
|
9
|
+
*/
|
|
10
|
+
immediate?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export declare const useIntersection: (el: TemplateRef<HTMLElement | undefined>, onIntersect: () => void, options?: UseIntersectionOptions) => void;
|
|
13
|
+
export {};
|
|
3
14
|
//# sourceMappingURL=use-intersection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-intersection.d.ts","sourceRoot":"","sources":["../../src/hooks/use-intersection.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAAa,MAAM,KAAK,CAAA;AAQjD,eAAO,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"use-intersection.d.ts","sourceRoot":"","sources":["../../src/hooks/use-intersection.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAAa,MAAM,KAAK,CAAA;AAQjD,KAAK,sBAAsB,GAAG;IAC5B,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,eAAO,MAAM,eAAe,GAC1B,IAAI,WAAW,CAAC,WAAW,GAAG,SAAS,CAAC,EACxC,aAAa,MAAM,IAAI,EACvB,UAAU,sBAAsB,SAsBjC,CAAA"}
|
|
@@ -6,14 +6,16 @@ import { useIntersectionObserver } from "@vueuse/core";
|
|
|
6
6
|
* the viewport (~2% of viewport height). Emits only while the target overlaps that line.
|
|
7
7
|
*/
|
|
8
8
|
var VIEWPORT_VERTICAL_CENTER_ROOT_MARGIN = "-49% 0px -49% 0px";
|
|
9
|
-
var useIntersection = (el, onIntersect) => {
|
|
9
|
+
var useIntersection = (el, onIntersect, options) => {
|
|
10
10
|
onMounted(() => {
|
|
11
|
+
const observerOptions = {
|
|
12
|
+
rootMargin: options?.immediate ? "0px 0px 0px 0px" : VIEWPORT_VERTICAL_CENTER_ROOT_MARGIN,
|
|
13
|
+
threshold: 0
|
|
14
|
+
};
|
|
11
15
|
if (el.value) useIntersectionObserver(el, ([entry]) => {
|
|
12
16
|
if (entry?.isIntersecting) onIntersect();
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
threshold: 0
|
|
16
|
-
});
|
|
17
|
+
else options?.onExit?.();
|
|
18
|
+
}, observerOptions);
|
|
17
19
|
});
|
|
18
20
|
};
|
|
19
21
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-intersection.js","names":[],"sources":["../../src/hooks/use-intersection.ts"],"sourcesContent":["import { useIntersectionObserver } from '@vueuse/core'\nimport { type TemplateRef, onMounted } from 'vue'\n\n/**\n * Shrinks the observation root to a thin horizontal strip at the vertical middle of\n * the viewport (~2% of viewport height). Emits only while the target overlaps that line.\n */\nconst VIEWPORT_VERTICAL_CENTER_ROOT_MARGIN = '-49% 0px -49% 0px'\n\nexport const useIntersection = (el: TemplateRef<HTMLElement | undefined
|
|
1
|
+
{"version":3,"file":"use-intersection.js","names":[],"sources":["../../src/hooks/use-intersection.ts"],"sourcesContent":["import { useIntersectionObserver } from '@vueuse/core'\nimport { type TemplateRef, onMounted } from 'vue'\n\n/**\n * Shrinks the observation root to a thin horizontal strip at the vertical middle of\n * the viewport (~2% of viewport height). Emits only while the target overlaps that line.\n */\nconst VIEWPORT_VERTICAL_CENTER_ROOT_MARGIN = '-49% 0px -49% 0px'\n\ntype UseIntersectionOptions = {\n /** Called when the element stops intersecting. */\n onExit?: () => void\n /**\n * Whether to immediately fire the intersection as soon as the element is on the screen.\n *\n * When false (default) we use a root margin that is 2% of the viewport height on the middle of the viewport.\n */\n immediate?: boolean\n}\n\nexport const useIntersection = (\n el: TemplateRef<HTMLElement | undefined>,\n onIntersect: () => void,\n options?: UseIntersectionOptions,\n) => {\n onMounted(() => {\n const observerOptions = {\n rootMargin: options?.immediate ? '0px 0px 0px 0px' : VIEWPORT_VERTICAL_CENTER_ROOT_MARGIN,\n threshold: 0,\n } as const\n\n if (el.value) {\n useIntersectionObserver(\n el,\n ([entry]) => {\n if (entry?.isIntersecting) {\n onIntersect()\n } else {\n options?.onExit?.()\n }\n },\n observerOptions,\n )\n }\n })\n}\n"],"mappings":";;;;;;;AAOA,IAAM,uCAAuC;AAa7C,IAAa,mBACX,IACA,aACA,YACG;AACH,iBAAgB;EACd,MAAM,kBAAkB;GACtB,YAAY,SAAS,YAAY,oBAAoB;GACrD,WAAW;GACZ;AAED,MAAI,GAAG,MACL,yBACE,KACC,CAAC,WAAW;AACX,OAAI,OAAO,eACT,cAAa;OAEb,UAAS,UAAU;KAGvB,gBACD;GAEH"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ClientPlugin } from '@scalar/oas-utils/helpers';
|
|
1
2
|
import type { ApiReferencePlugin as OriginalApiReferencePlugin, SpecificationExtension, ViewComponent } from '@scalar/types/api-reference';
|
|
2
3
|
export type ApiReferencePlugin = OriginalApiReferencePlugin;
|
|
3
4
|
type CreatePluginManagerParams = {
|
|
@@ -17,6 +18,22 @@ export declare const createPluginManager: ({ plugins }: CreatePluginManagerParam
|
|
|
17
18
|
* Get all components for a specific view from registered plugins
|
|
18
19
|
*/
|
|
19
20
|
getViewComponents: (viewName: "content.end") => ViewComponent[];
|
|
21
|
+
/**
|
|
22
|
+
* Notify all plugins that the API Reference has been initialized
|
|
23
|
+
*/
|
|
24
|
+
notifyInit: (config: Record<string, unknown>) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Notify all plugins that the configuration has changed
|
|
27
|
+
*/
|
|
28
|
+
notifyConfigChange: (config: Record<string, unknown>) => void;
|
|
29
|
+
/**
|
|
30
|
+
* Notify all plugins that the API Reference is being destroyed
|
|
31
|
+
*/
|
|
32
|
+
notifyDestroy: () => void;
|
|
33
|
+
/**
|
|
34
|
+
* Get all client plugins provided by registered plugins
|
|
35
|
+
*/
|
|
36
|
+
getApiClientPlugins: () => ClientPlugin[];
|
|
20
37
|
};
|
|
21
38
|
export type PluginManager = ReturnType<typeof createPluginManager>;
|
|
22
39
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-manager.d.ts","sourceRoot":"","sources":["../../src/plugins/plugin-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,IAAI,0BAA0B,EAChD,sBAAsB,EACtB,aAAa,EACd,MAAM,6BAA6B,CAAA;AAEpC,MAAM,MAAM,kBAAkB,GAAG,0BAA0B,CAAA;AAE3D,KAAK,yBAAyB,GAAG;IAC/B,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAA;CAC/B,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,aAAkB,yBAAyB;IAU3E;;OAEG;uCACgC,KAAK,MAAM,EAAE,KAAG,sBAAsB,EAAE;IAc3E;;OAEG;kCAC2B,aAAa,KAAG,aAAa,EAAE;
|
|
1
|
+
{"version":3,"file":"plugin-manager.d.ts","sourceRoot":"","sources":["../../src/plugins/plugin-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EACV,kBAAkB,IAAI,0BAA0B,EAChD,sBAAsB,EACtB,aAAa,EACd,MAAM,6BAA6B,CAAA;AAEpC,MAAM,MAAM,kBAAkB,GAAG,0BAA0B,CAAA;AAE3D,KAAK,yBAAyB,GAAG;IAC/B,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAA;CAC/B,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,aAAkB,yBAAyB;IAU3E;;OAEG;uCACgC,KAAK,MAAM,EAAE,KAAG,sBAAsB,EAAE;IAc3E;;OAEG;kCAC2B,aAAa,KAAG,aAAa,EAAE;IAa7D;;OAEG;yBACkB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;IAMnD;;OAEG;iCAC0B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;IAM3D;;OAEG;yBACgB,IAAI;IAMvB;;OAEG;+BACsB,YAAY,EAAE;CAY1C,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAA"}
|
|
@@ -23,6 +23,20 @@ var createPluginManager = ({ plugins = [] }) => {
|
|
|
23
23
|
if (viewComponents) components.push(...viewComponents);
|
|
24
24
|
}
|
|
25
25
|
return components;
|
|
26
|
+
},
|
|
27
|
+
notifyInit: (config) => {
|
|
28
|
+
for (const plugin of registeredPlugins.values()) plugin.hooks?.onInit?.({ config });
|
|
29
|
+
},
|
|
30
|
+
notifyConfigChange: (config) => {
|
|
31
|
+
for (const plugin of registeredPlugins.values()) plugin.hooks?.onConfigChange?.({ config });
|
|
32
|
+
},
|
|
33
|
+
notifyDestroy: () => {
|
|
34
|
+
for (const plugin of registeredPlugins.values()) plugin.hooks?.onDestroy?.();
|
|
35
|
+
},
|
|
36
|
+
getApiClientPlugins: () => {
|
|
37
|
+
const apiClientPlugins = [];
|
|
38
|
+
for (const plugin of registeredPlugins.values()) if (plugin.apiClientPlugins) apiClientPlugins.push(...plugin.apiClientPlugins);
|
|
39
|
+
return apiClientPlugins;
|
|
26
40
|
}
|
|
27
41
|
};
|
|
28
42
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-manager.js","names":[],"sources":["../../src/plugins/plugin-manager.ts"],"sourcesContent":["import type {\n ApiReferencePlugin as OriginalApiReferencePlugin,\n SpecificationExtension,\n ViewComponent,\n} from '@scalar/types/api-reference'\n\nexport type ApiReferencePlugin = OriginalApiReferencePlugin\n\ntype CreatePluginManagerParams = {\n plugins?: ApiReferencePlugin[]\n}\n\n/**\n * Create the plugin manager store\n *\n * This store manages all plugins registered with the API client\n */\nexport const createPluginManager = ({ plugins = [] }: CreatePluginManagerParams) => {\n const registeredPlugins = new Map<string, ReturnType<ApiReferencePlugin>>()\n\n // Register initial plugins\n plugins.forEach((plugin) => {\n const pluginInstance = plugin()\n registeredPlugins.set(pluginInstance.name, pluginInstance)\n })\n\n return {\n /**\n * Get all extensions with the given name from registered plugins\n */\n getSpecificationExtensions: (name: `x-${string}`): SpecificationExtension[] => {\n const extensions: SpecificationExtension[] = []\n\n for (const plugin of registeredPlugins.values()) {\n for (const extension of plugin.extensions) {\n if (extension.name === name) {\n extensions.push(extension)\n }\n }\n }\n\n return extensions\n },\n\n /**\n * Get all components for a specific view from registered plugins\n */\n getViewComponents: (viewName: 'content.end'): ViewComponent[] => {\n const components: ViewComponent[] = []\n\n for (const plugin of registeredPlugins.values()) {\n const viewComponents = plugin.views?.[viewName]\n if (viewComponents) {\n components.push(...viewComponents)\n }\n }\n\n return components\n },\n }\n}\n\nexport type PluginManager = ReturnType<typeof createPluginManager>\n"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"plugin-manager.js","names":[],"sources":["../../src/plugins/plugin-manager.ts"],"sourcesContent":["import type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type {\n ApiReferencePlugin as OriginalApiReferencePlugin,\n SpecificationExtension,\n ViewComponent,\n} from '@scalar/types/api-reference'\n\nexport type ApiReferencePlugin = OriginalApiReferencePlugin\n\ntype CreatePluginManagerParams = {\n plugins?: ApiReferencePlugin[]\n}\n\n/**\n * Create the plugin manager store\n *\n * This store manages all plugins registered with the API client\n */\nexport const createPluginManager = ({ plugins = [] }: CreatePluginManagerParams) => {\n const registeredPlugins = new Map<string, ReturnType<ApiReferencePlugin>>()\n\n // Register initial plugins\n plugins.forEach((plugin) => {\n const pluginInstance = plugin()\n registeredPlugins.set(pluginInstance.name, pluginInstance)\n })\n\n return {\n /**\n * Get all extensions with the given name from registered plugins\n */\n getSpecificationExtensions: (name: `x-${string}`): SpecificationExtension[] => {\n const extensions: SpecificationExtension[] = []\n\n for (const plugin of registeredPlugins.values()) {\n for (const extension of plugin.extensions) {\n if (extension.name === name) {\n extensions.push(extension)\n }\n }\n }\n\n return extensions\n },\n\n /**\n * Get all components for a specific view from registered plugins\n */\n getViewComponents: (viewName: 'content.end'): ViewComponent[] => {\n const components: ViewComponent[] = []\n\n for (const plugin of registeredPlugins.values()) {\n const viewComponents = plugin.views?.[viewName]\n if (viewComponents) {\n components.push(...viewComponents)\n }\n }\n\n return components\n },\n\n /**\n * Notify all plugins that the API Reference has been initialized\n */\n notifyInit: (config: Record<string, unknown>): void => {\n for (const plugin of registeredPlugins.values()) {\n plugin.hooks?.onInit?.({ config })\n }\n },\n\n /**\n * Notify all plugins that the configuration has changed\n */\n notifyConfigChange: (config: Record<string, unknown>): void => {\n for (const plugin of registeredPlugins.values()) {\n plugin.hooks?.onConfigChange?.({ config })\n }\n },\n\n /**\n * Notify all plugins that the API Reference is being destroyed\n */\n notifyDestroy: (): void => {\n for (const plugin of registeredPlugins.values()) {\n plugin.hooks?.onDestroy?.()\n }\n },\n\n /**\n * Get all client plugins provided by registered plugins\n */\n getApiClientPlugins: (): ClientPlugin[] => {\n const apiClientPlugins: ClientPlugin[] = []\n\n for (const plugin of registeredPlugins.values()) {\n if (plugin.apiClientPlugins) {\n apiClientPlugins.push(...(plugin.apiClientPlugins as ClientPlugin[]))\n }\n }\n\n return apiClientPlugins\n },\n }\n}\n\nexport type PluginManager = ReturnType<typeof createPluginManager>\n"],"mappings":";;;;;;AAkBA,IAAa,uBAAuB,EAAE,UAAU,EAAE,OAAkC;CAClF,MAAM,oCAAoB,IAAI,KAA6C;AAG3E,SAAQ,SAAS,WAAW;EAC1B,MAAM,iBAAiB,QAAQ;AAC/B,oBAAkB,IAAI,eAAe,MAAM,eAAe;GAC1D;AAEF,QAAO;EAIL,6BAA6B,SAAkD;GAC7E,MAAM,aAAuC,EAAE;AAE/C,QAAK,MAAM,UAAU,kBAAkB,QAAQ,CAC7C,MAAK,MAAM,aAAa,OAAO,WAC7B,KAAI,UAAU,SAAS,KACrB,YAAW,KAAK,UAAU;AAKhC,UAAO;;EAMT,oBAAoB,aAA6C;GAC/D,MAAM,aAA8B,EAAE;AAEtC,QAAK,MAAM,UAAU,kBAAkB,QAAQ,EAAE;IAC/C,MAAM,iBAAiB,OAAO,QAAQ;AACtC,QAAI,eACF,YAAW,KAAK,GAAG,eAAe;;AAItC,UAAO;;EAMT,aAAa,WAA0C;AACrD,QAAK,MAAM,UAAU,kBAAkB,QAAQ,CAC7C,QAAO,OAAO,SAAS,EAAE,QAAQ,CAAC;;EAOtC,qBAAqB,WAA0C;AAC7D,QAAK,MAAM,UAAU,kBAAkB,QAAQ,CAC7C,QAAO,OAAO,iBAAiB,EAAE,QAAQ,CAAC;;EAO9C,qBAA2B;AACzB,QAAK,MAAM,UAAU,kBAAkB,QAAQ,CAC7C,QAAO,OAAO,aAAa;;EAO/B,2BAA2C;GACzC,MAAM,mBAAmC,EAAE;AAE3C,QAAK,MAAM,UAAU,kBAAkB,QAAQ,CAC7C,KAAI,OAAO,iBACT,kBAAiB,KAAK,GAAI,OAAO,iBAAoC;AAIzE,UAAO;;EAEV"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type PostHogConfig } from '@scalar/api-client/plugins/posthog';
|
|
2
|
+
import type { ApiReferencePlugin } from '../plugin-manager.js';
|
|
3
|
+
export type { PostHogConfig };
|
|
4
|
+
/**
|
|
5
|
+
* PostHog analytics plugin for the API Reference.
|
|
6
|
+
*
|
|
7
|
+
* Loading this plugin opts in to analytics for both the API Reference
|
|
8
|
+
* and the embedded API Client (tracked as separate products).
|
|
9
|
+
*
|
|
10
|
+
* Respects the `telemetry` configuration option — when set to `false`,
|
|
11
|
+
* capturing is disabled. Reacts dynamically to config changes at runtime.
|
|
12
|
+
*
|
|
13
|
+
* If the plugin is not loaded, no tracking occurs.
|
|
14
|
+
*/
|
|
15
|
+
export declare const PostHogPlugin: (config: PostHogConfig) => ApiReferencePlugin;
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/posthog/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,oCAAoC,CAAA;AAI5F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAE3D,YAAY,EAAE,aAAa,EAAE,CAAA;AAE7B;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,aAAa,KAAG,kBAuDrD,CAAA"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { PostHogClientPlugin } from "@scalar/api-client/plugins/posthog";
|
|
2
|
+
import ph from "posthog-js";
|
|
3
|
+
//#region src/plugins/posthog/index.ts
|
|
4
|
+
/**
|
|
5
|
+
* PostHog analytics plugin for the API Reference.
|
|
6
|
+
*
|
|
7
|
+
* Loading this plugin opts in to analytics for both the API Reference
|
|
8
|
+
* and the embedded API Client (tracked as separate products).
|
|
9
|
+
*
|
|
10
|
+
* Respects the `telemetry` configuration option — when set to `false`,
|
|
11
|
+
* capturing is disabled. Reacts dynamically to config changes at runtime.
|
|
12
|
+
*
|
|
13
|
+
* If the plugin is not loaded, no tracking occurs.
|
|
14
|
+
*/
|
|
15
|
+
var PostHogPlugin = (config) => {
|
|
16
|
+
let posthog = null;
|
|
17
|
+
const clientPlugin = PostHogClientPlugin(config);
|
|
18
|
+
return () => ({
|
|
19
|
+
name: "posthog",
|
|
20
|
+
extensions: [],
|
|
21
|
+
apiClientPlugins: [clientPlugin],
|
|
22
|
+
hooks: {
|
|
23
|
+
onInit({ config: referenceConfig }) {
|
|
24
|
+
if (typeof window === "undefined") return;
|
|
25
|
+
const instance = ph.init(config.apiKey, {
|
|
26
|
+
api_host: config.apiHost,
|
|
27
|
+
...config.uiHost ? { ui_host: config.uiHost } : {},
|
|
28
|
+
...config.defaults ? { defaults: config.defaults } : {},
|
|
29
|
+
opt_out_capturing_by_default: true
|
|
30
|
+
}, "scalar-api-reference");
|
|
31
|
+
if (instance) {
|
|
32
|
+
posthog = instance;
|
|
33
|
+
posthog.register({ product: "api-reference" });
|
|
34
|
+
if (referenceConfig.telemetry !== false) posthog.opt_in_capturing();
|
|
35
|
+
}
|
|
36
|
+
clientPlugin.lifecycle?.onInit?.({ config: referenceConfig });
|
|
37
|
+
},
|
|
38
|
+
onConfigChange({ config: referenceConfig }) {
|
|
39
|
+
if (posthog) if (referenceConfig.telemetry === false) posthog.opt_out_capturing();
|
|
40
|
+
else posthog.opt_in_capturing();
|
|
41
|
+
clientPlugin.lifecycle?.onConfigChange?.({ config: referenceConfig });
|
|
42
|
+
},
|
|
43
|
+
onDestroy() {
|
|
44
|
+
posthog?.reset();
|
|
45
|
+
posthog = null;
|
|
46
|
+
clientPlugin.lifecycle?.onDestroy?.();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
//#endregion
|
|
52
|
+
export { PostHogPlugin };
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/plugins/posthog/index.ts"],"sourcesContent":["import { PostHogClientPlugin, type PostHogConfig } from '@scalar/api-client/plugins/posthog'\nimport type { PostHog } from 'posthog-js'\nimport ph from 'posthog-js'\n\nimport type { ApiReferencePlugin } from '../plugin-manager'\n\nexport type { PostHogConfig }\n\n/**\n * PostHog analytics plugin for the API Reference.\n *\n * Loading this plugin opts in to analytics for both the API Reference\n * and the embedded API Client (tracked as separate products).\n *\n * Respects the `telemetry` configuration option — when set to `false`,\n * capturing is disabled. Reacts dynamically to config changes at runtime.\n *\n * If the plugin is not loaded, no tracking occurs.\n */\nexport const PostHogPlugin = (config: PostHogConfig): ApiReferencePlugin => {\n let posthog: PostHog | null = null\n const clientPlugin = PostHogClientPlugin(config)\n\n return () => ({\n name: 'posthog',\n extensions: [],\n apiClientPlugins: [clientPlugin],\n hooks: {\n onInit({ config: referenceConfig }) {\n if (typeof window === 'undefined') {\n return\n }\n\n const instance = ph.init(\n config.apiKey,\n {\n api_host: config.apiHost,\n ...(config.uiHost ? { ui_host: config.uiHost } : {}),\n ...(config.defaults ? { defaults: config.defaults } : {}),\n opt_out_capturing_by_default: true,\n },\n 'scalar-api-reference',\n )\n\n if (instance) {\n posthog = instance\n posthog.register({ product: 'api-reference' })\n\n if (referenceConfig.telemetry !== false) {\n posthog.opt_in_capturing()\n }\n }\n\n clientPlugin.lifecycle?.onInit?.({ config: referenceConfig })\n },\n onConfigChange({ config: referenceConfig }) {\n if (posthog) {\n if (referenceConfig.telemetry === false) {\n posthog.opt_out_capturing()\n } else {\n posthog.opt_in_capturing()\n }\n }\n\n clientPlugin.lifecycle?.onConfigChange?.({ config: referenceConfig })\n },\n onDestroy() {\n posthog?.reset()\n posthog = null\n\n clientPlugin.lifecycle?.onDestroy?.()\n },\n },\n })\n}\n"],"mappings":";;;;;;;;;;;;;;AAmBA,IAAa,iBAAiB,WAA8C;CAC1E,IAAI,UAA0B;CAC9B,MAAM,eAAe,oBAAoB,OAAO;AAEhD,eAAc;EACZ,MAAM;EACN,YAAY,EAAE;EACd,kBAAkB,CAAC,aAAa;EAChC,OAAO;GACL,OAAO,EAAE,QAAQ,mBAAmB;AAClC,QAAI,OAAO,WAAW,YACpB;IAGF,MAAM,WAAW,GAAG,KAClB,OAAO,QACP;KACE,UAAU,OAAO;KACjB,GAAI,OAAO,SAAS,EAAE,SAAS,OAAO,QAAQ,GAAG,EAAE;KACnD,GAAI,OAAO,WAAW,EAAE,UAAU,OAAO,UAAU,GAAG,EAAE;KACxD,8BAA8B;KAC/B,EACD,uBACD;AAED,QAAI,UAAU;AACZ,eAAU;AACV,aAAQ,SAAS,EAAE,SAAS,iBAAiB,CAAC;AAE9C,SAAI,gBAAgB,cAAc,MAChC,SAAQ,kBAAkB;;AAI9B,iBAAa,WAAW,SAAS,EAAE,QAAQ,iBAAiB,CAAC;;GAE/D,eAAe,EAAE,QAAQ,mBAAmB;AAC1C,QAAI,QACF,KAAI,gBAAgB,cAAc,MAChC,SAAQ,mBAAmB;QAE3B,SAAQ,kBAAkB;AAI9B,iBAAa,WAAW,iBAAiB,EAAE,QAAQ,iBAAiB,CAAC;;GAEvE,YAAY;AACV,aAAS,OAAO;AAChB,cAAU;AAEV,iBAAa,WAAW,aAAa;;GAExC;EACF"}
|