@scalar/api-reference 0.4.0 → 0.5.1

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 (40) hide show
  1. package/README.md +44 -0
  2. package/dist/components/ApiReference.vue.d.ts +0 -24
  3. package/dist/components/ApiReference.vue.d.ts.map +1 -1
  4. package/dist/components/Content/Introduction/BaseUrl.vue.d.ts.map +1 -1
  5. package/dist/components/Content/MarkdownRenderer.vue.d.ts.map +1 -1
  6. package/dist/components/Content/ReferenceEndpoint/Copy.vue.d.ts.map +1 -1
  7. package/dist/components/Content/ReferenceEndpoint/ExampleRequest.vue.d.ts.map +1 -1
  8. package/dist/components/Content/ReferenceEndpoint/{ExampleResponses.vue.d.ts → ExampleResponses/ExampleResponses.vue.d.ts} +1 -1
  9. package/dist/components/Content/ReferenceEndpoint/ExampleResponses/ExampleResponses.vue.d.ts.map +1 -0
  10. package/dist/components/Content/ReferenceEndpoint/ExampleResponses/Headers.vue.d.ts +14 -0
  11. package/dist/components/Content/ReferenceEndpoint/ExampleResponses/Headers.vue.d.ts.map +1 -0
  12. package/dist/components/Content/ReferenceEndpoint/ExampleResponses/SelectExample.vue.d.ts +13 -0
  13. package/dist/components/Content/ReferenceEndpoint/ExampleResponses/SelectExample.vue.d.ts.map +1 -0
  14. package/dist/components/Content/ReferenceEndpoint/ExampleResponses/index.d.ts +2 -0
  15. package/dist/components/Content/ReferenceEndpoint/ExampleResponses/index.d.ts.map +1 -0
  16. package/dist/components/Sidebar.vue.d.ts.map +1 -1
  17. package/dist/helpers/index.d.ts +1 -0
  18. package/dist/helpers/index.d.ts.map +1 -1
  19. package/dist/helpers/mapFromObject.d.ts +8 -0
  20. package/dist/helpers/mapFromObject.d.ts.map +1 -0
  21. package/dist/index.js +16657 -19388
  22. package/dist/types.d.ts +9 -11
  23. package/dist/types.d.ts.map +1 -1
  24. package/package.json +32 -11
  25. package/src/components/ApiReference.vue +0 -4
  26. package/src/components/Content/Introduction/BaseUrl.vue +22 -5
  27. package/src/components/Content/MarkdownRenderer.vue +5 -2
  28. package/src/components/Content/ReferenceEndpoint/Copy.vue +2 -1
  29. package/src/components/Content/ReferenceEndpoint/ExampleRequest.vue +21 -7
  30. package/src/components/Content/ReferenceEndpoint/{ExampleResponses.vue → ExampleResponses/ExampleResponses.vue} +57 -57
  31. package/src/components/Content/ReferenceEndpoint/ExampleResponses/Headers.vue +83 -0
  32. package/src/components/Content/ReferenceEndpoint/ExampleResponses/SelectExample.vue +129 -0
  33. package/src/components/Content/ReferenceEndpoint/ExampleResponses/index.ts +1 -0
  34. package/src/components/Content/ReferenceEndpoint/ReferenceEndpoint.vue +1 -1
  35. package/src/components/Sidebar.vue +6 -2
  36. package/src/components/SimpleTable/SimpleCell.vue +1 -0
  37. package/src/helpers/index.ts +1 -0
  38. package/src/helpers/mapFromObject.ts +11 -0
  39. package/src/types.ts +13 -14
  40. package/dist/components/Content/ReferenceEndpoint/ExampleResponses.vue.d.ts.map +0 -1
