@stainless-api/docs 0.1.0-beta.5 → 0.1.0-beta.50
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 +381 -0
- package/eslint-suppressions.json +47 -0
- package/locals.d.ts +14 -0
- package/package.json +42 -38
- package/plugin/buildAlgoliaIndex.ts +31 -6
- package/plugin/cms/server.ts +98 -56
- package/plugin/cms/sidebar-builder.ts +7 -26
- package/plugin/cms/worker.ts +3 -3
- package/plugin/components/MethodDescription.tsx +54 -0
- package/plugin/components/SDKSelect.astro +7 -87
- package/plugin/components/SnippetCode.tsx +11 -7
- package/plugin/components/search/SearchAlgolia.astro +5 -33
- package/plugin/components/search/SearchIsland.tsx +37 -23
- package/plugin/generateAPIReferenceLink.ts +2 -2
- package/plugin/globalJs/ai-dropdown-options.ts +235 -0
- package/plugin/globalJs/method-descriptions.ts +33 -0
- package/plugin/globalJs/navigation.ts +7 -27
- package/plugin/helpers/getPageLoadEvent.ts +1 -1
- package/plugin/index.ts +54 -34
- package/plugin/languages.ts +2 -2
- package/plugin/loadPluginConfig.ts +112 -32
- package/plugin/middlewareBuilder/stainlessMiddleware.d.ts +1 -1
- package/plugin/react/Routing.tsx +176 -80
- package/plugin/referencePlaceholderUtils.ts +1 -1
- package/plugin/replaceSidebarPlaceholderMiddleware.ts +5 -1
- package/plugin/routes/Docs.astro +60 -85
- package/plugin/routes/Overview.astro +10 -16
- package/plugin/routes/markdown.ts +7 -7
- package/plugin/vendor/preview.worker.docs.js +17973 -16561
- package/plugin/vendor/templates/go.md +1 -1
- package/plugin/vendor/templates/python.md +1 -1
- package/resolveSrcFile.ts +10 -0
- package/scripts/vendor_deps.ts +1 -1
- package/shared/getSharedLogger.ts +15 -0
- package/shared/terminalUtils.ts +3 -0
- package/src/content.config.ts +9 -0
- package/stl-docs/components/AIDropdown.tsx +63 -0
- package/stl-docs/components/{content-panel/ContentBreadcrumbs.tsx → ContentBreadcrumbs.tsx} +2 -2
- package/stl-docs/components/Head.astro +16 -0
- package/stl-docs/components/Header.astro +6 -8
- package/stl-docs/components/PageTitle.astro +82 -0
- package/stl-docs/components/TableOfContents.astro +34 -0
- package/stl-docs/components/ThemeSelect.astro +118 -141
- package/stl-docs/components/content-panel/ContentPanel.astro +16 -46
- package/stl-docs/components/headers/DefaultHeader.astro +1 -1
- package/stl-docs/components/headers/HeaderLinks.astro +1 -1
- package/stl-docs/components/headers/SplashMobileMenuToggle.astro +17 -1
- package/stl-docs/components/headers/StackedHeader.astro +29 -24
- package/stl-docs/components/icons/chat-gpt.tsx +17 -0
- package/stl-docs/components/icons/claude.tsx +10 -0
- package/stl-docs/components/icons/cursor.tsx +10 -0
- package/stl-docs/components/icons/gemini.tsx +19 -0
- package/stl-docs/components/icons/markdown.tsx +10 -0
- package/stl-docs/components/index.ts +1 -0
- package/stl-docs/components/mintlify-compat/Accordion.astro +7 -38
- package/stl-docs/components/mintlify-compat/AccordionGroup.astro +9 -23
- package/stl-docs/components/mintlify-compat/Columns.astro +40 -42
- package/stl-docs/components/mintlify-compat/Frame.astro +16 -18
- package/stl-docs/components/mintlify-compat/Step.astro +30 -32
- package/stl-docs/components/mintlify-compat/Steps.astro +8 -10
- package/stl-docs/components/mintlify-compat/callouts/Callout.astro +10 -3
- package/stl-docs/components/mintlify-compat/callouts/Check.astro +7 -3
- package/stl-docs/components/mintlify-compat/callouts/Danger.astro +7 -3
- package/stl-docs/components/mintlify-compat/callouts/Info.astro +7 -3
- package/stl-docs/components/mintlify-compat/callouts/Note.astro +7 -3
- package/stl-docs/components/mintlify-compat/callouts/Tip.astro +7 -3
- package/stl-docs/components/mintlify-compat/callouts/Warning.astro +7 -3
- package/stl-docs/components/mintlify-compat/card.css +33 -35
- package/stl-docs/components/nav-tabs/NavDropdown.astro +31 -75
- package/stl-docs/components/nav-tabs/NavTabs.astro +78 -80
- package/stl-docs/components/nav-tabs/SecondaryNavTabs.astro +15 -8
- package/stl-docs/components/nav-tabs/buildNavLinks.ts +4 -3
- package/stl-docs/components/pagination/HomeLink.astro +10 -0
- package/stl-docs/components/pagination/Pagination.astro +174 -0
- package/stl-docs/components/pagination/PaginationLinkEmphasized.astro +22 -0
- package/stl-docs/components/pagination/PaginationLinkQuiet.astro +13 -0
- package/stl-docs/components/pagination/util.ts +71 -0
- package/stl-docs/components/scripts.ts +1 -0
- package/stl-docs/components/{Sidebar.astro → sidebars/BaseSidebar.astro} +2 -3
- package/stl-docs/components/sidebars/SDKSelectSidebar.astro +8 -0
- package/stl-docs/disableCalloutSyntax.ts +36 -0
- package/stl-docs/index.ts +98 -26
- package/stl-docs/loadStlDocsConfig.ts +37 -5
- package/stl-docs/proseMarkdown/proseMarkdownIntegration.ts +64 -0
- package/stl-docs/proseMarkdown/proseMarkdownMiddleware.ts +34 -0
- package/stl-docs/proseMarkdown/toMarkdown.ts +158 -0
- package/stl-docs/tabsMiddleware.ts +12 -4
- package/styles/code.css +104 -141
- package/styles/fonts.css +32 -17
- package/styles/links.css +11 -48
- package/styles/method-descriptions.css +36 -0
- package/styles/overrides.css +49 -57
- package/styles/page.css +90 -59
- package/styles/sdk_select.css +9 -7
- package/styles/search.css +58 -69
- package/styles/sidebar.css +211 -131
- package/styles/{variables.css → sl-variables.css} +3 -2
- package/styles/stldocs-variables.css +6 -0
- package/styles/toc.css +41 -34
- package/theme.css +12 -2
- package/tsconfig.json +2 -5
- package/virtual-module.d.ts +8 -4
- package/components/variables.css +0 -139
- package/plugin/globalJs/ai-dropdown.ts +0 -57
- package/stl-docs/components/APIReferenceAIDropdown.tsx +0 -86
- package/stl-docs/components/content-panel/ProseAIDropdown.tsx +0 -64
- /package/{plugin/assets → assets}/fonts/geist/OFL.txt +0 -0
- /package/{plugin/assets → assets}/fonts/geist/geist-italic-latin-ext.woff2 +0 -0
- /package/{plugin/assets → assets}/fonts/geist/geist-italic-latin.woff2 +0 -0
- /package/{plugin/assets → assets}/fonts/geist/geist-latin-ext.woff2 +0 -0
- /package/{plugin/assets → assets}/fonts/geist/geist-latin.woff2 +0 -0
- /package/{plugin/assets → assets}/fonts/geist/geist-mono-italic-latin-ext.woff2 +0 -0
- /package/{plugin/assets → assets}/fonts/geist/geist-mono-italic-latin.woff2 +0 -0
- /package/{plugin/assets → assets}/fonts/geist/geist-mono-latin-ext.woff2 +0 -0
- /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/
|
|
5
|
-
import type { PropertySettingsType } from '@stainless-api/docs-ui/
|
|
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
|
-
*
|
|
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,
|
|
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
|
-
*
|
|
59
|
-
*
|
|
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
|
-
*
|
|
101
|
+
* @default 'double-pane'
|
|
94
102
|
*/
|
|
95
103
|
layout?: ContentLayout;
|
|
96
104
|
};
|
|
@@ -100,23 +108,28 @@ 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
|
-
*
|
|
114
|
+
*
|
|
115
|
+
* @default false
|
|
118
116
|
*/
|
|
119
117
|
experimentalCollapsibleSnippets?: boolean;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Enable experimental collapsible method descriptions. Method descriptions will be
|
|
121
|
+
* collapsed if their content exceeds a certain length.
|
|
122
|
+
*
|
|
123
|
+
* @default false
|
|
124
|
+
*/
|
|
125
|
+
experimentalCollapsibleMethodDescriptions?: boolean;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Whether to show the context menu with options like "Copy as Markdown" and "Open in ChatGPT".
|
|
129
|
+
*
|
|
130
|
+
* @default true
|
|
131
|
+
*/
|
|
132
|
+
contextMenu?: boolean;
|
|
120
133
|
};
|
|
121
134
|
|
|
122
135
|
export type ExternalSpecServerUserConfig = Omit<StainlessStarlightUserConfig, 'stainlessProject'> & {
|
|
@@ -133,15 +146,29 @@ function getLocalFilePaths(command: AstroCommand): InputFilePaths | null {
|
|
|
133
146
|
if (command !== 'dev') {
|
|
134
147
|
return null;
|
|
135
148
|
}
|
|
136
|
-
|
|
149
|
+
|
|
150
|
+
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
151
|
+
const oasPath = process.env.OPENAPI_PATH;
|
|
152
|
+
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
153
|
+
const configPath = process.env.STAINLESS_CONFIG_PATH;
|
|
154
|
+
|
|
155
|
+
if (!oasPath || !configPath) {
|
|
137
156
|
return null;
|
|
138
157
|
}
|
|
158
|
+
|
|
139
159
|
return {
|
|
140
|
-
oasPath: resolvePath(
|
|
141
|
-
configPath: resolvePath(
|
|
160
|
+
oasPath: resolvePath(oasPath),
|
|
161
|
+
configPath: resolvePath(configPath),
|
|
142
162
|
};
|
|
143
163
|
}
|
|
144
164
|
|
|
165
|
+
export type ApiKeySource = 'explicit-config' | 'environment-variable' | 'cli';
|
|
166
|
+
|
|
167
|
+
export type LoadedApiKey = {
|
|
168
|
+
value: string;
|
|
169
|
+
source: ApiKeySource;
|
|
170
|
+
};
|
|
171
|
+
|
|
145
172
|
export type SpecRetrieverConfig =
|
|
146
173
|
| {
|
|
147
174
|
kind: 'external_spec_server';
|
|
@@ -152,16 +179,63 @@ export type SpecRetrieverConfig =
|
|
|
152
179
|
kind: 'local_spec_server_with_files';
|
|
153
180
|
stainlessProject: string;
|
|
154
181
|
devPaths: InputFilePaths;
|
|
155
|
-
apiKey:
|
|
182
|
+
apiKey: LoadedApiKey | null;
|
|
156
183
|
version: VersionUserConfig;
|
|
157
184
|
}
|
|
158
185
|
| {
|
|
159
186
|
kind: 'local_spec_server_with_remote_files';
|
|
160
187
|
stainlessProject: string;
|
|
161
|
-
apiKey:
|
|
188
|
+
apiKey: LoadedApiKey;
|
|
162
189
|
version: VersionUserConfig;
|
|
163
190
|
};
|
|
164
191
|
|
|
192
|
+
function parseAuthJson(authJsonStr: string) {
|
|
193
|
+
let json: unknown;
|
|
194
|
+
try {
|
|
195
|
+
json = JSON.parse(authJsonStr);
|
|
196
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
197
|
+
} catch (_error) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (typeof json !== 'object' || json === null) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
if (!('access_token' in json)) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
const accessToken = json['access_token'];
|
|
208
|
+
if (typeof accessToken !== 'string') {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
return accessToken;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function loadApiKey(configValue: string | undefined): LoadedApiKey | null {
|
|
215
|
+
if (typeof configValue === 'string') {
|
|
216
|
+
return { value: configValue, source: 'explicit-config' };
|
|
217
|
+
}
|
|
218
|
+
if (process.env.STAINLESS_API_KEY) {
|
|
219
|
+
return { value: process.env.STAINLESS_API_KEY, source: 'environment-variable' };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const homeDirPath = homedir();
|
|
223
|
+
|
|
224
|
+
const authJsonPath = path.join(homeDirPath, '.config', 'stainless', 'auth.json');
|
|
225
|
+
|
|
226
|
+
if (!existsSync(authJsonPath)) {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const authJsonStr = readFileSync(authJsonPath, 'utf-8');
|
|
231
|
+
const accessToken = parseAuthJson(authJsonStr);
|
|
232
|
+
if (!accessToken) {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return { value: accessToken, source: 'cli' };
|
|
237
|
+
}
|
|
238
|
+
|
|
165
239
|
function normalizeConfig(partial: SomeStainlessStarlightUserConfig, command: AstroCommand) {
|
|
166
240
|
const configWithDefaults = {
|
|
167
241
|
basePath: partial.basePath ?? '/api',
|
|
@@ -181,15 +255,14 @@ function normalizeConfig(partial: SomeStainlessStarlightUserConfig, command: Ast
|
|
|
181
255
|
layout: partial.contentPanel?.layout ?? 'double-pane',
|
|
182
256
|
},
|
|
183
257
|
experimentalCollapsibleSnippets: partial.experimentalCollapsibleSnippets ?? false,
|
|
258
|
+
experimentalCollapsibleMethodDescriptions: partial.experimentalCollapsibleMethodDescriptions ?? false,
|
|
184
259
|
propertySettings: {
|
|
185
260
|
types: partial.propertySettings?.types ?? 'rich',
|
|
186
261
|
collapseDescription: partial.propertySettings?.collapseDescription ?? true,
|
|
187
262
|
expandDepth: partial.propertySettings?.expandDepth ?? 0,
|
|
188
263
|
includeModelProperties: partial.propertySettings?.includeModelProperties ?? true,
|
|
189
264
|
},
|
|
190
|
-
|
|
191
|
-
enableAISearch: partial.search?.enableAISearch ?? false,
|
|
192
|
-
},
|
|
265
|
+
contextMenu: partial.contextMenu ?? true,
|
|
193
266
|
};
|
|
194
267
|
|
|
195
268
|
function getSpecRetrieverConfig(): SpecRetrieverConfig {
|
|
@@ -205,7 +278,7 @@ function normalizeConfig(partial: SomeStainlessStarlightUserConfig, command: Ast
|
|
|
205
278
|
throw new Error('You must provide a stainlessProject when using Stainless Starlight');
|
|
206
279
|
}
|
|
207
280
|
|
|
208
|
-
const apiKey = partial.apiKey
|
|
281
|
+
const apiKey = loadApiKey(partial.apiKey);
|
|
209
282
|
|
|
210
283
|
const version = {
|
|
211
284
|
stainlessProject: partial.stainlessProject,
|
|
@@ -226,7 +299,14 @@ function normalizeConfig(partial: SomeStainlessStarlightUserConfig, command: Ast
|
|
|
226
299
|
|
|
227
300
|
if (!apiKey) {
|
|
228
301
|
throw new Error(
|
|
229
|
-
|
|
302
|
+
[
|
|
303
|
+
bold(
|
|
304
|
+
'No Stainless credentials found. Please choose one of the following options to authenticate with Stainless:',
|
|
305
|
+
),
|
|
306
|
+
'- Run `stl auth login` to authenticate via the Stainless CLI',
|
|
307
|
+
'- Provide a Stainless API key via the `STAINLESS_API_KEY` environment variable (eg. in a .env file)',
|
|
308
|
+
'- Set the `apiKey` option in the Stainless Docs config',
|
|
309
|
+
].join('\n'),
|
|
230
310
|
);
|
|
231
311
|
}
|
|
232
312
|
|
|
@@ -249,11 +329,11 @@ function normalizeConfig(partial: SomeStainlessStarlightUserConfig, command: Ast
|
|
|
249
329
|
export type NormalizedStainlessStarlightConfig = ReturnType<typeof normalizeConfig>;
|
|
250
330
|
|
|
251
331
|
/*
|
|
252
|
-
The goal of the code in this file is to take a user's config and normalize it.
|
|
332
|
+
The goal of the code in this file is to take a user's config and normalize it.
|
|
253
333
|
Specifically: we want a single complete config format used throughout the internals of the plugin.
|
|
254
334
|
|
|
255
335
|
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
|
|
336
|
+
- Any optional config values should have their defaults set here: eg. basePath defaults to /api
|
|
257
337
|
- If a field is only used in certain contexts, we make each context a discriminated union (see SpecRetrieverConfig)
|
|
258
338
|
- We prefer empty arrays over undefined/null
|
|
259
339
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TransformRequestSnippetFn } from '@stainless-api/docs-ui/
|
|
1
|
+
import type { TransformRequestSnippetFn } from '@stainless-api/docs-ui/components/sdk';
|
|
2
2
|
|
|
3
3
|
export type StlStarlightMiddleware = {
|
|
4
4
|
transformRequestSnippet?: TransformRequestSnippetFn;
|
package/plugin/react/Routing.tsx
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { marked } from 'marked';
|
|
3
|
-
|
|
4
|
-
import {
|
|
2
|
+
import { marked, Tokens } from 'marked';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
createMarkdownProcessor,
|
|
6
|
+
CreateShikiHighlighterOptions,
|
|
7
|
+
type MarkdownProcessor,
|
|
8
|
+
} from '@astrojs/markdown-remark';
|
|
5
9
|
import remarkGfmAlerts from 'remark-github-alerts';
|
|
6
10
|
|
|
7
11
|
import type { MarkdownHeading } from 'astro';
|
|
8
12
|
import type { StarlightRouteData } from '@astrojs/starlight/route-data';
|
|
9
|
-
import type * as SDKJSON from '
|
|
10
|
-
import type
|
|
13
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
14
|
+
import { LanguageNames, SupportedLanguageSyntaxes, type DocsLanguage } from '@stainless-api/docs-ui/routing';
|
|
11
15
|
|
|
12
16
|
import {
|
|
13
17
|
generateRouteList,
|
|
14
18
|
generateRoute,
|
|
15
19
|
parseStainlessPath,
|
|
16
20
|
walkTree,
|
|
17
|
-
SupportedLanguageSyntaxes,
|
|
18
21
|
getLanguageSnippet,
|
|
19
|
-
} from '@stainless-api/docs-ui/
|
|
22
|
+
} from '@stainless-api/docs-ui/routing';
|
|
20
23
|
|
|
21
24
|
import {
|
|
22
25
|
DocsProvider,
|
|
@@ -24,23 +27,22 @@ import {
|
|
|
24
27
|
NavigationProvider,
|
|
25
28
|
useSpec,
|
|
26
29
|
type ContentPanelLayout,
|
|
27
|
-
} from '@stainless-api/docs-ui/
|
|
30
|
+
} from '@stainless-api/docs-ui/contexts';
|
|
28
31
|
|
|
29
|
-
import { flatResources, getResourceFromSpec } from '@stainless-api/docs-ui/
|
|
32
|
+
import { flatResources, getResourceFromSpec } from '@stainless-api/docs-ui/utils';
|
|
30
33
|
|
|
31
34
|
import {
|
|
32
35
|
SDKMethod,
|
|
33
36
|
SDKResource,
|
|
34
37
|
type SDKRequestTitleProps,
|
|
35
38
|
SDKBreadcrumbs,
|
|
36
|
-
Dropdown,
|
|
37
|
-
DropdownTrigger,
|
|
38
|
-
DropdownMenu,
|
|
39
|
-
DropdownItem,
|
|
40
39
|
SDKIcon,
|
|
41
40
|
SDKOverview,
|
|
42
41
|
SDKLanguageBlock,
|
|
43
|
-
} from '@stainless-api/docs-ui/
|
|
42
|
+
} from '@stainless-api/docs-ui/components';
|
|
43
|
+
|
|
44
|
+
import { Dropdown } from '@stainless-api/docs/components';
|
|
45
|
+
|
|
44
46
|
import {
|
|
45
47
|
BASE_PATH,
|
|
46
48
|
EXCLUDE_LANGUAGES,
|
|
@@ -48,14 +50,17 @@ import {
|
|
|
48
50
|
HIGHLIGHT_THEMES,
|
|
49
51
|
BREADCRUMB_CONFIG,
|
|
50
52
|
PROPERTY_SETTINGS,
|
|
53
|
+
ENABLE_CONTEXT_MENU,
|
|
54
|
+
EXPERIMENTAL_COLLAPSIBLE_METHOD_DESCRIPTIONS,
|
|
51
55
|
} from 'virtual:stl-starlight-virtual-module';
|
|
52
|
-
import style from '@stainless-api/docs-ui/
|
|
53
|
-
import {
|
|
56
|
+
import style from '@stainless-api/docs-ui/style';
|
|
57
|
+
import { BundledTheme, createHighlighter, HighlighterGeneric, type BundledLanguage } from 'shiki';
|
|
54
58
|
import { SnippetCode, SnippetContainer, SnippetRequestContainer } from '../components/SnippetCode';
|
|
55
|
-
import clsx from 'clsx';
|
|
56
59
|
import type { StlStarlightMiddleware } from '../middlewareBuilder/stainlessMiddleware';
|
|
57
|
-
import { ComponentProvider } from '@stainless-api/docs-ui/
|
|
58
|
-
import {
|
|
60
|
+
import { ComponentProvider } from '@stainless-api/docs-ui/contexts/component';
|
|
61
|
+
import { AIDropdown } from '../../stl-docs/components/AIDropdown';
|
|
62
|
+
import { ChevronsUpDownIcon } from 'lucide-react';
|
|
63
|
+
import { MethodDescription } from '../components/MethodDescription';
|
|
59
64
|
|
|
60
65
|
export function generateDocsRoutes(spec: SDKJSON.Spec) {
|
|
61
66
|
const paths = generateRouteList({
|
|
@@ -120,7 +125,6 @@ export function buildSidebar(
|
|
|
120
125
|
|
|
121
126
|
const meths: SidebarEntry[] = Object.values(resource.methods ?? [])
|
|
122
127
|
.filter((method) => spec.decls?.[language]?.[method.stainlessPath])
|
|
123
|
-
.toSorted((first, second) => first.name.localeCompare(second.name))
|
|
124
128
|
.map((method) => ({
|
|
125
129
|
type: 'link',
|
|
126
130
|
isCurrent: current === method.stainlessPath,
|
|
@@ -152,19 +156,58 @@ export function buildPageNavigation(resource: SDKJSON.Resource, depth: number =
|
|
|
152
156
|
return [...output, ...subs];
|
|
153
157
|
}
|
|
154
158
|
|
|
155
|
-
function renderMarkdown(content: string) {
|
|
156
|
-
|
|
159
|
+
async function renderMarkdown(content: string) {
|
|
160
|
+
const highlighter = await astroHighlight();
|
|
161
|
+
|
|
162
|
+
const renderer = {
|
|
163
|
+
code({ text, lang }: Tokens.Code) {
|
|
164
|
+
return shikiHighlight({
|
|
165
|
+
highlighter,
|
|
166
|
+
content: text,
|
|
167
|
+
language: lang,
|
|
168
|
+
});
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
marked.use({ renderer });
|
|
173
|
+
return marked.parse(content, {
|
|
174
|
+
gfm: true,
|
|
175
|
+
}) as string;
|
|
157
176
|
}
|
|
158
177
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
178
|
+
function shikiHighlight({
|
|
179
|
+
highlighter,
|
|
180
|
+
content,
|
|
181
|
+
language,
|
|
182
|
+
themes,
|
|
183
|
+
}: {
|
|
184
|
+
highlighter: HighlighterGeneric<BundledLanguage, BundledTheme>;
|
|
185
|
+
content: string;
|
|
186
|
+
language?: string;
|
|
187
|
+
themes?: CreateShikiHighlighterOptions['themes'] | Record<string, 'stainless-docs-json'>;
|
|
188
|
+
}) {
|
|
189
|
+
let _themes = themes;
|
|
190
|
+
if (!themes && language === 'json') {
|
|
191
|
+
_themes = {
|
|
192
|
+
light: 'stainless-docs-json',
|
|
193
|
+
dark: 'stainless-docs-json',
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (!_themes) {
|
|
198
|
+
_themes = HIGHLIGHT_THEMES;
|
|
199
|
+
}
|
|
162
200
|
return highlighter.codeToHtml(content, {
|
|
163
201
|
lang: language ?? 'javascript',
|
|
164
|
-
themes:
|
|
202
|
+
themes: _themes || {},
|
|
165
203
|
});
|
|
166
204
|
}
|
|
167
205
|
|
|
206
|
+
async function highlight(content: string, language?: string) {
|
|
207
|
+
const highlighter = await astroHighlight();
|
|
208
|
+
return shikiHighlight({ highlighter, content, language });
|
|
209
|
+
}
|
|
210
|
+
|
|
168
211
|
export function SDKSelectReactComponent({
|
|
169
212
|
selected,
|
|
170
213
|
languages,
|
|
@@ -178,30 +221,36 @@ export function SDKSelectReactComponent({
|
|
|
178
221
|
}) {
|
|
179
222
|
return (
|
|
180
223
|
<Dropdown id={id} data-current-value={selected} className={className}>
|
|
181
|
-
<
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
<
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
224
|
+
<Dropdown.Trigger>
|
|
225
|
+
<Dropdown.TriggerSelectedItem>
|
|
226
|
+
<Dropdown.Icon>
|
|
227
|
+
<SDKIcon language={getLanguageSnippet(selected)} />
|
|
228
|
+
</Dropdown.Icon>
|
|
229
|
+
<span className="stl-snippet-dropdown-button-text">{LanguageNames[selected]}</span>
|
|
230
|
+
</Dropdown.TriggerSelectedItem>
|
|
231
|
+
<Dropdown.TriggerIcon>
|
|
232
|
+
<ChevronsUpDownIcon size={16} />
|
|
233
|
+
</Dropdown.TriggerIcon>
|
|
234
|
+
</Dropdown.Trigger>
|
|
235
|
+
<Dropdown.Menu
|
|
192
236
|
className="dropdown-menu stl-sdk-select-dropdown-menu"
|
|
193
|
-
|
|
194
|
-
aria-labelledby="stldocs-snippet-title-button"
|
|
237
|
+
aria-labelledby="stl-docs-snippet-title-button"
|
|
195
238
|
>
|
|
196
239
|
{languages.map((item) => (
|
|
197
|
-
<
|
|
198
|
-
<
|
|
240
|
+
<Dropdown.MenuItem key={item} value={item} isSelected={item === selected}>
|
|
241
|
+
<Dropdown.Icon>
|
|
199
242
|
<SDKIcon language={getLanguageSnippet(item)} size={16} />
|
|
200
|
-
|
|
201
|
-
</
|
|
202
|
-
|
|
243
|
+
</Dropdown.Icon>
|
|
244
|
+
<Dropdown.MenuItemText>{LanguageNames[item]}</Dropdown.MenuItemText>
|
|
245
|
+
<Dropdown.MenuItemTemplate>
|
|
246
|
+
<Dropdown.Icon>
|
|
247
|
+
<SDKIcon language={getLanguageSnippet(item)} size={16} />
|
|
248
|
+
</Dropdown.Icon>
|
|
249
|
+
<span className="stl-snippet-dropdown-button-text">{LanguageNames[item]}</span>
|
|
250
|
+
</Dropdown.MenuItemTemplate>
|
|
251
|
+
</Dropdown.MenuItem>
|
|
203
252
|
))}
|
|
204
|
-
</
|
|
253
|
+
</Dropdown.Menu>
|
|
205
254
|
</Dropdown>
|
|
206
255
|
);
|
|
207
256
|
}
|
|
@@ -302,7 +351,10 @@ export function RenderSpec({
|
|
|
302
351
|
const parsed = parseStainlessPath(path);
|
|
303
352
|
const resource = getResourceFromSpec(path, spec);
|
|
304
353
|
|
|
305
|
-
if (!resource || !parsed)
|
|
354
|
+
if (!resource || !parsed) {
|
|
355
|
+
console.warn(`Could not find resource or parsed path for '${path}'`);
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
306
358
|
|
|
307
359
|
return (
|
|
308
360
|
<DocsProvider
|
|
@@ -319,11 +371,12 @@ export function RenderSpec({
|
|
|
319
371
|
SnippetCode,
|
|
320
372
|
SnippetContainer,
|
|
321
373
|
SnippetRequestContainer,
|
|
374
|
+
...(EXPERIMENTAL_COLLAPSIBLE_METHOD_DESCRIPTIONS ? { MethodDescription } : {}),
|
|
322
375
|
}}
|
|
323
376
|
>
|
|
324
377
|
<NavigationProvider basePath={BASE_PATH} selectedPath={path}>
|
|
325
378
|
<MarkdownProvider render={renderMarkdown} highlight={highlight}>
|
|
326
|
-
{
|
|
379
|
+
{
|
|
327
380
|
<div className="stldocs-root stl-ui-not-prose">
|
|
328
381
|
<div className="stl-page-nav-container">
|
|
329
382
|
<SDKBreadcrumbs
|
|
@@ -332,27 +385,18 @@ export function RenderSpec({
|
|
|
332
385
|
basePath={BASE_PATH}
|
|
333
386
|
config={BREADCRUMB_CONFIG}
|
|
334
387
|
/>
|
|
335
|
-
<
|
|
388
|
+
{ENABLE_CONTEXT_MENU && <AIDropdown />}
|
|
336
389
|
</div>
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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}
|
|
390
|
+
{kind === 'http_method' ? (
|
|
391
|
+
<SDKMethod
|
|
392
|
+
method={resource.methods[parsed.method!]!}
|
|
393
|
+
transformRequestSnippet={transformRequestSnippet}
|
|
350
394
|
/>
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
395
|
+
) : (
|
|
396
|
+
<SDKOverview resource={resource} />
|
|
397
|
+
)}
|
|
354
398
|
</div>
|
|
355
|
-
|
|
399
|
+
}
|
|
356
400
|
</MarkdownProvider>
|
|
357
401
|
</NavigationProvider>
|
|
358
402
|
</ComponentProvider>
|
|
@@ -366,10 +410,14 @@ export function RenderMethod({ path }: { path: string }) {
|
|
|
366
410
|
|
|
367
411
|
const parsed = parseStainlessPath(path);
|
|
368
412
|
const resource = getResourceFromSpec(path, spec);
|
|
369
|
-
if (!resource || !parsed) return null;
|
|
370
413
|
|
|
371
|
-
|
|
372
|
-
|
|
414
|
+
if (!resource || !parsed) {
|
|
415
|
+
console.warn(`Could not find resource or parsed path for '${path}'`);
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const method = resource.methods[parsed.method!]!;
|
|
420
|
+
return <SDKMethod method={method} />;
|
|
373
421
|
}
|
|
374
422
|
|
|
375
423
|
export async function getReadmeContent(spec: SDKJSON.Spec, language: DocsLanguage) {
|
|
@@ -389,6 +437,66 @@ export async function getReadmeContent(spec: SDKJSON.Spec, language: DocsLanguag
|
|
|
389
437
|
return spec.readme[language];
|
|
390
438
|
}
|
|
391
439
|
|
|
440
|
+
let astroShikiHighlighter:
|
|
441
|
+
| HighlighterGeneric<BundledLanguage, BundledTheme>
|
|
442
|
+
| Promise<HighlighterGeneric<BundledLanguage, BundledTheme>>
|
|
443
|
+
| null = null;
|
|
444
|
+
|
|
445
|
+
async function astroHighlight() {
|
|
446
|
+
if (astroShikiHighlighter) {
|
|
447
|
+
return astroShikiHighlighter;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
astroShikiHighlighter = createHighlighter({
|
|
451
|
+
themes: [
|
|
452
|
+
'github-light',
|
|
453
|
+
'github-dark',
|
|
454
|
+
{
|
|
455
|
+
name: 'stainless-docs-json',
|
|
456
|
+
colors: {
|
|
457
|
+
'editor.background': 'var(--stl-color-background)',
|
|
458
|
+
'editor.foreground': 'var(--stl-color-foreground)',
|
|
459
|
+
},
|
|
460
|
+
|
|
461
|
+
tokenColors: [
|
|
462
|
+
{
|
|
463
|
+
scope: ['comment', 'punctuation.definition.comment'],
|
|
464
|
+
settings: { foreground: 'var(--stl-color-foreground-muted)' },
|
|
465
|
+
},
|
|
466
|
+
// numbers, booleans, null
|
|
467
|
+
{
|
|
468
|
+
scope: ['constant.numeric', 'constant.language'],
|
|
469
|
+
settings: { foreground: 'var(--stl-color-orange-foreground)' },
|
|
470
|
+
},
|
|
471
|
+
// strings
|
|
472
|
+
{
|
|
473
|
+
scope: ['string', 'string.quoted', 'string.template'],
|
|
474
|
+
settings: { foreground: 'var(--stl-color-green-foreground)' },
|
|
475
|
+
},
|
|
476
|
+
// Keys, brackets
|
|
477
|
+
{
|
|
478
|
+
scope: ['support.type', 'meta'],
|
|
479
|
+
settings: { foreground: 'var(--stl-color-foreground)' },
|
|
480
|
+
},
|
|
481
|
+
// brackets
|
|
482
|
+
{
|
|
483
|
+
scope: ['meta'],
|
|
484
|
+
settings: { foreground: 'var(--stl-color-foreground-muted)' },
|
|
485
|
+
},
|
|
486
|
+
// built-in types
|
|
487
|
+
{
|
|
488
|
+
scope: ['support.type.builtin'],
|
|
489
|
+
settings: { foreground: 'var(--stl-color-purple-foreground)' },
|
|
490
|
+
},
|
|
491
|
+
],
|
|
492
|
+
},
|
|
493
|
+
],
|
|
494
|
+
langs: SupportedLanguageSyntaxes,
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
return astroShikiHighlighter;
|
|
498
|
+
}
|
|
499
|
+
|
|
392
500
|
// Astro's markdown processor is a singleton
|
|
393
501
|
// Need to cache it instead of instanting per request
|
|
394
502
|
let astroMarkdownProcessor: MarkdownProcessor;
|
|
@@ -406,18 +514,6 @@ async function astroMarkdown() {
|
|
|
406
514
|
return astroMarkdownProcessor;
|
|
407
515
|
}
|
|
408
516
|
|
|
409
|
-
let astroShikiHighlighter: HighlighterGeneric<BundledLanguage, BundledTheme>;
|
|
410
|
-
async function astroHighlight() {
|
|
411
|
-
if (!astroShikiHighlighter) {
|
|
412
|
-
astroShikiHighlighter = await createHighlighter({
|
|
413
|
-
themes: ['github-light', 'github-dark'],
|
|
414
|
-
langs: SupportedLanguageSyntaxes,
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
return astroShikiHighlighter;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
517
|
export async function astroMarkdownRender(content: string) {
|
|
422
518
|
const md = await astroMarkdown();
|
|
423
519
|
const output = await md.render(content);
|
|
@@ -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/
|
|
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();
|