@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,10 +1,11 @@
1
+ import type { AstroIntegrationLogger } from 'astro';
1
2
  import { createServer, IncomingMessage } from 'http';
2
3
  import { readFile } from 'fs/promises';
3
4
 
4
- import type * as SDKJSON from '~/lib/json-spec-v2/types';
5
+ import type * as SDKJSON from '@stainless/sdk-json';
5
6
  import { createSDKJSON, parseInputs, transformOAS } from './worker';
6
- import { Languages, parseRoute, type DocsLanguage } from '@stainless-api/docs-ui/src/routing';
7
- import Stainless from '@stainless-api/sdk';
7
+ import { Languages, parseRoute, type DocsLanguage } from '@stainless-api/docs-ui/routing';
8
+ import Stainless, { APIError } from '@stainless-api/sdk';
8
9
 
9
10
  import {
10
11
  toStarlightSidebar,
@@ -12,88 +13,118 @@ import {
12
13
  SidebarConfigItemsBuilder,
13
14
  } from './sidebar-builder';
14
15
  import type { VersionUserConfig } from '../loadPluginConfig';
16
+ import { bold } from '../../shared/terminalUtils';
15
17
 
16
18
  export type InputFilePaths = {
17
19
  oasPath?: string;
18
20
  configPath?: string;
19
21
  };
20
22
 
21
- async function versionInfo(project: string, apiKey: string) {
23
+ async function versionInfo(project: string, apiKey: string): Promise<Record<DocsLanguage, string>> {
22
24
  const data = await fetch(`https://api.stainless.com/api/projects/${project}/package-versions`, {
23
25
  headers: { Authorization: `Bearer ${apiKey}` },
24
26
  });
25
27
 
26
28
  const content = await data.text();
27
- return JSON.parse(content);
29
+ return JSON.parse(content) as Record<DocsLanguage, string>;
30
+ }
31
+
32
+ function redactApiKey(apiKey: string) {
33
+ return apiKey
34
+ .split('')
35
+ .map((char, index) => (index < 10 ? char : '*'))
36
+ .join('');
28
37
  }
29
38
 
30
39
  async function loadSpec({
31
40
  apiKey,
32
41
  devPaths,
33
42
  version,
43
+ logger,
34
44
  }: {
35
45
  apiKey: string;
36
46
  devPaths: InputFilePaths;
37
47
  version: VersionUserConfig;
48
+ logger: AstroIntegrationLogger;
38
49
  }) {
39
- let oasStr: string;
40
- let configStr: string;
41
- let versions: Record<DocsLanguage, string> | undefined;
42
-
43
- if (devPaths.oasPath && devPaths.configPath) {
44
- [oasStr, configStr] = await Promise.all([
45
- readFile(devPaths.oasPath, 'utf-8'),
46
- readFile(devPaths.configPath, 'utf-8'),
47
- ]);
48
- } else {
49
- const client = new Stainless({ apiKey });
50
- const configs = await client.projects.configs.retrieve({
51
- project: version.stainlessProject,
52
- branch: version.branch,
53
- include: 'openapi',
54
- });
50
+ async function unsafeLoad() {
51
+ let oasStr: string;
52
+ let configStr: string;
53
+ let versions: Record<DocsLanguage, string> | undefined;
54
+
55
+ if (devPaths.oasPath && devPaths.configPath) {
56
+ [oasStr, configStr] = await Promise.all([
57
+ readFile(devPaths.oasPath, 'utf-8'),
58
+ readFile(devPaths.configPath, 'utf-8'),
59
+ ]);
60
+ } else {
61
+ const client = new Stainless({ apiKey });
62
+ const configs = await client.projects.configs.retrieve({
63
+ project: version.stainlessProject,
64
+ branch: version.branch,
65
+ include: 'openapi',
66
+ });
55
67
 
56
- versions = await versionInfo(version.stainlessProject, apiKey);
68
+ versions = await versionInfo(version.stainlessProject, apiKey);
57
69
 
58
- const configYML = Object.values(configs)[0] as { content: any };
59
- const oasJson = Object.values(configs)[1] as { content: any };
60
- oasStr = oasJson['content'];
61
- configStr = configYML['content'];
62
- }
70
+ const configYML = Object.values(configs)[0] as { content: any };
71
+ const oasJson = Object.values(configs)[1] as { content: any };
72
+ oasStr = oasJson['content'];
73
+ configStr = configYML['content'];
74
+ }
63
75
 
64
- const { oas, config } = await parseInputs({
65
- oas: oasStr,
66
- config: configStr,
67
- });
76
+ const { oas, config } = await parseInputs({
77
+ oas: oasStr,
78
+ config: configStr,
79
+ });
68
80
 
69
- const transformedOAS = await transformOAS({ oas, config });
81
+ const transformedOAS = await transformOAS({ oas, config });
70
82
 
71
- const languages =
72
- config.docs?.languages ??
73
- (Object.entries(config.targets)
74
- // @ts-expect-error we don't have the actual Stainless config type here
75
- .filter(([name, target]) => Languages.includes(name) && !target.skip)
76
- .map(([name]) => name) as SDKJSON.SpecLanguage[]);
83
+ const languages =
84
+ config.docs?.languages ??
85
+ (Object.entries(config.targets)
86
+ // @ts-expect-error we don't have the actual Stainless config type here
87
+ .filter(([name, target]) => Languages.includes(name) && !target.skip)
88
+ .map(([name]) => name) as SDKJSON.SpecLanguage[]);
77
89
 
78
- const sdkJson = await createSDKJSON({
79
- oas: transformedOAS,
80
- config,
81
- languages,
82
- });
90
+ const sdkJson = await createSDKJSON({
91
+ oas: transformedOAS,
92
+ config,
93
+ languages,
94
+ });
83
95
 
84
- if (versions) {
85
- for (const [lang, version] of Object.entries(versions)) {
86
- const meta = sdkJson.metadata[lang as DocsLanguage];
87
- if (meta?.version) meta.version = version;
96
+ if (versions) {
97
+ for (const [lang, version] of Object.entries(versions)) {
98
+ const meta = sdkJson.metadata[lang as DocsLanguage];
99
+ if (meta?.version) meta.version = version;
100
+ }
88
101
  }
102
+
103
+ const id = crypto.randomUUID();
104
+
105
+ return {
106
+ data: sdkJson,
107
+ id,
108
+ };
89
109
  }
90
110
 
91
- const id = crypto.randomUUID();
111
+ try {
112
+ const result = await unsafeLoad();
113
+ return result;
114
+ } catch (error) {
115
+ logger.error(bold('Failed to fetch API reference information from Stainless:'));
116
+ if (error instanceof APIError && error.status >= 400 && error.status < 500) {
117
+ logger.error(`Requested project slug: "${version.stainlessProject}"`);
118
+ logger.error(`API key: "${redactApiKey(apiKey)}"`);
119
+ logger.error(
120
+ `This error can usually be corrected by re-authenticating with the Stainless. Use the CLI (stl auth login) or verify that the Stainless API key you're using can access the project mentioned above.`,
121
+ );
122
+ } else {
123
+ logger.error(error instanceof Error ? error.message : 'Unknown error');
124
+ }
92
125
 
93
- return {
94
- data: sdkJson,
95
- id,
96
- };
126
+ process.exit(1);
127
+ }
97
128
  }
98
129
 
99
130
  class Spec {
@@ -107,6 +138,7 @@ class Spec {
107
138
  apiKey: this.apiKey,
108
139
  devPaths: this.devPaths,
109
140
  version: this.version,
141
+ logger: this.logger,
110
142
  });
111
143
  }
112
144
 
@@ -128,15 +160,22 @@ class Spec {
128
160
  return spec;
129
161
  }
130
162
 
131
- constructor(apiKey: string, version: VersionUserConfig, devPaths: InputFilePaths) {
163
+ constructor(
164
+ apiKey: string,
165
+ version: VersionUserConfig,
166
+ devPaths: InputFilePaths,
167
+ private logger: AstroIntegrationLogger,
168
+ ) {
132
169
  this.specPromise = loadSpec({
133
170
  apiKey,
134
171
  devPaths,
135
172
  version,
173
+ logger,
136
174
  });
137
175
  this.devPaths = devPaths;
138
176
  this.apiKey = apiKey;
139
177
  this.version = version;
178
+ this.logger = logger;
140
179
  }
141
180
  }
142
181
 
@@ -166,14 +205,16 @@ export function startDevServer({
166
205
  devPaths,
167
206
  apiKey,
168
207
  getGeneratedSidebarConfig,
208
+ logger,
169
209
  }: {
170
210
  port: number;
171
211
  version: VersionUserConfig;
172
212
  devPaths: InputFilePaths;
173
213
  apiKey: string;
174
214
  getGeneratedSidebarConfig: (id: number) => GeneratedSidebarConfig | null;
215
+ logger: AstroIntegrationLogger;
175
216
  }) {
176
- const spec = new Spec(apiKey, version, devPaths);
217
+ const spec = new Spec(apiKey, version, devPaths, logger);
177
218
 
178
219
  const server = createServer(async (req, res) => {
179
220
  // Add CORS headers
@@ -250,7 +291,7 @@ export function startDevServer({
250
291
  });
251
292
 
252
293
  server.listen(port, () => {
253
- console.log(`Server is running on port ${port}`);
294
+ logger.debug(`Stainless spec server is running on port: ${port}`);
254
295
  });
255
296
 
256
297
  return {
@@ -266,3 +307,5 @@ export function startDevServer({
266
307
  },
267
308
  };
268
309
  }
310
+
311
+ export type DevSpecServer = Awaited<ReturnType<typeof startDevServer>>;
@@ -1,5 +1,5 @@
1
- import type * as SDKJSON from '~/lib/json-spec-v2/types';
2
- import { generateRoute, walkTree, type DocsLanguage } from '@stainless-api/docs-ui/src/routing';
1
+ import type * as SDKJSON from '@stainless/sdk-json';
2
+ import { generateRoute, walkTree, type DocsLanguage } from '@stainless-api/docs-ui/routing';
3
3
  import type { StarlightRouteData } from '@astrojs/starlight/route-data';
4
4
 
5
5
  function isResourceNonEmpty(resource: SDKJSON.Resource) {
@@ -120,22 +120,12 @@ export type GeneratedSidebarConfig = {
120
120
  };
121
121
 
122
122
  function countKeys(obj?: Record<string, any>) {
123
- let o = obj ?? {};
123
+ const o = obj ?? {};
124
124
  return Object.keys(o).length;
125
125
  }
126
126
 
127
- function getMethodDeclForLanguage(entry: SDKJSON.Method, spec: SDKJSON.Spec, language: DocsLanguage) {
128
- const decls = spec.decls[language] ?? {};
129
- const decl = decls[entry.stainlessPath];
130
- if (decl !== undefined) {
131
- if ('ident' in decl) {
132
- return decl;
133
- }
134
- }
135
- return null;
136
- }
137
-
138
- type MethodDecl = Exclude<ReturnType<typeof getMethodDeclForLanguage>, null>;
127
+ type HasIdent<T> = T extends { ident: unknown } ? T : never;
128
+ type MethodDecl = HasIdent<SDKJSON.LanguageDeclNodes[SDKJSON.SpecLanguage]>;
139
129
 
140
130
  function makeAPIOverviewPage(): UserSidebarAPIOverviewPage {
141
131
  return {
@@ -166,7 +156,7 @@ function pullOutSharedModelsResource(resources: SDKJSON.Resource[]): {
166
156
  }
167
157
 
168
158
  export class SidebarConfigItemsBuilder {
169
- private getMethodDeclForLanguage(entry: SDKJSON.Method) {
159
+ private getMethodDeclForLanguage(entry: SDKJSON.Method): MethodDecl | null {
170
160
  const decls = this.spec.decls[this.language] ?? {};
171
161
  const decl = decls[entry.stainlessPath];
172
162
  if (decl !== undefined) {
@@ -208,13 +198,6 @@ export class SidebarConfigItemsBuilder {
208
198
  };
209
199
  }
210
200
 
211
- private sortByLabel<T extends UserSidebarConfigItem>(items: T[]) {
212
- // sorts in place
213
- items.sort((a, b) => {
214
- return a.label.localeCompare(b.label);
215
- });
216
- }
217
-
218
201
  private generateResourceGroup(resource: SDKJSON.Resource, collapsed: boolean): ReferenceSidebarGroup {
219
202
  const entries: ReferenceSidebarConfigItem[] = [];
220
203
  if (!this.options?.excludeResourceOverviewPages) {
@@ -228,7 +211,6 @@ export class SidebarConfigItemsBuilder {
228
211
  methodPages.push(this.toMethodPage(m, langDecl));
229
212
  }
230
213
  }
231
- this.sortByLabel(methodPages);
232
214
  entries.push(...methodPages);
233
215
 
234
216
  const subresources = Object.values(resource.subresources ?? {});
@@ -238,7 +220,6 @@ export class SidebarConfigItemsBuilder {
238
220
  subresourceGroups.push(this.generateResourceGroup(sub, true));
239
221
  }
240
222
  }
241
- this.sortByLabel(subresourceGroups);
242
223
  entries.push(...subresourceGroups);
243
224
 
244
225
  return {
@@ -253,7 +234,7 @@ export class SidebarConfigItemsBuilder {
253
234
 
254
235
  public generateItems(): ReferenceSidebarConfigItem[] {
255
236
  const resourceMap = this.spec.resources;
256
- let { resources, sharedModelsResource } = pullOutSharedModelsResource(Object.values(resourceMap ?? {}));
237
+ const { resources, sharedModelsResource } = pullOutSharedModelsResource(Object.values(resourceMap ?? {}));
257
238
 
258
239
  const entries: ReferenceSidebarConfigItem[] = resources.filter(isResourceNonEmpty).map((r) => {
259
240
  return this.generateResourceGroup(r, false);
@@ -1,6 +1,6 @@
1
1
  import Worker from 'web-worker';
2
- import { Languages, type DocsLanguage } from '@stainless-api/docs-ui/src/routing';
3
- import type * as SDKJSON from '~/lib/json-spec-v2/types';
2
+ import { Languages, type DocsLanguage } from '@stainless-api/docs-ui/routing';
3
+ import type * as SDKJSON from '@stainless/sdk-json';
4
4
  import { fileURLToPath } from 'node:url';
5
5
  import { dirname, resolve } from 'node:path';
6
6
  import fs from 'fs/promises';
@@ -98,7 +98,7 @@ export async function createSDKJSON({
98
98
  try {
99
99
  const content = await fs.readFile(mdfile);
100
100
  return [language, content.toString()];
101
- } catch (err) {
101
+ } catch {
102
102
  return [language, null];
103
103
  }
104
104
  }),
@@ -1,6 +1,6 @@
1
1
  ---
2
- import type { DocsLanguage } from '@stainless-api/docs-ui/src/routing';
3
- import { parseRoute } from '@stainless-api/docs-ui/src/routing';
2
+ import type { DocsLanguage } from '@stainless-api/docs-ui/routing';
3
+ import { parseRoute } from '@stainless-api/docs-ui/routing';
4
4
  import { cmsClient } from '../cms/client';
5
5
  import { BASE_PATH, DEFAULT_LANGUAGE, EXCLUDE_LANGUAGES } from 'virtual:stl-starlight-virtual-module';
6
6
  import { Languages } from '../languages';
@@ -138,15 +138,17 @@ const readmeSlug = language === 'http' ? BASE_PATH : `${BASE_PATH}/${language}`;
138
138
  <script>
139
139
  import { navigate } from 'astro:transitions/client';
140
140
  import { updateSelectedLanguage } from '../languages';
141
- import { initDropdown } from '@stainless-api/docs-ui/src/components/scripts/dropdown';
141
+ import { initDropdown } from '@stainless-api/docs/components/scripts';
142
142
  import { BASE_PATH } from 'virtual:stl-starlight-virtual-module';
143
143
  import { getPageLoadEvent } from '../helpers/getPageLoadEvent';
144
144
 
145
145
  document.addEventListener(getPageLoadEvent(), () => {
146
+ const sdkSelect = document.getElementById('sidebar-sdk-select');
147
+ if (!sdkSelect) return;
146
148
  initDropdown({
147
- dropdownId: 'sidebar-sdk-select',
149
+ root: sdkSelect,
148
150
  onSelect: (value) => {
149
- const originalLanguage = document.getElementById('sidebar-sdk-select')?.dataset.currentValue;
151
+ const originalLanguage = sdkSelect.dataset.currentValue;
150
152
  navigate(updateSelectedLanguage(BASE_PATH, originalLanguage, value));
151
153
  },
152
154
  });
@@ -2,12 +2,14 @@ import type {
2
2
  SnippetCodeProps,
3
3
  SnippetContainerProps,
4
4
  SnippetRequestContainerProps,
5
- } from '@stainless-api/docs-ui/src/components';
6
- import { useHighlight, useLanguage } from '@stainless-api/docs-ui/src/contexts';
7
- import style from '@stainless-api/docs-ui/src/style';
5
+ } from '@stainless-api/docs-ui/components';
6
+ import { useHighlight, useLanguage } from '@stainless-api/docs-ui/contexts';
7
+ import style from '@stainless-api/docs-ui/style';
8
8
  import * as cheerio from 'cheerio/slim';
9
9
  import { EXPERIMENTAL_COLLAPSIBLE_SNIPPETS } from 'virtual:stl-starlight-virtual-module';
10
10
  import clsx from 'clsx';
11
+ import { Button } from '@stainless-api/ui-primitives';
12
+
11
13
  /*
12
14
  * This may be replaced by additional data from the sdk.
13
15
  * Without information from the sdk, we use simple heuristics per language.
@@ -53,7 +55,7 @@ function wrapFirstNSpaces($line: cheerio.Cheerio<any>, n: number) {
53
55
  const m = inner.match(new RegExp(`^( {1,${n}})`));
54
56
  if (!m) return;
55
57
 
56
- const lead = m[1];
58
+ const lead = m[1]!;
57
59
  $firstSpan.html(`<span class="leading-ws">${lead}</span>${inner.slice(lead.length)}`);
58
60
  }
59
61
 
@@ -130,12 +132,14 @@ export function SnippetRequestContainer({ children, signature }: SnippetRequestC
130
132
  <div className="stl-snippet-request-container">
131
133
  {children}
132
134
  {signature && isCollapsible && (
133
- <button
134
- className={clsx(style.Button, style.ButtonSecondary, 'stl-snippet-expand-button')}
135
+ <Button
136
+ className={'stl-snippet-expand-button'}
135
137
  id="stl-snippet-expand-button"
138
+ size="sm"
139
+ variant="outline"
136
140
  >
137
141
  Show more
138
- </button>
142
+ </Button>
139
143
  )}
140
144
  </div>
141
145
  );
@@ -1,30 +1,23 @@
1
1
  ---
2
2
  import { Icon } from '@astrojs/starlight/components';
3
3
  import { DocsSearch } from './SearchIsland';
4
- import { SEARCH } from 'virtual:stl-starlight-virtual-module';
5
-
6
- import '@stainless-api/docs-ui/src/styles/resets.css';
7
- import '@stainless-api/docs-ui/src/styles/primitives.css';
8
- import '@stainless-api/docs-ui/src/styles/main.css';
9
- import '@stainless-api/docs-ui/src/styles/snippets.css';
10
- import '@stainless-api/docs-ui/src/styles/search.css';
11
- import '../../../components/variables.css';
4
+ import { Button } from '@stainless-api/ui-primitives';
12
5
  ---
13
6
 
14
7
  <site-search>
15
- <button
16
- popovertarget="stldocs-search"
8
+ <Button
9
+ popoverTarget="stldocs-search"
17
10
  data-open-modal
18
11
  aria-label={Astro.locals.t('search.label')}
19
12
  aria-keyshortcuts="Control+K"
20
- class="stldocs-button stldocs-button-secondary"
13
+ variant="outline"
21
14
  >
22
15
  <Icon name="magnifier" />
23
16
  <span class="sl-hidden md:sl-block" aria-hidden="true">{Astro.locals.t('search.label')}</span>
24
17
  <kbd class="sl-hidden md:sl-flex" style="display: none;">
25
18
  <kbd>{Astro.locals.t('search.ctrlKey')}</kbd><kbd>K</kbd>
26
19
  </kbd>
27
- </button>
20
+ </Button>
28
21
 
29
22
  <DocsSearch
30
23
  client:only="react"
@@ -38,14 +31,6 @@ import '../../../components/variables.css';
38
31
  />
39
32
  </site-search>
40
33
 
41
- {
42
- SEARCH?.enableAISearch === true && (
43
- <button id="chat-button" popovertarget="stldocs-chat" data-open-modal>
44
- <Icon name="comment" />
45
- </button>
46
- )
47
- }
48
-
49
34
  <style>
50
35
  #chat-button {
51
36
  background: var(--sl-color-bg-ui);
@@ -1,19 +1,20 @@
1
1
  import * as React from 'react';
2
- import { BASE_PATH, SEARCH } from 'virtual:stl-starlight-virtual-module';
3
- import { parseRoute, generateRoute } from '@stainless-api/docs-ui/src/routing';
4
- import { SearchModal } from '@stainless-api/docs-ui/src/search/index';
5
- import { ChatModal } from '@stainless-api/docs-ui/src/components/chat';
2
+ import { BASE_PATH, HIGHLIGHT_THEMES } from 'virtual:stl-starlight-virtual-module';
3
+ import { parseRoute, generateRoute } from '@stainless-api/docs-ui/routing';
4
+ import { SearchModal } from '@stainless-api/docs-ui/search';
6
5
  import * as Markdoc from '@markdoc/markdoc';
7
6
  import { createHighlighter } from 'shiki';
8
7
  import type { BundledLanguage, BundledTheme, HighlighterGeneric } from 'shiki';
9
8
 
10
9
  import {
11
10
  DocsProvider,
11
+ type MarkdownContext,
12
12
  MarkdownProvider,
13
13
  NavigationProvider,
14
14
  SearchProvider,
15
- } from '@stainless-api/docs-ui/src/contexts';
16
- import type { SearchSettings } from '@stainless-api/docs-ui/src/search/types';
15
+ } from '@stainless-api/docs-ui/contexts';
16
+ import { ComponentProvider } from '@stainless-api/docs-ui/contexts/component';
17
+ import type { SearchSettings } from '@stainless-api/docs-ui/search/types';
17
18
 
18
19
  let $$highlighter: HighlighterGeneric<BundledLanguage, BundledTheme> | null = null;
19
20
  async function getHighlighter() {
@@ -27,7 +28,7 @@ async function getHighlighter() {
27
28
  return $$highlighter;
28
29
  }
29
30
 
30
- async function createMarkdownRenderer() {
31
+ async function createMarkdownRenderer(): Promise<MarkdownContext> {
31
32
  const highlighter = await getHighlighter();
32
33
  const markdocConfig: Markdoc.Config = {
33
34
  nodes: {
@@ -66,16 +67,25 @@ async function createMarkdownRenderer() {
66
67
  },
67
68
  };
68
69
 
69
- return (content: string) => {
70
- const ast = Markdoc.parse(content);
71
- const transformed = Markdoc.transform(ast, markdocConfig);
72
- return Markdoc.renderers.html(transformed);
70
+ return {
71
+ render: (content: string) => {
72
+ const ast = Markdoc.parse(content);
73
+ const transformed = Markdoc.transform(ast, markdocConfig);
74
+ return Markdoc.renderers.html(transformed);
75
+ },
76
+ highlight: (content: string, language: string) => {
77
+ return highlighter.codeToHtml(content, {
78
+ lang: language ?? 'javascript',
79
+ themes: HIGHLIGHT_THEMES || {},
80
+ });
81
+ },
73
82
  };
74
83
  }
75
84
 
76
85
  export function DocsSearch({ settings, currentPath }: { settings: SearchSettings; currentPath: string }) {
77
- const renderMarkdown = React.use(createMarkdownRenderer());
86
+ const markdownRenderer = React.use(createMarkdownRenderer());
78
87
  const { stainlessPath, language } = parseRoute(BASE_PATH, currentPath);
88
+ // eslint-disable-next-line turbo/no-undeclared-env-vars
79
89
  const pageFind = import.meta.env.DEV ? undefined : '/pagefind/pagefind.js';
80
90
 
81
91
  function handleSelect(path: string) {
@@ -85,16 +95,17 @@ export function DocsSearch({ settings, currentPath }: { settings: SearchSettings
85
95
 
86
96
  return (
87
97
  <DocsProvider spec={null} language={language}>
88
- <NavigationProvider basePath="/" selectedPath={stainlessPath}>
89
- <MarkdownProvider render={renderMarkdown}>
90
- <SearchProvider onSelect={handleSelect} pageFind={pageFind} settings={settings}>
91
- <div className="stldocs-root">
92
- <SearchModal id="stldocs-search" />
93
- {SEARCH?.enableAISearch === true && <ChatModal id="stldocs-chat" />}
94
- </div>
95
- </SearchProvider>
96
- </MarkdownProvider>
97
- </NavigationProvider>
98
+ <ComponentProvider>
99
+ <NavigationProvider basePath="/" selectedPath={stainlessPath}>
100
+ <MarkdownProvider {...markdownRenderer}>
101
+ <SearchProvider onSelect={handleSelect} pageFind={pageFind} settings={settings}>
102
+ <div className="stldocs-root">
103
+ <SearchModal id="stldocs-search" />
104
+ </div>
105
+ </SearchProvider>
106
+ </MarkdownProvider>
107
+ </NavigationProvider>
108
+ </ComponentProvider>
98
109
  </DocsProvider>
99
110
  );
100
111
  }
@@ -1,8 +1,8 @@
1
1
  // This is probably temporary, but it fills in functionality needed for Mintlify imports
2
2
 
3
3
  import type { StarlightRouteData } from '@astrojs/starlight/route-data';
4
- import type * as SDKJSON from '~/lib/json-spec-v2/types';
5
- import { walkTree } from '@stainless-api/docs-ui/src/routing';
4
+ import type * as SDKJSON from '@stainless/sdk-json';
5
+ import { walkTree } from '@stainless-api/docs-ui/routing';
6
6
 
7
7
  const INTERNAL_REFERENCE_ENTRY_MARKER = 'STL_STARLIGHT_API_REFERENCE_METHOD_LINK_PLACEHOLDER';
8
8