package/dist/types.d.ts CHANGED
@@ -1,8 +1,4 @@
1
1
  export type ReferenceProps = {
2
- documentName?: string;
3
- token?: string;
4
- username?: string;
5
- hocusPocusUrl?: string;
6
2
  isEditable?: boolean;
7
3
  showSidebar?: boolean;
8
4
  footerBelowSidebar?: boolean;
@@ -46,15 +42,17 @@ export type Operation = {
46
42
  description: string;
47
43
  information: Information;
48
44
  };
45
+ export type ExampleResponseHeaders = Record<string, {
46
+ description: string;
47
+ schema: {
48
+ type: string;
49
+ format?: string;
50
+ example?: string;
51
+ };
52
+ }>;
49
53
  export type TransformedOperation = Operation & {
50
54
  responses: Record<string, Response & {
51
- headers: Record<string, {
52
- description: string;
53
- schema: {
54
- type: string;
55
- format?: string;
56
- };
57
- }>;
55
+ headers: ExampleResponseHeaders;
58
56
  }>;
59
57
  };
60
58
  export type Tag = {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,CAAC,EAAE,GAAG,EAAE,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;CACzB,CAAA;AACD,MAAM,MAAM,MAAM,GAAG;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,GAAG,CAAA;CACb,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,UAAU,EAAE,CAAA;IACxB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IACnC,QAAQ,EAAE,QAAQ,EAAE,CAAA;IACpB,WAAW,EAAE,WAAW,CAAA;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,EAAE,CAAA;CACf,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,WAAW,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG;IAC7C,SAAS,EAAE,MAAM,CACf,MAAM,EACN,QAAQ,GAAG;QACT,OAAO,EAAE,MAAM,CACb,MAAM,EACN;YACE,WAAW,EAAE,MAAM,CAAA;YACnB,MAAM,EAAE;gBACN,IAAI,EAAE,MAAM,CAAA;gBACZ,MAAM,CAAC,EAAE,MAAM,CAAA;aAChB,CAAA;SACF,CACF,CAAA;KACF,CACF,CAAA;CACF,CAAA;AAED,MAAM,MAAM,GAAG,GAAG;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,oBAAoB,EAAE,CAAA;CACnC,CAAA;AACD,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,CAAC,GAAG,EAAE,MAAM,GAAG;QACb,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;QACd,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,EAAE,CAAA;QAClB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,UAAU,CAAC,EAAE,iBAAiB,CAAA;KAC/B,CAAA;CACF,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAA;QACZ,QAAQ,EAAE,MAAM,EAAE,CAAA;QAClB,UAAU,EAAE,iBAAiB,CAAA;KAC9B,CAAA;CACF,CAAA;AAED,MAAM,MAAM,WAAW,GACnB,kBAAkB,GAClB,iBAAiB,GACjB,YAAY,GACZ,WAAW,GACX,mCAAmC,GACnC,qBAAqB,CAAA;AAEzB,MAAM,MAAM,OAAO,GAAG;KACnB,GAAG,IAAI,WAAW,GAAG,aAAa;CACpC,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,IAAI,GAAG;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,MAAM,GAAG;IACnB,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,IAAI,GAAG;IACjB,IAAI,EAAE,GAAG,EAAE,CAAA;IACX,IAAI,EAAE,IAAI,CAAA;IACV,YAAY,EAAE,YAAY,CAAA;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,27 @@
1
1
  {
2
2
  "name": "@scalar/api-reference",
3
- "version": "0.4.0",
4
- "author": "Scalar",
3
+ "description": "generate beautiful API references from OpenAPI specs",
4
+ "keywords": [
5
+ "vue",
6
+ "vue3",
7
+ "swagger",
8
+ "openapi",
9
+ "spec",
10
+ "reference",
11
+ "documentation",
12
+ "component"
13
+ ],
14
+ "version": "0.5.1",
15
+ "author": "Scalar (https://github.com/scalar)",
16
+ "homepage": "https://github.com/scalar/scalar",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/scalar/scalar.git",
20
+ "directory": "packages/api-reference"
21
+ },
22
+ "bugs": {
23
+ "url": "https://github.com/scalar/scalar/issues/new"
24
+ },
5
25
  "license": "MIT",
6
26
  "engines": {
7
27
  "node": ">=18"
@@ -21,7 +41,6 @@
21
41
  "dependencies": {
22
42
  "@headlessui/vue": "1.7.14",
23
43
  "@vueuse/core": "10.1.2",
24
- "codemirror": "6.0.1",
25
44
  "fuse.js": "^6.6.2",
26
45
  "httpsnippet-lite": "3.0.5",
27
46
  "js-yaml": "4.1.0",
@@ -32,6 +51,7 @@
32
51
  "rehype-format": "4.0.1",
33
52
  "rehype-sanitize": "5.0.1",
34
53
  "rehype-stringify": "9.0.3",
54
+ "remark-breaks": "^3.0.3",
35
55
  "remark-gfm": "3.0.1",
36
56
  "remark-parse": "10.0.2",
37
57
  "remark-rehype": "10.1.0",
@@ -39,14 +59,15 @@
39
59
  "typographic-base": "1.0.4",
40
60
  "unified": "10.1.2",
41
61
  "xmldom": "0.6.0",
42
- "@scalar/api-client": "0.4.0",
43
- "@scalar/default-theme": "0.2.0",
44
- "@scalar/swagger-editor": "0.4.0",
45
- "@scalar/swagger-parser": "0.4.0",
46
- "@scalar/use-clipboard": "0.4.0",
47
- "@scalar/use-keyboard-event": "0.4.0",
48
- "@scalar/use-toasts": "0.4.0",
49
- "@scalar/use-tooltip": "0.4.0"
62
+ "@scalar/api-client": "0.5.1",
63
+ "@scalar/default-theme": "0.2.1",
64
+ "@scalar/swagger-editor": "0.5.1",
65
+ "@scalar/swagger-parser": "0.4.2",
66
+ "@scalar/use-clipboard": "0.4.1",
67
+ "@scalar/use-codemirror": "0.5.0",
68
+ "@scalar/use-keyboard-event": "0.4.1",
69
+ "@scalar/use-toasts": "0.4.1",
70
+ "@scalar/use-tooltip": "0.4.1"
50
71
  },
51
72
  "devDependencies": {
52
73
  "@vitejs/plugin-vue": "4.2.3",
@@ -180,10 +180,6 @@ const breadCrumbs = computed(() => {
180
180
  v-show="showCodeEditor"
181
181
  class="layout-content">
182
182
  <LazyLoadedSwaggerEditor
183
- :documentName="documentName"
184
- :hocusPocusUrl="hocusPocusUrl"
185
- :token="token"
186
- :username="username"
187
183
  :value="specRef"
188
184
  @specUpdate="handleSpecUpdate" />
189
185
  </div>
@@ -1,7 +1,8 @@
1
1
  <script lang="ts" setup>
2
2
  import { useClipboard } from '@scalar/use-clipboard'
3
+ import { computed } from 'vue'
3
4
 
4
- defineProps<{
5
+ const props = defineProps<{
5
6
  server?: {
6
7
  url: string
7
8
  description?: string
@@ -9,23 +10,39 @@ defineProps<{
9
10
  }>()
10
11
 
11
12
  const { copyToClipboard } = useClipboard()
13
+
14
+ const formattedServerUrl = computed(() => {
15
+ const url = props.server?.url ?? ''
16
+ const urlWithoutHtml = url.replace(/(<([^>]+)>)/gi, '')
17
+
18
+ /* Replace all variables (example: {{ baseurl }} with an HTML tag) */
19
+ return urlWithoutHtml.replace(
20
+ /{{\s*([\w.-]+)\s*}}/g,
21
+ '<span class="base-url-variable">{{ $1 }}</span>',
22
+ )
23
+ })
12
24
  </script>
13
25
  <template>
14
26
  <template v-if="server">
15
27
  <a
16
28
  class="base-url"
17
29
  :title="server.description"
18
- @click="copyToClipboard(server.url)">
19
- {{ server.url }}
20
- </a>
30
+ @click="copyToClipboard(server.url)"
31
+ v-html="formattedServerUrl" />
21
32
  </template>
22
33
  </template>
34
+
35
+ <style>
36
+ .base-url-variable {
37
+ color: var(--theme-color-disabled);
38
+ }
39
+ </style>
40
+
23
41
  <style scoped>
24
42
  .base-url {
25
43
  color: var(--theme-color-2);
26
44
  font-size: var(--theme-mini);
27
45
  cursor: pointer;
28
- display: flex;
29
46
  font-family: var(--theme-font-code);
30
47
  flex-direction: column;
31
48
  }
@@ -3,6 +3,7 @@ import rehypeDocument from 'rehype-document'
3
3
  import rehypeFormat from 'rehype-format'
4
4
  import rehypeSanitize, { defaultSchema } from 'rehype-sanitize'
5
5
  import rehypeStringify from 'rehype-stringify'
6
+ import remarkBreaks from 'remark-breaks'
6
7
  import remarkGfm from 'remark-gfm'
7
8
  import remarkParse from 'remark-parse'
8
9
  import remarkRehype from 'remark-rehype'
@@ -20,6 +21,7 @@ watch(
20
21
  () => {
21
22
  unified()
22
23
  .use(remarkParse)
24
+ .use(remarkBreaks)
23
25
  .use(remarkGfm)
24
26
  .use(remarkRehype)
25
27
  .use(remarkTextr, { plugins: [typographicBase] })
@@ -59,6 +61,7 @@ watch(
59
61
  .markdown :deep(h6) {
60
62
  font-size: var(--font-size);
61
63
  margin: 12px 0 6px;
64
+ font-weight: var(--theme-bold);
62
65
  }
63
66
 
64
67
  .markdown :deep(p) {
@@ -123,7 +126,7 @@ watch(
123
126
  border-collapse: collapse;
124
127
  table-layout: fixed;
125
128
  width: 100%;
126
- margin: 0;
129
+ margin: 1em 0;
127
130
  overflow: hidden;
128
131
  box-shadow: 0 0 0 1px var(--theme-border-color);
129
132
  border-radius: var(--theme-radius-lg);
@@ -149,7 +152,7 @@ watch(
149
152
  margin-top: 4px;
150
153
  font-size: var(--theme-small);
151
154
  color: var(--theme-color-2);
152
- line-height: initial;
155
+ line-height: 1.4;
153
156
  }
154
157
  .markdown :deep(td:first-of-type),
155
158
  .markdown :deep(th:first-of-type) {
@@ -9,6 +9,7 @@ import { computed, onMounted, ref } from 'vue'
9
9
 
10
10
  import { useTemplateStore } from '../../../stores/template'
11
11
  import type { Tag } from '../../../types'
12
+ import MarkdownRenderer from '../MarkdownRenderer.vue'
12
13
  import Parameters from './Parameters.vue'
13
14
  import RequestBody from './RequestBody.vue'
14
15
 
@@ -72,7 +73,7 @@ onMounted(() => {
72
73
  </div>
73
74
  <div>
74
75
  <p class="tag-description">
75
- {{ operation.description }}
76
+ <MarkdownRenderer :value="operation.description" />
76
77
  </p>
77
78
  </div>
78
79
  <Parameters
@@ -1,12 +1,12 @@
1
1
  <script setup lang="ts">
2
2
  import {
3
- CodeMirror,
4
3
  generateRequest,
5
4
  useApiClientRequestStore,
6
5
  useApiClientStore,
7
6
  useOperation,
8
7
  } from '@scalar/api-client'
9
8
  import { useClipboard } from '@scalar/use-clipboard'
9
+ import { CodeMirror } from '@scalar/use-codemirror'
10
10
  import {
11
11
  HTTPSnippet,
12
12
  type HarRequest,
@@ -55,26 +55,39 @@ async function generateSnippet() {
55
55
  if (pathVariables) {
56
56
  pathVariables.forEach((variable) => {
57
57
  const variableName = variable.replace(/{|}/g, '')
58
- path = path.replace(variable, variableName.toUpperCase())
58
+ path = path.replace(variable, `__${variableName.toUpperCase()}__`)
59
+ })
60
+ }
61
+
62
+ let url = props.server.url
63
+
64
+ // Replace all variables of the format {something} with the uppercase variable name without the brackets
65
+ const urlVariables = url.match(/{{(.*?)}}/g)
66
+
67
+ if (urlVariables) {
68
+ console.log(urlVariables)
69
+ urlVariables.forEach((variable) => {
70
+ const variableName = variable.replace(/{|}/g, '')
71
+ url = url.replace(variable, `__${variableName}__`)
59
72
  })
60
73
  }
61
74
 
62
75
  if (templateState.preferredLanguage === 'axios') {
63
76
  return generateAxiosCodeFromRequest({
64
77
  method: props.operation.httpVerb.toUpperCase(),
65
- url: `${props.server.url}${path}`,
78
+ url: `${url}${path}`,
66
79
  })
67
80
  } else if (templateState.preferredLanguage === 'laravel') {
68
81
  return generateLaravelCodeFromRequest({
69
82
  method: props.operation.httpVerb.toUpperCase(),
70
- url: `${props.server.url}${path}`,
83
+ url: `${url}${path}`,
71
84
  })
72
85
  }
73
86
 
74
87
  try {
75
88
  const snippet = new HTTPSnippet({
76
89
  method: props.operation.httpVerb.toUpperCase(),
77
- url: `${props.server.url}${path}`,
90
+ url: `${url}${path}`,
78
91
  } as HarRequest)
79
92
  const output = (await snippet.convert(
80
93
  templateState.preferredLanguage as TargetId,
@@ -176,9 +189,10 @@ const availableLanguages = computed(() => {
176
189
  <!-- @vue-ignore -->
177
190
  <CodeMirror
178
191
  :content="CodeMirrorValue"
192
+ :forceDarkMode="true"
179
193
  :languages="CodeMirrorLanguages"
180
- :lineNumbers="true"
181
- :readOnly="true" />
194
+ lineNumbers
195
+ readOnly />
182
196
  </CardContent>
183
197
  <CardFooter muted>
184
198
  <button
@@ -1,23 +1,19 @@
1
1
  <script lang="ts" setup>
2
- import { CodeMirror, type HttpHeader, httpHeaders } from '@scalar/api-client'
3
2
  import { useClipboard } from '@scalar/use-clipboard'
3
+ import { CodeMirror } from '@scalar/use-codemirror'
4
4
  import { computed, ref } from 'vue'
5
5
 
6
- import type { TransformedOperation } from '../../../types'
6
+ import type { TransformedOperation } from '../../../../types'
7
7
  import {
8
8
  Card,
9
9
  CardContent,
10
10
  CardFooter,
11
11
  CardTab,
12
12
  CardTabHeader,
13
- } from '../../Card'
14
- import { Icon } from '../../Icon'
15
- import {
16
- SimpleCell,
17
- SimpleHeader,
18
- SimpleRow,
19
- SimpleTable,
20
- } from '../../SimpleTable'
13
+ } from '../../../Card'
14
+ import { Icon } from '../../../Icon'
15
+ import Headers from './Headers.vue'
16
+ import SelectExample from './SelectExample.vue'
21
17
 
22
18
  const props = defineProps<{ operation: TransformedOperation }>()
23
19
 
@@ -45,29 +41,24 @@ const currentResponse = computed(() => {
45
41
  return props.operation.responses?.[currentStatusCode]
46
42
  })
47
43
 
48
- const currentResponseJsonBody = computed(() => {
49
- return currentResponse.value?.content?.['application/json']?.body
44
+ const currentResponseExamples = computed(() => {
45
+ const examples =
46
+ currentResponse.value?.content?.['application/json']?.examples
47
+
48
+ if (examples) {
49
+ return JSON.parse(examples)
50
+ }
51
+
52
+ return false
53
+ })
54
+
55
+ const currentResponseExample = computed(() => {
56
+ return currentResponse.value?.content?.['application/json']?.example
50
57
  })
51
58
 
52
59
  const changeTab = (index: number) => {
53
60
  selectedResponseIndex.value = index
54
61
  }
55
-
56
- const getDocumentationUrlForHttpHeader = (headerName: string) => {
57
- return httpHeaders.find((header: HttpHeader) => {
58
- return header.name.toLowerCase() === headerName.toLowerCase()
59
- })?.url
60
- }
61
-
62
- // Make the first letter and all letters after a - uppercase
63
- const formatHeaderName = (headerName: string) => {
64
- return headerName
65
- .split('-')
66
- .map((word) => {
67
- return word.charAt(0).toUpperCase() + word.slice(1)
68
- })
69
- .join('-')
70
- }
71
62
  </script>
72
63
  <template>
73
64
  <Card v-if="orderedStatusCodes.length">
@@ -82,10 +73,10 @@ const formatHeaderName = (headerName: string) => {
82
73
 
83
74
  <template #actions>
84
75
  <button
85
- v-if="currentResponseJsonBody"
76
+ v-if="currentResponseExample"
86
77
  class="code-copy"
87
78
  type="button"
88
- @click="() => copyToClipboard(currentResponseJsonBody)">
79
+ @click="() => copyToClipboard(currentResponseExample)">
89
80
  <Icon
90
81
  src="solid/interface-copy-clipboard"
91
82
  width="10px" />
@@ -95,35 +86,24 @@ const formatHeaderName = (headerName: string) => {
95
86
  <CardContent
96
87
  v-if="currentResponse.headers"
97
88
  muted>
98
- <SimpleTable>
99
- <SimpleRow>
100
- <SimpleHeader>Header</SimpleHeader>
101
- <SimpleHeader>Description</SimpleHeader>
102
- </SimpleRow>
103
- <SimpleRow
104
- v-for="(data, header) in currentResponse.headers"
105
- :key="header">
106
- <SimpleCell
107
- :href="getDocumentationUrlForHttpHeader(header)"
108
- :strong="true"
109
- :wrap="false">
110
- {{ formatHeaderName(header) }}
111
- </SimpleCell>
112
- <SimpleCell>{{ data.description }}</SimpleCell>
113
- </SimpleRow>
114
- </SimpleTable>
89
+ <Headers :headers="currentResponse.headers" />
115
90
  </CardContent>
116
91
  <CardContent muted>
117
- <CodeMirror
118
- v-show="currentResponseJsonBody"
119
- :content="currentResponseJsonBody"
120
- :languages="['json']"
121
- readOnly />
122
- <div
123
- v-if="!currentResponseJsonBody"
124
- class="scalar-api-reference__empty-state">
125
- No Body
126
- </div>
92
+ <template v-if="currentResponseExamples">
93
+ <SelectExample :examples="currentResponseExamples" />
94
+ </template>
95
+ <template v-else>
96
+ <CodeMirror
97
+ v-show="currentResponseExample"
98
+ :content="currentResponseExample"
99
+ :languages="['json']"
100
+ readOnly />
101
+ <div
102
+ v-if="!currentResponseExample"
103
+ class="scalar-api-reference__empty-state">
104
+ No Body
105
+ </div>
106
+ </template>
127
107
  </CardContent>
128
108
  <CardFooter
129
109
  v-if="currentResponse?.description"
@@ -165,4 +145,24 @@ const formatHeaderName = (headerName: string) => {
165
145
  padding: 20px;
166
146
  color: var(--theme-color-2);
167
147
  }
148
+
149
+ .schema-type {
150
+ font-size: var(--theme-micro);
151
+ color: var(--theme-color-2);
152
+ font-weight: var(--theme-semibold);
153
+ background: var(--theme-background-3);
154
+ padding: 2px 4px;
155
+ border-radius: 4px;
156
+ margin-right: 4px;
157
+ }
158
+ .schema-example {
159
+ font-size: var(--theme-micro);
160
+ color: var(--theme-color-2);
161
+ font-weight: var(--theme-semibold);
162
+ }
163
+
164
+ .example-response-tab {
165
+ display: block;
166
+ margin: 6px;
167
+ }
168
168
  </style>
@@ -0,0 +1,83 @@
1
+ <script lang="ts" setup>
2
+ import { type HttpHeader, httpHeaders } from '@scalar/api-client'
3
+ import { computed } from 'vue'
4
+
5
+ import { mapFromObject } from '../../../../helpers'
6
+ import type { ExampleResponseHeaders } from '../../../../types'
7
+ import {
8
+ SimpleCell,
9
+ SimpleHeader,
10
+ SimpleRow,
11
+ SimpleTable,
12
+ } from '../../../SimpleTable'
13
+
14
+ const props = defineProps<{
15
+ headers: ExampleResponseHeaders
16
+ }>()
17
+
18
+ const getDocumentationUrlForHttpHeader = (headerName: string) => {
19
+ return httpHeaders.find((header: HttpHeader) => {
20
+ return header.name.toLowerCase() === headerName.toLowerCase()
21
+ })?.url
22
+ }
23
+
24
+ // Make the first letter and all letters after a - uppercase
25
+ const formatHeaderName = (headerName: string) => {
26
+ return headerName
27
+ .split('-')
28
+ .map((word) => {
29
+ return word.charAt(0).toUpperCase() + word.slice(1)
30
+ })
31
+ .join('-')
32
+ }
33
+
34
+ const headersHaveDescription = computed(() => {
35
+ const headers = mapFromObject(props.headers)
36
+
37
+ return headers.some((header: any) => {
38
+ return header.value.description
39
+ })
40
+ })
41
+
42
+ const headersHaveSchema = computed(() => {
43
+ const headers = mapFromObject(props.headers)
44
+
45
+ return headers.some((header: any) => {
46
+ return header.value.schema
47
+ })
48
+ })
49
+ </script>
50
+
51
+ <template>
52
+ <SimpleTable>
53
+ <SimpleRow>
54
+ <SimpleHeader>Header</SimpleHeader>
55
+ <SimpleHeader v-if="headersHaveDescription">Description</SimpleHeader>
56
+ <SimpleHeader v-if="headersHaveSchema">Value</SimpleHeader>
57
+ </SimpleRow>
58
+ <SimpleRow
59
+ v-for="(data, header) in headers"
60
+ :key="header">
61
+ <SimpleCell
62
+ :href="getDocumentationUrlForHttpHeader(header)"
63
+ :strong="true"
64
+ :wrap="false">
65
+ {{ formatHeaderName(header) }}
66
+ </SimpleCell>
67
+ <SimpleCell v-if="headersHaveDescription">{{ data }}</SimpleCell>
68
+ <SimpleCell v-if="headersHaveSchema">
69
+ <span v-if="data.schema.example">
70
+ <code class="schema-example">{{ data.schema.example }}</code>
71
+ </span>
72
+ <code
73
+ v-else-if="data.schema.type"
74
+ class="schema-type">
75
+ {{ data.schema.type }}
76
+ </code>
77
+ <code v-else>
78
+ {{ data.schema }}
79
+ </code>
80
+ </SimpleCell>
81
+ </SimpleRow>
82
+ </SimpleTable>
83
+ </template>
@@ -0,0 +1,129 @@
1
+ <script lang="ts" setup>
2
+ import {
3
+ Listbox,
4
+ ListboxButton,
5
+ ListboxOption,
6
+ ListboxOptions,
7
+ } from '@headlessui/vue'
8
+ import { CodeMirror } from '@scalar/use-codemirror'
9
+ import { ref } from 'vue'
10
+
11
+ import { mapFromObject } from '../../../../helpers'
12
+ import { Icon } from '../../../Icon'
13
+
14
+ const props = defineProps<{ examples: Record<string, any> }>()
15
+
16
+ const examples = mapFromObject(props.examples)
17
+ const selectedExample = ref(examples[0])
18
+ </script>
19
+ <template>
20
+ <div class="example-switcher">
21
+ <label
22
+ class="listbox-label"
23
+ for="listbox-button">
24
+ Select Example
25
+ </label>
26
+ <Listbox v-model="selectedExample">
27
+ <ListboxButton
28
+ id="listbox-button"
29
+ class="listbox-button">
30
+ <div class="listbox-button-content">
31
+ <div class="listbox-button-label">
32
+ {{ selectedExample.value.summary ?? selectedExample.key }}
33
+ </div>
34
+ <div>
35
+ <Icon
36
+ class="icon"
37
+ src="line/arrow-chevron-down" />
38
+ </div>
39
+ </div>
40
+ </ListboxButton>
41
+
42
+ <ListboxOptions class="listbox-options">
43
+ <ListboxOption
44
+ v-for="example in examples"
45
+ :key="example.key"
46
+ class="listbox-option"
47
+ :value="example">
48
+ {{ example.value.summary ?? example.key }}
49
+ </ListboxOption>
50
+ </ListboxOptions>
51
+ </Listbox>
52
+ <CodeMirror
53
+ :content="JSON.stringify(selectedExample.value.value, null, 2)"
54
+ :languages="['json']"
55
+ readOnly />
56
+ </div>
57
+ </template>
58
+
59
+ <style scoped>
60
+ .example-switcher {
61
+ display: flex;
62
+ gap: 6px;
63
+ flex-direction: column;
64
+ }
65
+
66
+ .listbox-label {
67
+ font-size: var(--theme-mini);
68
+ font-weight: var(--theme-semibold);
69
+ margin: 0 4px;
70
+ color: var(--theme-color-2);
71
+ }
72
+
73
+ .listbox-button {
74
+ border: 1px solid var(--theme-border-color);
75
+ background: var(--theme-background-1);
76
+ padding: 6px 12px;
77
+ border-radius: var(--theme-radius);
78
+ text-align: left;
79
+ display: block;
80
+ font-size: var(--theme-mini);
81
+ }
82
+
83
+ .listbox-button-content {
84
+ display: flex;
85
+ align-items: center;
86
+ justify-content: space-between;
87
+ }
88
+
89
+ .listbox-button-label {
90
+ white-space: nowrap;
91
+ overflow: hidden;
92
+ text-overflow: ellipsis;
93
+ }
94
+
95
+ .listbox-options {
96
+ background: var(--theme-background-1);
97
+ padding: 6px 6px;
98
+ border-radius: var(--theme-radius-lg);
99
+ margin-top: 4px;
100
+ box-shadow: var(--theme-shadow-2);
101
+ position: absolute;
102
+ margin: 0 1px;
103
+ transform: translateY(-50%);
104
+ z-index: 100;
105
+ }
106
+
107
+ .listbox-option {
108
+ padding: 6px 12px;
109
+ cursor: pointer;
110
+ color: var(--theme-color-1);
111
+ border-radius: var(--theme-radius);
112
+ margin: 2px 0;
113
+ }
114
+
115
+ .listbox-option[data-headlessui-state='selected'] {
116
+ background: var(--theme-background-2);
117
+ }
118
+
119
+ .listbox-option:hover {
120
+ background: var(--theme-background-2);
121
+ color: var(--theme-color-2);
122
+ }
123
+
124
+ .icon {
125
+ width: 13px;
126
+ height: 13px;
127
+ color: var(--theme-color-3);
128
+ }
129
+ </style>