@stainless-api/docs 0.1.0-beta.4 → 0.1.0-beta.41

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 (108) hide show
  1. package/CHANGELOG.md +297 -0
  2. package/components/variables.css +2 -32
  3. package/eslint-suppressions.json +47 -0
  4. package/locals.d.ts +14 -0
  5. package/package.json +35 -31
  6. package/plugin/buildAlgoliaIndex.ts +31 -6
  7. package/plugin/cms/server.ts +98 -55
  8. package/plugin/cms/sidebar-builder.ts +7 -26
  9. package/plugin/cms/worker.ts +3 -3
  10. package/plugin/components/SDKSelect.astro +7 -5
  11. package/plugin/components/SnippetCode.tsx +11 -7
  12. package/plugin/components/search/SearchAlgolia.astro +5 -20
  13. package/plugin/components/search/SearchIsland.tsx +33 -22
  14. package/plugin/generateAPIReferenceLink.ts +2 -2
  15. package/plugin/globalJs/ai-dropdown-options.ts +235 -0
  16. package/plugin/globalJs/navigation.ts +7 -27
  17. package/plugin/helpers/getPageLoadEvent.ts +1 -1
  18. package/plugin/index.ts +52 -25
  19. package/plugin/languages.ts +2 -2
  20. package/plugin/loadPluginConfig.ts +103 -32
  21. package/plugin/middlewareBuilder/stainlessMiddleware.d.ts +1 -1
  22. package/plugin/react/Routing.tsx +60 -57
  23. package/plugin/referencePlaceholderUtils.ts +1 -1
  24. package/plugin/replaceSidebarPlaceholderMiddleware.ts +5 -1
  25. package/plugin/routes/Docs.astro +59 -85
  26. package/plugin/routes/Overview.astro +10 -16
  27. package/plugin/routes/markdown.ts +7 -7
  28. package/plugin/vendor/preview.worker.docs.js +7566 -6784
  29. package/resolveSrcFile.ts +10 -0
  30. package/scripts/vendor_deps.ts +1 -1
  31. package/shared/getSharedLogger.ts +15 -0
  32. package/shared/terminalUtils.ts +3 -0
  33. package/src/content.config.ts +9 -0
  34. package/stl-docs/components/AIDropdown.tsx +63 -0
  35. package/stl-docs/components/{content-panel/ContentBreadcrumbs.tsx → ContentBreadcrumbs.tsx} +2 -2
  36. package/stl-docs/components/Head.astro +16 -0
  37. package/stl-docs/components/Header.astro +3 -2
  38. package/stl-docs/components/PageTitle.astro +82 -0
  39. package/stl-docs/components/TableOfContents.astro +34 -0
  40. package/stl-docs/components/ThemeSelect.astro +80 -112
  41. package/stl-docs/components/content-panel/ContentPanel.astro +9 -39
  42. package/stl-docs/components/headers/DefaultHeader.astro +1 -1
  43. package/stl-docs/components/headers/HeaderLinks.astro +1 -1
  44. package/stl-docs/components/headers/SplashMobileMenuToggle.astro +19 -0
  45. package/stl-docs/components/headers/StackedHeader.astro +29 -24
  46. package/stl-docs/components/icons/chat-gpt.tsx +17 -0
  47. package/stl-docs/components/icons/claude.tsx +10 -0
  48. package/stl-docs/components/icons/cursor.tsx +10 -0
  49. package/stl-docs/components/icons/gemini.tsx +19 -0
  50. package/stl-docs/components/icons/markdown.tsx +10 -0
  51. package/stl-docs/components/index.ts +1 -0
  52. package/stl-docs/components/mintlify-compat/Accordion.astro +7 -38
  53. package/stl-docs/components/mintlify-compat/AccordionGroup.astro +9 -23
  54. package/stl-docs/components/mintlify-compat/Columns.astro +40 -42
  55. package/stl-docs/components/mintlify-compat/Frame.astro +16 -18
  56. package/stl-docs/components/mintlify-compat/Step.astro +30 -32
  57. package/stl-docs/components/mintlify-compat/Steps.astro +8 -10
  58. package/stl-docs/components/mintlify-compat/callouts/Callout.astro +10 -3
  59. package/stl-docs/components/mintlify-compat/callouts/Check.astro +7 -3
  60. package/stl-docs/components/mintlify-compat/callouts/Danger.astro +7 -3
  61. package/stl-docs/components/mintlify-compat/callouts/Info.astro +7 -3
  62. package/stl-docs/components/mintlify-compat/callouts/Note.astro +7 -3
  63. package/stl-docs/components/mintlify-compat/callouts/Tip.astro +7 -3
  64. package/stl-docs/components/mintlify-compat/callouts/Warning.astro +7 -3
  65. package/stl-docs/components/mintlify-compat/card.css +33 -35
  66. package/stl-docs/components/nav-tabs/NavDropdown.astro +29 -63
  67. package/stl-docs/components/nav-tabs/NavTabs.astro +79 -65
  68. package/stl-docs/components/nav-tabs/SecondaryNavTabs.astro +15 -7
  69. package/stl-docs/components/nav-tabs/buildNavLinks.ts +4 -3
  70. package/stl-docs/components/pagination/HomeLink.astro +10 -0
  71. package/stl-docs/components/pagination/Pagination.astro +173 -0
  72. package/stl-docs/components/pagination/PaginationLinkEmphasized.astro +22 -0
  73. package/stl-docs/components/pagination/PaginationLinkQuiet.astro +13 -0
  74. package/stl-docs/components/pagination/util.ts +71 -0
  75. package/stl-docs/components/scripts.ts +1 -0
  76. package/stl-docs/components/{Sidebar.astro → sidebars/BaseSidebar.astro} +2 -3
  77. package/stl-docs/components/sidebars/SDKSelectSidebar.astro +8 -0
  78. package/stl-docs/disableCalloutSyntax.ts +36 -0
  79. package/stl-docs/index.ts +76 -27
  80. package/stl-docs/loadStlDocsConfig.ts +35 -5
  81. package/stl-docs/proseMarkdown/proseMarkdownIntegration.ts +64 -0
  82. package/stl-docs/proseMarkdown/proseMarkdownMiddleware.ts +34 -0
  83. package/stl-docs/proseMarkdown/toMarkdown.ts +158 -0
  84. package/stl-docs/tabsMiddleware.ts +12 -4
  85. package/styles/code.css +115 -127
  86. package/styles/fonts.css +32 -17
  87. package/styles/links.css +10 -49
  88. package/styles/overrides.css +53 -57
  89. package/styles/page.css +90 -59
  90. package/styles/sdk_select.css +9 -7
  91. package/styles/search.css +59 -69
  92. package/styles/sidebar.css +190 -127
  93. package/styles/toc.css +37 -33
  94. package/theme.css +9 -1
  95. package/tsconfig.json +2 -5
  96. package/virtual-module.d.ts +7 -4
  97. package/plugin/globalJs/ai-dropdown.ts +0 -57
  98. package/stl-docs/components/APIReferenceAIDropdown.tsx +0 -86
  99. package/stl-docs/components/content-panel/ProseAIDropdown.tsx +0 -64
  100. /package/{plugin/assets → assets}/fonts/geist/OFL.txt +0 -0
  101. /package/{plugin/assets → assets}/fonts/geist/geist-italic-latin-ext.woff2 +0 -0
  102. /package/{plugin/assets → assets}/fonts/geist/geist-italic-latin.woff2 +0 -0
  103. /package/{plugin/assets → assets}/fonts/geist/geist-latin-ext.woff2 +0 -0
  104. /package/{plugin/assets → assets}/fonts/geist/geist-latin.woff2 +0 -0
  105. /package/{plugin/assets → assets}/fonts/geist/geist-mono-italic-latin-ext.woff2 +0 -0
  106. /package/{plugin/assets → assets}/fonts/geist/geist-mono-italic-latin.woff2 +0 -0
  107. /package/{plugin/assets → assets}/fonts/geist/geist-mono-latin-ext.woff2 +0 -0
  108. /package/{plugin/assets → assets}/fonts/geist/geist-mono-latin.woff2 +0 -0
