UNPKG

vitepress-openapi

Version:

Generate VitePress API Documentation from OpenAPI Specification.

1,131 lines (962 loc) 32.4 kB
import type MarkdownIt from 'markdown-it' import type { Ref, UnwrapNestedRefs } from 'vue' import type { OARequest } from '../lib/codeSamples/request' import type { OperationSlot, ParsedOperation } from '../types' import vitesseDark from '@shikijs/themes/vitesse-dark' import vitesseLight from '@shikijs/themes/vitesse-light' import { useDark } from '@vueuse/core' import { ref } from 'vue' import { generateCodeSample } from '../lib/codeSamples/generateCodeSample' import { deepUnref } from '../lib/utils/deepUnref' import { locales } from '../locales' function ensureNestedProperty<T, K extends keyof T>(obj: T, key: K): Exclude<NonNullable<T[K]>, false> { if (!obj[key]) { obj[key] = {} as T[K] } return obj[key] as Exclude<NonNullable<T[K]>, false> } function ensureRefProperty<T, K extends keyof T, V>(obj: T, key: K, propName: string, value: V): Ref<V> { const container = ensureNestedProperty(obj, key) as any if (!container[propName]) { container[propName] = ref(value) } else if (value !== undefined) { container[propName].value = value } return container[propName] } function ensureNestedRefProperty<V>(obj: any, path: string[], propName: string, value: V): Ref<V> { let current = obj for (const segment of path) { current = ensureNestedProperty(current, segment) } if (!current[propName]) { current[propName] = ref(value) } else if (value !== undefined) { current[propName].value = value } return current[propName] } export type BodyViewType = 'schema' | 'contentType' | 'autogenerated' export type JsonRendererType = 'vue-json-pretty' | 'shiki' | string export type ResponseCodeSelectorType = 'tabs' | 'select' export type OperationColsType = 1 | 2 export type OperationBadges = 'deprecated' | 'operationId' export type PlaygroundJsonEditorMode = 'text' | 'tree' | 'table' export type Languages = 'es' | 'en' | 'ja' | 'pt-BR' | 'zh' | string export type Messages = Record<Languages, Record<string, string>> export interface ThemeConfig { highlighterTheme?: { light?: any dark?: any } } export interface PathConfig { showBaseURL?: Ref<boolean> } export interface RequestConfig { defaultView?: Ref<BodyViewType> } export interface JsonViewerConfig { deep?: Ref<number> renderer?: Ref<JsonRendererType> } export interface SchemaViewerConfig { deep?: Ref<number> } export interface HeadingLevels { h1?: number h2?: number h3?: number h4?: number h5?: number h6?: number } export interface ResponseConfig { responseCodeSelector?: Ref<ResponseCodeSelectorType> maxTabs?: Ref<number> body?: { defaultView?: Ref<BodyViewType> } } export interface PlaygroundConfig { jsonEditor?: { mode?: Ref<PlaygroundJsonEditorMode> mainMenuBar?: Ref<boolean> navigationBar?: Ref<boolean> statusBar?: Ref<boolean> } } export interface SecurityConfig { defaultScheme?: Ref<string | null> } export interface OperationConfig { badges?: Ref<OperationBadges[]> slots?: Ref<OperationSlot[]> /** @deprecated Use server.getServers instead */ getServers?: GetServersFunction | null hiddenSlots?: Ref<OperationSlot[]> cols?: Ref<OperationColsType> defaultBaseUrl?: string } export interface AvailableLocale { code: string label: string } export interface I18nConfig { locale?: Ref<Languages> fallbackLocale?: Ref<Languages> messages?: Messages availableLocales?: AvailableLocale[] } export interface SpecConfig { groupByTags?: Ref<boolean> collapsePaths?: Ref<boolean> showPathsSummary?: Ref<boolean> avoidCirculars?: Ref<boolean> lazyRendering?: Ref<boolean> defaultTag?: string defaultTagDescription?: string wrapExamples?: boolean disableDownload?: Ref<boolean> } export interface ServerConfig { allowCustomServer?: boolean getServers?: GetServersFunction | null } export interface OperationLinkConfig { linkPrefix?: string transformHref?: (href: string) => string } export interface MarkdownConfig { operationLink?: OperationLinkConfig | false externalLinksNewTab?: boolean config?: (md: MarkdownIt) => MarkdownIt | undefined } export interface UseThemeConfig { theme?: Partial<ThemeConfig> path?: Partial<PathConfig> requestBody?: Partial<RequestConfig> jsonViewer?: Partial<JsonViewerConfig> schemaViewer?: Partial<SchemaViewerConfig> headingLevels?: Partial<HeadingLevels> response?: Partial<ResponseConfig> playground?: Partial<PlaygroundConfig> security?: Partial<SecurityConfig> operation?: Partial<OperationConfig> i18n?: Partial<I18nConfig> spec?: Partial<SpecConfig> codeSamples?: Partial<CodeSamplesConfig> linksPrefixes?: Partial<LinksPrefixesConfig> server?: Partial<ServerConfig> markdown?: Partial<MarkdownConfig> } export interface CodeSamplesConfig { langs: string[] defaultLang: string availableLanguages: LanguageConfig[] generator: GeneratorFunction defaultHeaders: Record<string, string> } export interface LinksPrefixesConfig { tags: string operations: string } interface LanguageConfig { lang: string label: string highlighter: string icon?: string } export type PartialUseThemeConfig = Partial<UnwrapNestedRefs<UseThemeConfig>> type GeneratorFunction = (lang: string, request: OARequest) => Promise<string> type GetServersFunction = ({ method, path, operation }: { method: string, path: string, operation: ParsedOperation }) => string[] | null export const DEFAULT_OPERATION_SLOTS: OperationSlot[] = [ 'header', 'path', 'description', 'security', 'parameters', 'request-body', 'responses', 'playground', 'code-samples', 'branding', 'footer', ] export const DEFAULT_BASE_URL = 'http://localhost' export const availableLanguages: LanguageConfig[] = [ { lang: 'curl', label: 'cURL', highlighter: 'bash', icon: 'curl', }, { lang: 'javascript', label: 'JavaScript', highlighter: 'javascript', icon: '.js', }, { lang: 'php', label: 'PHP', highlighter: 'php', icon: '.php', }, { lang: 'python', label: 'Python', highlighter: 'python', icon: '.py', }, ] const DEFAULT_OPERATIONS_PREFIX = '/operations/' const defaultValues = { theme: { highlighterTheme: { light: vitesseLight, dark: vitesseDark, }, }, path: { showBaseURL: false, }, requestBody: { defaultView: 'contentType' as BodyViewType, }, jsonViewer: { deep: Number.POSITIVE_INFINITY, renderer: 'vue-json-pretty' as JsonRendererType, }, schemaViewer: { deep: 1, }, headingLevels: { h1: 1, h2: 2, h3: 3, h4: 4, h5: 5, h6: 6, }, response: { responseCodeSelector: 'tabs' as ResponseCodeSelectorType, maxTabs: 5, body: { defaultView: 'contentType' as BodyViewType, }, }, playground: { jsonEditor: { mode: 'tree' as PlaygroundJsonEditorMode, mainMenuBar: false, navigationBar: false, statusBar: false, }, }, security: { defaultScheme: null as string | null, }, operation: { badges: ['deprecated'] as OperationBadges[], slots: DEFAULT_OPERATION_SLOTS, hiddenSlots: [] as OperationSlot[], cols: 2 as OperationColsType, defaultBaseUrl: DEFAULT_BASE_URL, getServers: null, }, i18n: { locale: 'en' as Languages, fallbackLocale: 'en' as Languages, messages: locales, availableLocales: [ { code: 'en', label: 'English', }, { code: 'es', label: 'Español', }, { code: 'ja', label: 'Japanese', }, { code: 'pt-BR', label: 'Português (Brasil)', }, { code: 'zh', label: '中文', }, ], }, spec: { groupByTags: true, collapsePaths: false, showPathsSummary: true, avoidCirculars: false, lazyRendering: false, defaultTag: 'Default', defaultTagDescription: '', wrapExamples: true, disableDownload: false, }, codeSamples: { langs: [ 'curl', 'javascript', 'php', 'python', ], defaultLang: 'curl', availableLanguages, generator: (lang: string, request: OARequest) => generateCodeSample(lang, request), defaultHeaders: {}, }, linksPrefixes: { tags: '/tags/', operations: DEFAULT_OPERATIONS_PREFIX, }, server: { allowCustomServer: false, getServers: null, }, markdown: { operationLink: { linkPrefix: DEFAULT_OPERATIONS_PREFIX, }, externalLinksNewTab: false, config: undefined, }, } const themeConfig: UseThemeConfig = { theme: { highlighterTheme: { light: defaultValues.theme.highlighterTheme.light, dark: defaultValues.theme.highlighterTheme.dark, }, }, path: { showBaseURL: ref(defaultValues.path.showBaseURL), }, requestBody: { defaultView: ref(defaultValues.requestBody.defaultView), }, jsonViewer: { deep: ref(defaultValues.jsonViewer.deep), renderer: ref(defaultValues.jsonViewer.renderer), }, schemaViewer: { deep: ref(defaultValues.schemaViewer.deep), }, headingLevels: { ...defaultValues.headingLevels, }, response: { responseCodeSelector: ref(defaultValues.response.responseCodeSelector), maxTabs: ref(defaultValues.response.maxTabs), body: { defaultView: ref(defaultValues.response.body.defaultView), }, }, playground: { jsonEditor: { mode: ref(defaultValues.playground.jsonEditor.mode), mainMenuBar: ref(defaultValues.playground.jsonEditor.mainMenuBar), navigationBar: ref(defaultValues.playground.jsonEditor.navigationBar), statusBar: ref(defaultValues.playground.jsonEditor.statusBar), }, }, security: { defaultScheme: ref(defaultValues.security.defaultScheme), }, operation: { badges: ref(defaultValues.operation.badges), slots: ref(defaultValues.operation.slots), hiddenSlots: ref(defaultValues.operation.hiddenSlots), cols: ref(defaultValues.operation.cols), defaultBaseUrl: defaultValues.operation.defaultBaseUrl, getServers: defaultValues.operation.getServers, }, i18n: { locale: ref(defaultValues.i18n.locale), fallbackLocale: ref(defaultValues.i18n.fallbackLocale), messages: defaultValues.i18n.messages, availableLocales: defaultValues.i18n.availableLocales, }, spec: { groupByTags: ref(defaultValues.spec.groupByTags), collapsePaths: ref(defaultValues.spec.collapsePaths), showPathsSummary: ref(defaultValues.spec.showPathsSummary), avoidCirculars: ref(defaultValues.spec.avoidCirculars), lazyRendering: ref(defaultValues.spec.lazyRendering), defaultTag: defaultValues.spec.defaultTag, defaultTagDescription: defaultValues.spec.defaultTagDescription, wrapExamples: defaultValues.spec.wrapExamples, disableDownload: ref(defaultValues.spec.disableDownload), }, codeSamples: { langs: defaultValues.codeSamples.langs, defaultLang: defaultValues.codeSamples.defaultLang, availableLanguages: defaultValues.codeSamples.availableLanguages, generator: defaultValues.codeSamples.generator, defaultHeaders: defaultValues.codeSamples.defaultHeaders, }, linksPrefixes: { tags: defaultValues.linksPrefixes.tags, operations: defaultValues.linksPrefixes.operations, }, server: { allowCustomServer: defaultValues.server.allowCustomServer, getServers: defaultValues.server.getServers, }, markdown: { operationLink: { linkPrefix: defaultValues.markdown.operationLink.linkPrefix, }, externalLinksNewTab: defaultValues.markdown.externalLinksNewTab, config: defaultValues.markdown.config, }, } const isDark = useDark({ storageKey: 'vitepress-theme-appearance', }) export function useTheme(initialConfig: PartialUseThemeConfig = {}) { setConfig(initialConfig) function setConfig(config: PartialUseThemeConfig) { if (!config || !Object.keys(config).length) { return } // Theme and highlighter if (config.theme?.highlighterTheme) { setHighlighterTheme(config.theme.highlighterTheme) } // Path if (config.path?.showBaseURL !== undefined) { ensureRefProperty(themeConfig, 'path', 'showBaseURL', config.path.showBaseURL) } // Request body if (config.requestBody?.defaultView !== undefined) { ensureRefProperty(themeConfig, 'requestBody', 'defaultView', config.requestBody.defaultView) } // JSON viewer if (config.jsonViewer?.deep !== undefined) { ensureRefProperty(themeConfig, 'jsonViewer', 'deep', config.jsonViewer.deep) } if (config.jsonViewer?.renderer !== undefined) { ensureRefProperty(themeConfig, 'jsonViewer', 'renderer', config.jsonViewer.renderer) } // Schema viewer if (config.schemaViewer?.deep !== undefined) { ensureRefProperty(themeConfig, 'schemaViewer', 'deep', config.schemaViewer.deep) } // Heading levels if (config.headingLevels !== undefined) { setHeadingLevels(config.headingLevels) } // Response if (config.response?.responseCodeSelector !== undefined) { ensureRefProperty(themeConfig, 'response', 'responseCodeSelector', config.response.responseCodeSelector) } if (config.response?.maxTabs !== undefined) { ensureRefProperty(themeConfig, 'response', 'maxTabs', config.response.maxTabs) } if (config.response?.body?.defaultView !== undefined) { ensureNestedRefProperty(themeConfig, ['response', 'body'], 'defaultView', config.response.body.defaultView) } // Playground if (config.playground?.jsonEditor?.mode !== undefined) { ensureNestedRefProperty(themeConfig, ['playground', 'jsonEditor'], 'mode', config.playground.jsonEditor.mode) } if (config.playground?.jsonEditor?.mainMenuBar !== undefined) { ensureNestedRefProperty(themeConfig, ['playground', 'jsonEditor'], 'mainMenuBar', config.playground.jsonEditor.mainMenuBar) } if (config.playground?.jsonEditor?.navigationBar !== undefined) { ensureNestedRefProperty(themeConfig, ['playground', 'jsonEditor'], 'navigationBar', config.playground.jsonEditor.navigationBar) } if (config.playground?.jsonEditor?.statusBar !== undefined) { ensureNestedRefProperty(themeConfig, ['playground', 'jsonEditor'], 'statusBar', config.playground.jsonEditor.statusBar) } // Security if (config.security?.defaultScheme !== undefined) { ensureRefProperty(themeConfig, 'security', 'defaultScheme', config.security.defaultScheme) } // Operation if (config.operation?.badges !== undefined) { ensureRefProperty(themeConfig, 'operation', 'badges', config.operation.badges) } if (config.operation?.slots !== undefined) { ensureRefProperty(themeConfig, 'operation', 'slots', config.operation.slots) } if (config.operation?.hiddenSlots !== undefined) { ensureRefProperty(themeConfig, 'operation', 'hiddenSlots', config.operation.hiddenSlots) } if (config.operation?.cols !== undefined) { ensureRefProperty(themeConfig, 'operation', 'cols', config.operation.cols) } if (config.operation?.defaultBaseUrl !== undefined) { setOperationDefaultBaseUrl(config.operation.defaultBaseUrl) } if (config.operation?.getServers !== undefined) { setOperationServers(config.operation.getServers) } // i18n if (config.i18n !== undefined) { setI18nConfig(config.i18n) } // Spec if (config.spec !== undefined) { setSpecConfig(config.spec) } // Code samples if (config.codeSamples !== undefined) { setCodeSamplesConfig(config.codeSamples) } // Links prefixes if (config.linksPrefixes !== undefined) { setLinksPrefixesConfig(config.linksPrefixes) } // Server if (config.server !== undefined) { setServerConfig(config.server) } // Markdown if (config.markdown !== undefined) { setMarkdownConfig(config.markdown) } } function reset() { setConfig(defaultValues) } function getState() { return deepUnref(themeConfig) } function getLocale(): Languages { return themeConfig?.i18n?.locale?.value || 'en' } /** * @deprecated Use `setI18nConfig({ locale: value })` instead. */ function setLocale(value: Languages) { console.warn('`setLocale` is deprecated. Use `setI18nConfig({ locale: value })` instead.') // @ts-expect-error: This is a valid expression. themeConfig.i18n.locale.value = value } function getHighlighterTheme() { return themeConfig?.theme?.highlighterTheme } function setHighlighterTheme(value: ThemeConfig['highlighterTheme']) { // @ts-expect-error: This is a valid expression. themeConfig.theme.highlighterTheme = { ...themeConfig?.theme?.highlighterTheme, ...value, } } function getRequestBodyDefaultView(): BodyViewType | undefined { return themeConfig?.requestBody?.defaultView?.value } function setRequestBodyDefaultView(value: BodyViewType) { ensureRefProperty(themeConfig, 'requestBody', 'defaultView', value) } function getShowBaseURL(): boolean | undefined { return themeConfig?.path?.showBaseURL?.value } function setShowBaseURL(value: boolean) { ensureRefProperty(themeConfig, 'path', 'showBaseURL', value) } function getJsonViewerDeep(): number | undefined { return themeConfig?.jsonViewer?.deep?.value } function setJsonViewerDeep(value: number) { ensureRefProperty(themeConfig, 'jsonViewer', 'deep', value) } function getJsonViewerRenderer(): JsonRendererType { return themeConfig?.jsonViewer?.renderer?.value || 'vue-json-pretty' } function setJsonViewerRenderer(value: JsonRendererType) { ensureRefProperty(themeConfig, 'jsonViewer', 'renderer', value) } function getSchemaViewerDeep(): number | undefined { return themeConfig?.schemaViewer?.deep?.value } function setSchemaViewerDeep(value: number) { ensureRefProperty(themeConfig, 'schemaViewer', 'deep', value) } function getHeadingLevels() { return themeConfig.headingLevels } function getHeadingLevel(level: keyof HeadingLevels): `h${1 | 2 | 3 | 4 | 5 | 6}` { if (!themeConfig.headingLevels) { return `h${level}` as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' } const headingLevel = themeConfig.headingLevels[level] as number if (headingLevel < 1 || headingLevel > 6) { throw new Error(`Heading level for ${level} must be between 1 and 6.`) } return `h${headingLevel}` as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' } function setHeadingLevels(levels: Partial<UnwrapNestedRefs<HeadingLevels>>) { if (!themeConfig.headingLevels) { themeConfig.headingLevels = { } } for (const key of Object.keys(levels)) { const value = levels[key as keyof HeadingLevels] as number if (value < 1 || value > 6) { throw new Error(`Heading level for ${key} must be between 1 and 6.`) } } Object.assign(themeConfig.headingLevels, levels) } function getResponseCodeSelector(): ResponseCodeSelectorType | undefined { return themeConfig?.response?.responseCodeSelector?.value } function setResponseCodeSelector(value: ResponseCodeSelectorType) { ensureRefProperty(themeConfig, 'response', 'responseCodeSelector', value) } function getResponseCodeMaxTabs(): number | undefined { return themeConfig?.response?.maxTabs?.value } function setResponseCodeMaxTabs(value: number) { ensureRefProperty(themeConfig, 'response', 'maxTabs', value) } function getResponseBodyDefaultView(): BodyViewType | undefined { return themeConfig?.response?.body?.defaultView?.value } function setResponseBodyDefaultView(value: BodyViewType) { ensureNestedRefProperty(themeConfig, ['response', 'body'], 'defaultView', value) } function getPlaygroundJsonEditorMode(): PlaygroundJsonEditorMode | undefined { return themeConfig?.playground?.jsonEditor?.mode?.value } function setPlaygroundJsonEditorMode(value: PlaygroundJsonEditorMode) { ensureNestedRefProperty(themeConfig, ['playground', 'jsonEditor'], 'mode', value) } function getPlaygroundJsonEditorMainMenuBar(): boolean | undefined { return themeConfig?.playground?.jsonEditor?.mainMenuBar?.value } function setPlaygroundJsonEditorMainMenuBar(value: boolean) { ensureNestedRefProperty(themeConfig, ['playground', 'jsonEditor'], 'mainMenuBar', value) } function getPlaygroundJsonEditorNavigationBar(): boolean | undefined { return themeConfig?.playground?.jsonEditor?.navigationBar?.value } function setPlaygroundJsonEditorNavigationBar(value: boolean) { ensureNestedRefProperty(themeConfig, ['playground', 'jsonEditor'], 'navigationBar', value) } function getPlaygroundJsonEditorStatusBar(): boolean | undefined { return themeConfig?.playground?.jsonEditor?.statusBar?.value } function setPlaygroundJsonEditorStatusBar(value: boolean) { ensureNestedRefProperty(themeConfig, ['playground', 'jsonEditor'], 'statusBar', value) } function getSecurityDefaultScheme(): string | null | undefined { return themeConfig?.security?.defaultScheme?.value } function setSecurityDefaultScheme(value: string | null) { ensureRefProperty(themeConfig, 'security', 'defaultScheme', value) } function getOperationBadges(): OperationBadges[] { return [...(themeConfig?.operation?.badges?.value || [])] } function setOperationBadges(value: OperationBadges[]) { ensureRefProperty(themeConfig, 'operation', 'badges', value) } function getOperationSlots(): OperationSlot[] | undefined { return themeConfig?.operation?.slots?.value } function setOperationSlots(value: OperationSlot[]) { ensureRefProperty(themeConfig, 'operation', 'slots', value) } function getOperationHiddenSlots(): OperationSlot[] | undefined { return themeConfig?.operation?.hiddenSlots?.value } function setOperationHiddenSlots(value: OperationSlot[]) { ensureRefProperty(themeConfig, 'operation', 'hiddenSlots', value) } function getOperationCols(): OperationColsType | undefined { return themeConfig?.operation?.cols?.value } function setOperationCols(value: OperationColsType) { ensureRefProperty(themeConfig, 'operation', 'cols', value) } function getOperationDefaultBaseUrl(): string { return themeConfig?.operation?.defaultBaseUrl || DEFAULT_BASE_URL } function setOperationDefaultBaseUrl(value: string) { const operation = ensureNestedProperty(themeConfig, 'operation') operation.defaultBaseUrl = value } function getOperationServers(): GetServersFunction | null { if (themeConfig?.operation?.getServers) { console.warn('operation.getServers is deprecated. Use server.getServers instead.') return themeConfig.operation.getServers } return themeConfig?.server?.getServers || null } function setOperationServers(value: GetServersFunction | null) { const operation = ensureNestedProperty(themeConfig, 'operation') operation.getServers = value } function getI18nConfig(): I18nConfig { return themeConfig.i18n as I18nConfig } function setI18nConfig(config: Partial<UnwrapNestedRefs<I18nConfig>>) { const i18n = ensureNestedProperty(themeConfig, 'i18n') if (config.locale) { ensureRefProperty(themeConfig, 'i18n', 'locale', config.locale) } if (config.fallbackLocale) { ensureRefProperty(themeConfig, 'i18n', 'fallbackLocale', config.fallbackLocale) } if (config.messages) { i18n.messages = config.messages } if (config.availableLocales) { i18n.availableLocales = config.availableLocales } } function getSpecConfig() { return themeConfig.spec } function getWrapExamples() { return themeConfig?.spec?.wrapExamples } function getSpecDisableDownload(): boolean | undefined { return themeConfig?.spec?.disableDownload?.value } function setSpecConfig(config: Partial<UnwrapNestedRefs<SpecConfig>>) { const spec = ensureNestedProperty(themeConfig, 'spec') if (config.groupByTags !== undefined) { ensureRefProperty(themeConfig, 'spec', 'groupByTags', config.groupByTags) } if (config.collapsePaths !== undefined) { ensureRefProperty(themeConfig, 'spec', 'collapsePaths', config.collapsePaths) } if (config.showPathsSummary !== undefined) { ensureRefProperty(themeConfig, 'spec', 'showPathsSummary', config.showPathsSummary) } if (config.avoidCirculars !== undefined) { ensureRefProperty(themeConfig, 'spec', 'avoidCirculars', config.avoidCirculars) } if (config.lazyRendering !== undefined) { ensureRefProperty(themeConfig, 'spec', 'lazyRendering', config.lazyRendering) } if (config.defaultTag !== undefined) { spec.defaultTag = config.defaultTag } if (config.defaultTagDescription !== undefined) { spec.defaultTagDescription = config.defaultTagDescription } if (config.wrapExamples !== undefined) { spec.wrapExamples = config.wrapExamples } if (config.disableDownload !== undefined) { ensureRefProperty(themeConfig, 'spec', 'disableDownload', config.disableDownload) } } function getCodeSamplesLangs() { const codeSamples = ensureNestedProperty(themeConfig, 'codeSamples') if (!codeSamples.langs) { codeSamples.langs = defaultValues.codeSamples.langs } return codeSamples.langs.filter((lang, index, self) => self.indexOf(lang) === index) } function getCodeSamplesDefaultLang() { const availableLangs = getCodeSamplesLangs() || [] const codeSamples = ensureNestedProperty(themeConfig, 'codeSamples') if (codeSamples.defaultLang && availableLangs.includes(codeSamples.defaultLang)) { return codeSamples.defaultLang } return availableLangs[0] } function getCodeSamplesAvailableLanguages() { const codeSamples = ensureNestedProperty(themeConfig, 'codeSamples') return codeSamples.availableLanguages } function getCodeSamplesGenerator() { const codeSamples = ensureNestedProperty(themeConfig, 'codeSamples') if (!codeSamples.generator) { codeSamples.generator = defaultValues.codeSamples.generator } return codeSamples.generator } function getCodeSamplesDefaultHeaders() { const codeSamples = ensureNestedProperty(themeConfig, 'codeSamples') if (!codeSamples.defaultHeaders) { codeSamples.defaultHeaders = defaultValues.codeSamples.defaultHeaders } return codeSamples.defaultHeaders } function setCodeSamplesConfig(config: Partial<UnwrapNestedRefs<CodeSamplesConfig>>) { const codeSamples = ensureNestedProperty(themeConfig, 'codeSamples') if (config.langs) { codeSamples.langs = config.langs.filter((lang, index, self) => self.indexOf(lang) === index) } if (config.defaultLang) { codeSamples.defaultLang = config.defaultLang } if (config.availableLanguages) { setCodeSamplesAvailableLanguages(config.availableLanguages) } if (config.generator) { codeSamples.generator = config.generator } if (config.defaultHeaders) { codeSamples.defaultHeaders = config.defaultHeaders } } function setCodeSamplesAvailableLanguages(languages: LanguageConfig[]) { const codeSamples = ensureNestedProperty(themeConfig, 'codeSamples') if (!codeSamples.availableLanguages) { codeSamples.availableLanguages = defaultValues.codeSamples.availableLanguages } const uniqueLanguages = [...new Set(languages.map(({ lang }) => lang))] codeSamples.availableLanguages = uniqueLanguages.map((lang) => { const language = languages.find(l => l.lang === lang) ?? availableLanguages.find(l => l.lang === lang) return language || { lang, label: lang, highlighter: 'plaintext' } }) } function getLinksPrefixesConfig() { return themeConfig.linksPrefixes } function setLinksPrefixesConfig(config: Partial<UnwrapNestedRefs<LinksPrefixesConfig>>) { const linksPrefixes = ensureNestedProperty(themeConfig, 'linksPrefixes') if (config.tags) { linksPrefixes.tags = config.tags } if (config.operations) { linksPrefixes.operations = config.operations } } function getTagsLinkPrefix() { return themeConfig?.linksPrefixes?.tags } function getOperationsLinkPrefix() { return themeConfig?.linksPrefixes?.operations } function getServerConfig(): ServerConfig { return themeConfig.server as ServerConfig } function setServerConfig(config: Partial<UnwrapNestedRefs<ServerConfig>>) { const server = ensureNestedProperty(themeConfig, 'server') if (config.allowCustomServer !== undefined) { server.allowCustomServer = config.allowCustomServer } if (config.getServers !== undefined) { server.getServers = config.getServers } } function getServerAllowCustomServer(): boolean { return themeConfig.server?.allowCustomServer || false } function getMarkdownConfig(): MarkdownConfig { return themeConfig.markdown as MarkdownConfig } function getExternalLinksNewTab(): boolean { return themeConfig.markdown?.externalLinksNewTab ?? false } function setMarkdownConfig(config: Partial<UnwrapNestedRefs<MarkdownConfig>>) { const markdown = ensureNestedProperty(themeConfig, 'markdown') if (config.operationLink !== undefined) { if (config.operationLink === false) { markdown.operationLink = false } else { const operationLink = ensureNestedProperty(markdown, 'operationLink') if (config.operationLink.linkPrefix !== undefined) { operationLink.linkPrefix = config.operationLink.linkPrefix } if (config.operationLink.transformHref !== undefined) { operationLink.transformHref = config.operationLink.transformHref } } } if (config.externalLinksNewTab !== undefined) { markdown.externalLinksNewTab = config.externalLinksNewTab } if (config.config !== undefined) { markdown.config = config.config } } function getOperationLinkConfig(): OperationLinkConfig | false | undefined { return themeConfig.markdown?.operationLink } return { isDark, schemaConfig: themeConfig.requestBody, reset, getState, getLocale, setLocale, getHighlighterTheme, /** @deprecated Use `getRequestBodyDefaultView` instead. */ getSchemaDefaultView: getRequestBodyDefaultView, getRequestBodyDefaultView, /** @deprecated Use `setRequestBodyDefaultView` instead. */ setSchemaDefaultView: setRequestBodyDefaultView, setRequestBodyDefaultView, getShowBaseURL, setShowBaseURL, getJsonViewerDeep, setJsonViewerDeep, getJsonViewerRenderer, setJsonViewerRenderer, getSchemaViewerDeep, setSchemaViewerDeep, getHeadingLevels, getHeadingLevel, setHeadingLevels, getResponseCodeSelector, setResponseCodeSelector, getResponseCodeMaxTabs, setResponseCodeMaxTabs, getResponseBodyDefaultView, setResponseBodyDefaultView, getPlaygroundJsonEditorMode, setPlaygroundJsonEditorMode, getPlaygroundJsonEditorMainMenuBar, setPlaygroundJsonEditorMainMenuBar, getPlaygroundJsonEditorNavigationBar, setPlaygroundJsonEditorNavigationBar, getPlaygroundJsonEditorStatusBar, setPlaygroundJsonEditorStatusBar, getSecurityDefaultScheme, setSecurityDefaultScheme, getOperationBadges, setOperationBadges, getOperationSlots, setOperationSlots, getOperationHiddenSlots, setOperationHiddenSlots, getOperationCols, setOperationCols, getOperationDefaultBaseUrl, getOperationServers, getI18nConfig, setI18nConfig, getSpecConfig, getWrapExamples, getSpecDisableDownload, setSpecConfig, getCodeSamplesLangs, getCodeSamplesDefaultLang, getCodeSamplesAvailableLanguages, getCodeSamplesGenerator, getCodeSamplesDefaultHeaders, setCodeSamplesConfig, getLinksPrefixesConfig, setLinksPrefixesConfig, getTagsLinkPrefix, getOperationsLinkPrefix, getServerConfig, setServerConfig, getServerAllowCustomServer, getMarkdownConfig, getExternalLinksNewTab, setMarkdownConfig, getOperationLinkConfig, } }