@@ -1,9 +1,12 @@
1
1
  import path from 'path';
2
+ import { homedir } from 'os';
3
+ import { existsSync, readFileSync } from 'fs';
2
4
 
3
5
  import type { CreateShikiHighlighterOptions } from '@astrojs/markdown-remark';
4
- import type { DocsLanguage } from '@stainless-api/docs-ui/src/routing';
5
- import type { PropertySettingsType } from '@stainless-api/docs-ui/src/contexts';
6
+ import type { DocsLanguage } from '@stainless-api/docs-ui/routing';
7
+ import type { PropertySettingsType } from '@stainless-api/docs-ui/contexts';
6
8
  import type { InputFilePaths } from '../plugin/cms/server';
9
+ import { bold } from '../shared/terminalUtils';
7
10
 
8
11
  export type AstroCommand = 'dev' | 'build' | 'preview' | 'sync';
9
12
 
@@ -18,7 +21,7 @@ export type VersionUserConfig = {
18
21
  type BreadcrumbUserConfig = {
19
22
  /**
20
23
  * Include the current page in the breadcrumb list.
21
- * Defaults to `false`.
24
+ * Default: `false`
22
25
  */
23
26
  includeCurrentPage?: boolean;
24
27
  };
@@ -26,7 +29,12 @@ type BreadcrumbUserConfig = {
26
29
  export type StainlessStarlightUserConfig = {
27
30
  /**
28
31
  * Optional api key for Stainless API.
29
- * If not provided, it will look for the STAINLESS_API_KEY environment variable.
32
+ * If not provided, we will handle Stainless auth via the `stl` CLI or look for the STAINLESS_API_KEY environment variable.
33
+ * Precedence:
34
+ * 1. Explicity `apiKey` option provided
35
+ * 2. `STAINLESS_API_KEY` environment variable
36
+ * 3. Login status from the `stl` CLI
37
+ * 4. Error (no auth found)
30
38
  */
31
39
  apiKey?: string;
32
40
 
@@ -42,8 +50,8 @@ export type StainlessStarlightUserConfig = {
42
50
 
43
51
  /**
44
52
  * Optional mount point for API reference docs.
45
- * Defaults to `/api`.
46
53
  * Example: `/my-api` → docs available at `/my-api/…`.
54
+ * @default `/api`
47
55
  */
48
56
  basePath?: string;
49
57
 
@@ -55,8 +63,8 @@ export type StainlessStarlightUserConfig = {
55
63
 
56
64
  /**
57
65
  * Optional language to treat as the default when the user hasn't selected one.
58
- * Defaults to `"http"` when none is provided.
59
- * Example: `"python"`
66
+ * Example: `'python'`
67
+ * @default 'http'
60
68
  */
61
69
  defaultLanguage?: DocsLanguage;
62
70
 
@@ -90,7 +98,7 @@ export type StainlessStarlightUserConfig = {
90
98
  contentPanel?: {
91
99
  /**
92
100
  * Optional layout for the content panel.
93
- * Defaults to `"double-pane"`.
101
+ * @default 'double-pane'
94
102
  */
95
103
  layout?: ContentLayout;
96
104
  };
@@ -100,23 +108,20 @@ export type StainlessStarlightUserConfig = {
100
108
  */
101
109
  propertySettings?: PropertySettingsType;
102
110
 
103
- /**
104
- * Options to control the documentation site's search functionality
105
- */
106
- search?: {
107
- /**
108
- * When set to `true`, the enableAISearch` setting turns on support for
109
- * LLM-based conversations with the API documentation
110
- */
111
- enableAISearch?: boolean;
112
- };
113
-
114
111
  /**
115
112
  * Enable experimental collapsible code snippets. Snippets will be collapsed by default for
116
113
  * single-pane and mobile layouts.
117
- * Defaults to `false`.
114
+ *
115
+ * @default false
118
116
  */
119
117
  experimentalCollapsibleSnippets?: boolean;
118
+
119
+ /**
120
+ * Whether to show the context menu with options like "Copy as Markdown" and "Open in ChatGPT".
121
+ *
122
+ * @default true
123
+ */
124
+ contextMenu?: boolean;
120
125
  };
121
126
 
122
127
  export type ExternalSpecServerUserConfig = Omit<StainlessStarlightUserConfig, 'stainlessProject'> & {
@@ -133,15 +138,29 @@ function getLocalFilePaths(command: AstroCommand): InputFilePaths | null {
133
138
  if (command !== 'dev') {
134
139
  return null;
135
140
  }
136
- if (!process.env.OPENAPI_PATH || !process.env.STAINLESS_SPEC_PATH) {
141
+
142
+ // eslint-disable-next-line turbo/no-undeclared-env-vars
143
+ const oasPath = process.env.OPENAPI_PATH;
144
+ // eslint-disable-next-line turbo/no-undeclared-env-vars
145
+ const configPath = process.env.STAINLESS_CONFIG_PATH;
146
+
147
+ if (!oasPath || !configPath) {
137
148
  return null;
138
149
  }
150
+
139
151
  return {
140
- oasPath: resolvePath(process.env.OPENAPI_PATH),
141
- configPath: resolvePath(process.env.STAINLESS_SPEC_PATH),
152
+ oasPath: resolvePath(oasPath),
153
+ configPath: resolvePath(configPath),
142
154
  };
143
155
  }
144
156
 
157
+ export type ApiKeySource = 'explicit-config' | 'environment-variable' | 'cli';
158
+
159
+ export type LoadedApiKey = {
160
+ value: string;
161
+ source: ApiKeySource;
162
+ };
163
+
145
164
  export type SpecRetrieverConfig =
146
165
  | {
147
166
  kind: 'external_spec_server';
@@ -152,16 +171,63 @@ export type SpecRetrieverConfig =
152
171
  kind: 'local_spec_server_with_files';
153
172
  stainlessProject: string;
154
173
  devPaths: InputFilePaths;
155
- apiKey: string | null;
174
+ apiKey: LoadedApiKey | null;
156
175
  version: VersionUserConfig;
157
176
  }
158
177
  | {
159
178
  kind: 'local_spec_server_with_remote_files';
160
179
  stainlessProject: string;
161
- apiKey: string;
180
+ apiKey: LoadedApiKey;
162
181
  version: VersionUserConfig;
163
182
  };
164
183
 
184
+ function parseAuthJson(authJsonStr: string) {
185
+ let json: unknown;
186
+ try {
187
+ json = JSON.parse(authJsonStr);
188
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
189
+ } catch (_error) {
190
+ return null;
191
+ }
192
+
193
+ if (typeof json !== 'object' || json === null) {
194
+ return null;
195
+ }
196
+ if (!('access_token' in json)) {
197
+ return null;
198
+ }
199
+ const accessToken = json['access_token'];
200
+ if (typeof accessToken !== 'string') {
201
+ return null;
202
+ }
203
+ return accessToken;
204
+ }
205
+
206
+ function loadApiKey(configValue: string | undefined): LoadedApiKey | null {
207
+ if (typeof configValue === 'string') {
208
+ return { value: configValue, source: 'explicit-config' };
209
+ }
210
+ if (process.env.STAINLESS_API_KEY) {
211
+ return { value: process.env.STAINLESS_API_KEY, source: 'environment-variable' };
212
+ }
213
+
214
+ const homeDirPath = homedir();
215
+
216
+ const authJsonPath = path.join(homeDirPath, '.config', 'stainless', 'auth.json');
217
+
218
+ if (!existsSync(authJsonPath)) {
219
+ return null;
220
+ }
221
+
222
+ const authJsonStr = readFileSync(authJsonPath, 'utf-8');
223
+ const accessToken = parseAuthJson(authJsonStr);
224
+ if (!accessToken) {
225
+ return null;
226
+ }
227
+
228
+ return { value: accessToken, source: 'cli' };
229
+ }
230
+
165
231
  function normalizeConfig(partial: SomeStainlessStarlightUserConfig, command: AstroCommand) {
166
232
  const configWithDefaults = {
167
233
  basePath: partial.basePath ?? '/api',
@@ -187,9 +253,7 @@ function normalizeConfig(partial: SomeStainlessStarlightUserConfig, command: Ast
187
253
  expandDepth: partial.propertySettings?.expandDepth ?? 0,
188
254
  includeModelProperties: partial.propertySettings?.includeModelProperties ?? true,
189
255
  },
190
- search: {
191
- enableAISearch: partial.search?.enableAISearch ?? false,
192
- },
256
+ contextMenu: partial.contextMenu ?? true,
193
257
  };
194
258
 
195
259
  function getSpecRetrieverConfig(): SpecRetrieverConfig {
@@ -205,7 +269,7 @@ function normalizeConfig(partial: SomeStainlessStarlightUserConfig, command: Ast
205
269
  throw new Error('You must provide a stainlessProject when using Stainless Starlight');
206
270
  }
207
271
 
208
- const apiKey = partial.apiKey ?? process.env.STAINLESS_API_KEY ?? null;
272
+ const apiKey = loadApiKey(partial.apiKey);
209
273
 
210
274
  const version = {
211
275
  stainlessProject: partial.stainlessProject,
@@ -226,7 +290,14 @@ function normalizeConfig(partial: SomeStainlessStarlightUserConfig, command: Ast
226
290
 
227
291
  if (!apiKey) {
228
292
  throw new Error(
229
- 'Please provide a Stainless API key via the STAINLESS_API_KEY environment variable or the apiKey option in the Stainless Starlight config.',
293
+ [
294
+ bold(
295
+ 'No Stainless credentials found. Please choose one of the following options to authenticate with Stainless:',
296
+ ),
297
+ '- Run `stl auth login` to authenticate via the Stainless CLI',
298
+ '- Provide a Stainless API key via the `STAINLESS_API_KEY` environment variable (eg. in a .env file)',
299
+ '- Set the `apiKey` option in the Stainless Docs config',
300
+ ].join('\n'),
230
301
  );
231
302
  }
232
303
 
@@ -249,11 +320,11 @@ function normalizeConfig(partial: SomeStainlessStarlightUserConfig, command: Ast
249
320
  export type NormalizedStainlessStarlightConfig = ReturnType<typeof normalizeConfig>;
250
321
 
251
322
  /*
252
- The goal of the code in this file is to take a user's config and normalize it.
323
+ The goal of the code in this file is to take a user's config and normalize it.
253
324
  Specifically: we want a single complete config format used throughout the internals of the plugin.
254
325
 
255
326
  We've tried to avoid any config values being optional/undefined. To accomplish this:
256
- - Any optional config values should have their defaults set here: eg. basePath defaults to /api
327
+ - Any optional config values should have their defaults set here: eg. basePath defaults to /api
257
328
  - If a field is only used in certain contexts, we make each context a discriminated union (see SpecRetrieverConfig)
258
329
  - We prefer empty arrays over undefined/null
259
330
  */
@@ -1,4 +1,4 @@
1
- import type { TransformRequestSnippetFn } from '@stainless-api/docs-ui/src/components/sdk';
1
+ import type { TransformRequestSnippetFn } from '@stainless-api/docs-ui/components/sdk';
2
2
 
3
3
  export type StlStarlightMiddleware = {
4
4
  transformRequestSnippet?: TransformRequestSnippetFn;
@@ -6,8 +6,8 @@ import remarkGfmAlerts from 'remark-github-alerts';
6
6
 
7
7
  import type { MarkdownHeading } from 'astro';
8
8
  import type { StarlightRouteData } from '@astrojs/starlight/route-data';
9
- import type * as SDKJSON from '~/lib/json-spec-v2/types';
10
- import type { DocsLanguage } from '@stainless-api/docs-ui/src/routing';
9
+ import type * as SDKJSON from '@stainless/sdk-json';
10
+ import { LanguageNames, type DocsLanguage } from '@stainless-api/docs-ui/routing';
11
11
 
12
12
  import {
13
13
  generateRouteList,
@@ -16,7 +16,7 @@ import {
16
16
  walkTree,
17
17
  SupportedLanguageSyntaxes,
18
18
  getLanguageSnippet,
19
- } from '@stainless-api/docs-ui/src/routing';
19
+ } from '@stainless-api/docs-ui/routing';
20
20
 
21
21
  import {
22
22
  DocsProvider,
@@ -24,23 +24,22 @@ import {
24
24
  NavigationProvider,
25
25
  useSpec,
26
26
  type ContentPanelLayout,
27
- } from '@stainless-api/docs-ui/src/contexts';
27
+ } from '@stainless-api/docs-ui/contexts';
28
28
 
29
- import { flatResources, getResourceFromSpec } from '@stainless-api/docs-ui/src/utils';
29
+ import { flatResources, getResourceFromSpec } from '@stainless-api/docs-ui/utils';
30
30
 
31
31
  import {
32
32
  SDKMethod,
33
33
  SDKResource,
34
34
  type SDKRequestTitleProps,
35
35
  SDKBreadcrumbs,
36
- Dropdown,
37
- DropdownTrigger,
38
- DropdownMenu,
39
- DropdownItem,
40
36
  SDKIcon,
41
37
  SDKOverview,
42
38
  SDKLanguageBlock,
43
- } from '@stainless-api/docs-ui/src/components';
39
+ } from '@stainless-api/docs-ui/components';
40
+
41
+ import { Dropdown } from '@stainless-api/docs/components';
42
+
44
43
  import {
45
44
  BASE_PATH,
46
45
  EXCLUDE_LANGUAGES,
@@ -48,14 +47,15 @@ import {
48
47
  HIGHLIGHT_THEMES,
49
48
  BREADCRUMB_CONFIG,
50
49
  PROPERTY_SETTINGS,
50
+ ENABLE_CONTEXT_MENU,
51
51
  } from 'virtual:stl-starlight-virtual-module';
52
- import style from '@stainless-api/docs-ui/src/style';
52
+ import style from '@stainless-api/docs-ui/style';
53
53
  import { createHighlighter, type BundledLanguage, type BundledTheme, type HighlighterGeneric } from 'shiki';
54
54
  import { SnippetCode, SnippetContainer, SnippetRequestContainer } from '../components/SnippetCode';
55
- import clsx from 'clsx';
56
55
  import type { StlStarlightMiddleware } from '../middlewareBuilder/stainlessMiddleware';
57
- import { ComponentProvider } from '@stainless-api/docs-ui/src/contexts/component';
58
- import { APIReferenceAIDropdown } from '../../stl-docs/components/APIReferenceAIDropdown';
56
+ import { ComponentProvider } from '@stainless-api/docs-ui/contexts/component';
57
+ import { AIDropdown } from '../../stl-docs/components/AIDropdown';
58
+ import { ChevronsUpDownIcon } from 'lucide-react';
59
59
 
60
60
  export function generateDocsRoutes(spec: SDKJSON.Spec) {
61
61
  const paths = generateRouteList({
@@ -120,7 +120,6 @@ export function buildSidebar(
120
120
 
121
121
  const meths: SidebarEntry[] = Object.values(resource.methods ?? [])
122
122
  .filter((method) => spec.decls?.[language]?.[method.stainlessPath])
123
- .toSorted((first, second) => first.name.localeCompare(second.name))
124
123
  .map((method) => ({
125
124
  type: 'link',
126
125
  isCurrent: current === method.stainlessPath,
@@ -178,30 +177,36 @@ export function SDKSelectReactComponent({
178
177
  }) {
179
178
  return (
180
179
  <Dropdown id={id} data-current-value={selected} className={className}>
181
- <DropdownTrigger
182
- className="dropdown-toggle stldocs-button-tertiary"
183
- type="button"
184
- id="stldocs-snippet-title-button"
185
- aria-expanded="false"
186
- withChevron
187
- >
188
- <SDKIcon language={getLanguageSnippet(selected)} size={16} />
189
- <span className={clsx('stl-snippet-dropdown-button-text', selected)}>{selected}</span>
190
- </DropdownTrigger>
191
- <DropdownMenu
180
+ <Dropdown.Trigger>
181
+ <Dropdown.TriggerSelectedItem>
182
+ <Dropdown.Icon>
183
+ <SDKIcon language={getLanguageSnippet(selected)} />
184
+ </Dropdown.Icon>
185
+ <span className="stl-snippet-dropdown-button-text">{LanguageNames[selected]}</span>
186
+ </Dropdown.TriggerSelectedItem>
187
+ <Dropdown.TriggerIcon>
188
+ <ChevronsUpDownIcon size={16} />
189
+ </Dropdown.TriggerIcon>
190
+ </Dropdown.Trigger>
191
+ <Dropdown.Menu
192
192
  className="dropdown-menu stl-sdk-select-dropdown-menu"
193
- position="below"
194
- aria-labelledby="stldocs-snippet-title-button"
193
+ aria-labelledby="stl-docs-snippet-title-button"
195
194
  >
196
195
  {languages.map((item) => (
197
- <DropdownItem key={item} value={item} selected={item === selected}>
198
- <div>
196
+ <Dropdown.MenuItem key={item} value={item} isSelected={item === selected}>
197
+ <Dropdown.Icon>
199
198
  <SDKIcon language={getLanguageSnippet(item)} size={16} />
200
- <span className={clsx('stl-snippet-dropdown-button-text', item)}>{item}</span>
201
- </div>
202
- </DropdownItem>
199
+ </Dropdown.Icon>
200
+ <Dropdown.MenuItemText>{LanguageNames[item]}</Dropdown.MenuItemText>
201
+ <Dropdown.MenuItemTemplate>
202
+ <Dropdown.Icon>
203
+ <SDKIcon language={getLanguageSnippet(item)} size={16} />
204
+ </Dropdown.Icon>
205
+ <span className="stl-snippet-dropdown-button-text">{LanguageNames[item]}</span>
206
+ </Dropdown.MenuItemTemplate>
207
+ </Dropdown.MenuItem>
203
208
  ))}
204
- </DropdownMenu>
209
+ </Dropdown.Menu>
205
210
  </Dropdown>
206
211
  );
207
212
  }
@@ -302,7 +307,10 @@ export function RenderSpec({
302
307
  const parsed = parseStainlessPath(path);
303
308
  const resource = getResourceFromSpec(path, spec);
304
309
 
305
- if (!resource || !parsed) return null;
310
+ if (!resource || !parsed) {
311
+ console.warn(`Could not find resource or parsed path for '${path}'`);
312
+ return null;
313
+ }
306
314
 
307
315
  return (
308
316
  <DocsProvider
@@ -323,7 +331,7 @@ export function RenderSpec({
323
331
  >
324
332
  <NavigationProvider basePath={BASE_PATH} selectedPath={path}>
325
333
  <MarkdownProvider render={renderMarkdown} highlight={highlight}>
326
- {kind === 'http_method' ? (
334
+ {
327
335
  <div className="stldocs-root stl-ui-not-prose">
328
336
  <div className="stl-page-nav-container">
329
337
  <SDKBreadcrumbs
@@ -332,27 +340,18 @@ export function RenderSpec({
332
340
  basePath={BASE_PATH}
333
341
  config={BREADCRUMB_CONFIG}
334
342
  />
335
- <APIReferenceAIDropdown />
343
+ {ENABLE_CONTEXT_MENU && <AIDropdown />}
336
344
  </div>
337
- <SDKMethod
338
- method={resource.methods[parsed.method]}
339
- transformRequestSnippet={transformRequestSnippet}
340
- />
341
- </div>
342
- ) : (
343
- <div className="stldocs-root stl-ui-not-prose">
344
- <div className="stl-page-nav-container">
345
- <SDKBreadcrumbs
346
- spec={spec as SDKJSON.Spec}
347
- currentPath={currentPath}
348
- basePath={BASE_PATH}
349
- config={BREADCRUMB_CONFIG}
345
+ {kind === 'http_method' ? (
346
+ <SDKMethod
347
+ method={resource.methods[parsed.method!]!}
348
+ transformRequestSnippet={transformRequestSnippet}
350
349
  />
351
- <APIReferenceAIDropdown />
352
- </div>
353
- <SDKOverview resource={resource} />
350
+ ) : (
351
+ <SDKOverview resource={resource} />
352
+ )}
354
353
  </div>
355
- )}
354
+ }
356
355
  </MarkdownProvider>
357
356
  </NavigationProvider>
358
357
  </ComponentProvider>
@@ -366,10 +365,14 @@ export function RenderMethod({ path }: { path: string }) {
366
365
 
367
366
  const parsed = parseStainlessPath(path);
368
367
  const resource = getResourceFromSpec(path, spec);
369
- if (!resource || !parsed) return null;
370
368
 
371
- const meth = resource.methods[parsed.method];
372
- return <SDKMethod method={meth} />;
369
+ if (!resource || !parsed) {
370
+ console.warn(`Could not find resource or parsed path for '${path}'`);
371
+ return null;
372
+ }
373
+
374
+ const method = resource.methods[parsed.method!]!;
375
+ return <SDKMethod method={method} />;
373
376
  }
374
377
 
375
378
  export async function getReadmeContent(spec: SDKJSON.Spec, language: DocsLanguage) {
@@ -58,7 +58,7 @@ function recursiveGetPlaceholderItems(
58
58
  items: PlaceholderItemResult[],
59
59
  ): PlaceholderItemResult[] {
60
60
  for (let i = 0; i < sidebar.length; i++) {
61
- const entry = sidebar[i];
61
+ const entry = sidebar[i]!;
62
62
  if ('attrs' in entry && entry.attrs?.about === INTERNAL_REFERENCE_ENTRY_MARKER) {
63
63
  items.push({
64
64
  index: i,
@@ -5,7 +5,7 @@ import { BASE_PATH } from 'virtual:stl-starlight-virtual-module';
5
5
  import { getAPIReferencePlaceholderItems } from './referencePlaceholderUtils';
6
6
  import { getMethodFromSDKJSON, recursiveReplacePlaceholderItems } from './generateAPIReferenceLink';
7
7
  import { forceGenerateRoute } from './cms/sidebar-builder';
8
- import { parseRoute } from '@stainless-api/docs-ui/src/routing';
8
+ import { parseRoute } from '@stainless-api/docs-ui/routing';
9
9
 
10
10
  // this fn is loaded in the plugin via addRouteMiddleware
11
11
 
@@ -15,6 +15,10 @@ export const onRequest = defineRouteMiddleware(async (context) => {
15
15
 
16
16
  const slug = `/${context.locals.starlightRoute.id}`; // same as .slug but not deprecated
17
17
 
18
+ context.locals.starlightRoute._stlStarlight = {
19
+ basePath: BASE_PATH,
20
+ };
21
+
18
22
  const apiReferencePlaceholderItems = getAPIReferencePlaceholderItems(context.locals.starlightRoute.sidebar);
19
23
 
20
24
  const spec = await cmsClient.getSpec();