@stainless-api/docs 0.1.0-beta.7 → 0.1.0-beta.70
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 +554 -0
- package/README.md +1 -1
- package/eslint-suppressions.json +52 -0
- package/locals.d.ts +17 -0
- package/package.json +51 -40
- package/plugin/assets/languages/csharp.svg +1 -0
- package/plugin/buildAlgoliaIndex.ts +32 -7
- package/plugin/cms/server.ts +130 -58
- package/plugin/cms/sidebar-builder.ts +7 -26
- package/plugin/cms/worker.ts +83 -5
- package/plugin/components/MethodDescription.tsx +54 -0
- package/plugin/components/SDKSelect.astro +7 -87
- package/plugin/components/SnippetCode.tsx +53 -8
- package/plugin/components/search/SearchAlgolia.astro +45 -28
- package/plugin/components/search/SearchIsland.tsx +38 -24
- package/plugin/create-playground.shim.tsx +3 -0
- package/plugin/generateAPIReferenceLink.ts +2 -2
- package/plugin/globalJs/ai-dropdown-options.ts +243 -0
- package/plugin/globalJs/code-snippets.ts +15 -8
- package/plugin/globalJs/copy.ts +81 -16
- package/plugin/globalJs/method-descriptions.ts +33 -0
- package/plugin/globalJs/navigation.ts +7 -4
- package/plugin/helpers/generateDocsRoutes.ts +27 -0
- package/plugin/index.ts +178 -35
- package/plugin/languages.ts +5 -2
- package/plugin/loadPluginConfig.ts +121 -32
- package/plugin/middlewareBuilder/stainlessMiddleware.d.ts +1 -1
- package/plugin/react/Routing.tsx +208 -129
- package/plugin/referencePlaceholderUtils.ts +1 -1
- package/plugin/replaceSidebarPlaceholderMiddleware.ts +5 -1
- package/plugin/routes/Docs.astro +62 -89
- package/plugin/routes/DocsStatic.astro +1 -1
- package/plugin/routes/Overview.astro +10 -16
- package/plugin/routes/markdown.ts +9 -8
- package/plugin/vendor/preview.worker.docs.js +19768 -17702
- 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 +5 -5
- package/shared/getProsePages.ts +42 -0
- 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/AiChatIsland.tsx +14 -0
- package/stl-docs/components/{content-panel/ContentBreadcrumbs.tsx → ContentBreadcrumbs.tsx} +10 -18
- package/stl-docs/components/Head.astro +16 -0
- package/stl-docs/components/Header.astro +6 -8
- package/stl-docs/components/PageFrame.astro +18 -0
- package/stl-docs/components/PageTitle.astro +82 -0
- package/stl-docs/components/TableOfContents.astro +34 -0
- package/stl-docs/components/ThemeProvider.astro +36 -0
- package/stl-docs/components/ThemeSelect.astro +84 -139
- package/stl-docs/components/content-panel/ContentPanel.astro +16 -25
- 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 -5
- package/stl-docs/components/mintlify-compat/AccordionGroup.astro +7 -3
- 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/callouts/Callout.astro +1 -1
- package/stl-docs/components/mintlify-compat/callouts/Check.astro +1 -1
- package/stl-docs/components/mintlify-compat/callouts/Danger.astro +1 -1
- package/stl-docs/components/mintlify-compat/callouts/Info.astro +1 -1
- package/stl-docs/components/mintlify-compat/callouts/Note.astro +1 -1
- package/stl-docs/components/mintlify-compat/callouts/Tip.astro +1 -1
- package/stl-docs/components/mintlify-compat/callouts/Warning.astro +1 -1
- package/stl-docs/components/mintlify-compat/card.css +33 -35
- package/stl-docs/components/mintlify-compat/index.ts +2 -4
- package/stl-docs/components/nav-tabs/NavDropdown.astro +31 -70
- 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 +3 -2
- package/stl-docs/components/pagination/HomeLink.astro +10 -0
- package/stl-docs/components/pagination/Pagination.astro +175 -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/disableCalloutSyntax.ts +36 -0
- package/stl-docs/index.ts +141 -50
- package/stl-docs/loadStlDocsConfig.ts +45 -5
- package/stl-docs/proseMarkdown/proseMarkdownIntegration.ts +61 -0
- package/stl-docs/proseMarkdown/proseMarkdownMiddleware.ts +39 -0
- package/stl-docs/proseMarkdown/toMarkdown.ts +158 -0
- package/stl-docs/proseSearchIndexing.ts +450 -0
- package/stl-docs/tabsMiddleware.ts +11 -3
- package/styles/code.css +108 -140
- package/styles/fonts.css +32 -17
- package/styles/links.css +11 -48
- package/styles/method-descriptions.css +36 -0
- package/styles/overrides.css +48 -60
- package/styles/page.css +92 -52
- package/styles/sdk_select.css +9 -7
- package/styles/search.css +56 -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 +10 -10
- package/tsconfig.json +2 -5
- package/virtual-module.d.ts +26 -4
- package/components/variables.css +0 -135
- package/stl-docs/components/mintlify-compat/Step.astro +0 -58
- package/stl-docs/components/mintlify-compat/Steps.astro +0 -17
- /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
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
const dirName = import.meta.dirname;
|
|
3
|
+
/**
|
|
4
|
+
* Resolve a source file path relative to the stl-starlight package.
|
|
5
|
+
* @param projectPath - The relative path to the source file.
|
|
6
|
+
* @returns The absolute path to the source file.
|
|
7
|
+
*/
|
|
8
|
+
export function resolveSrcFile(...projectPath: string[]) {
|
|
9
|
+
return join(dirName, ...projectPath);
|
|
10
|
+
}
|
package/scripts/vendor_deps.ts
CHANGED
|
@@ -3,7 +3,7 @@ import fs from 'fs';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
|
|
6
|
-
import { Languages } from '@stainless-api/docs-ui/
|
|
6
|
+
import { Languages } from '@stainless-api/docs-ui/routing';
|
|
7
7
|
|
|
8
8
|
const DEPS_DIR = './plugin/vendor';
|
|
9
9
|
|
|
@@ -11,12 +11,12 @@ config();
|
|
|
11
11
|
|
|
12
12
|
const envSchema = z.object({
|
|
13
13
|
// absolute path to the Stainless monorepo root
|
|
14
|
-
|
|
14
|
+
STAINLESS_ROOT: z.string(),
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
const env = envSchema.parse(process.env);
|
|
18
18
|
|
|
19
|
-
console.log(`Using Stainless monorepo at ${env.
|
|
19
|
+
console.log(`Using Stainless monorepo at ${env.STAINLESS_ROOT}`);
|
|
20
20
|
|
|
21
21
|
if (fs.existsSync(DEPS_DIR)) {
|
|
22
22
|
fs.rmSync(DEPS_DIR, { recursive: true });
|
|
@@ -25,11 +25,11 @@ if (fs.existsSync(DEPS_DIR)) {
|
|
|
25
25
|
fs.mkdirSync(DEPS_DIR, { recursive: true });
|
|
26
26
|
|
|
27
27
|
const previewWorkerPath = path.join(
|
|
28
|
-
env.
|
|
28
|
+
env.STAINLESS_ROOT,
|
|
29
29
|
'/packages/preview-worker/dist/stainless/preview.worker.docs.js',
|
|
30
30
|
);
|
|
31
31
|
|
|
32
|
-
const readmeTemplatePath = path.join(env.
|
|
32
|
+
const readmeTemplatePath = path.join(env.STAINLESS_ROOT, '/legacy-dir-root/templates');
|
|
33
33
|
|
|
34
34
|
fs.copyFileSync(previewWorkerPath, path.join(DEPS_DIR, 'preview.worker.docs.js'));
|
|
35
35
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { readdir } from 'fs/promises';
|
|
2
|
+
import { join, relative } from 'path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Get all prose pages after a build, by reading all HTML files from the
|
|
6
|
+
* given output directory, and not from assets.
|
|
7
|
+
*
|
|
8
|
+
* We cannot use the `assets` map here because it is not guaranteed to
|
|
9
|
+
* contain all files, especially if they were generated by other integrations.
|
|
10
|
+
* Other astro integrations may hijack the "[...slug]" entrypoint, and any files
|
|
11
|
+
* previously in the [...slug] asset map entry would be lost (this is where starlight stores
|
|
12
|
+
* its prose HTML files).
|
|
13
|
+
*/
|
|
14
|
+
export async function getProsePages({
|
|
15
|
+
apiReferenceBasePath,
|
|
16
|
+
outputBasePath,
|
|
17
|
+
}: {
|
|
18
|
+
apiReferenceBasePath: string | null;
|
|
19
|
+
outputBasePath: string;
|
|
20
|
+
}): Promise<string[]> {
|
|
21
|
+
const allFiles = await readdir(outputBasePath, {
|
|
22
|
+
recursive: true,
|
|
23
|
+
withFileTypes: true,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const htmlFiles = allFiles
|
|
27
|
+
.filter((file) => file.isFile() && file.name.endsWith('.html'))
|
|
28
|
+
.map((file) => join(file.parentPath, file.name));
|
|
29
|
+
|
|
30
|
+
// Filter out API reference pages
|
|
31
|
+
const pagesToRender = htmlFiles.filter((absPath) => {
|
|
32
|
+
if (!apiReferenceBasePath) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
const relPath = relative(outputBasePath, absPath);
|
|
36
|
+
// Normalize by removing leading/trailing slashes from apiReferenceBasePath
|
|
37
|
+
const normalizedApiPath = apiReferenceBasePath.replace(/^\/+|\/+$/g, '');
|
|
38
|
+
return !relPath.startsWith(normalizedApiPath);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return pagesToRender;
|
|
42
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AstroIntegrationLogger } from 'astro';
|
|
2
|
+
|
|
3
|
+
let sharedLogger: AstroIntegrationLogger | null = null;
|
|
4
|
+
|
|
5
|
+
// This is probably temporary, but it's a quick way to share a logger between our many integrations
|
|
6
|
+
// we want to share a logger so they have the same "stainless" label
|
|
7
|
+
|
|
8
|
+
export function setSharedLogger(logger: AstroIntegrationLogger) {
|
|
9
|
+
sharedLogger = logger;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// a fallback is probably not required, but it's a good safeguard in case we somehow call a logger before the shared logger is set
|
|
13
|
+
export function getSharedLogger({ fallback }: { fallback: AstroIntegrationLogger }) {
|
|
14
|
+
return sharedLogger ?? fallback;
|
|
15
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Stub here so that `astro sync` generates the correct types for the `docs` content collection
|
|
2
|
+
|
|
3
|
+
import { defineCollection } from 'astro:content';
|
|
4
|
+
import { docsLoader } from '@astrojs/starlight/loaders';
|
|
5
|
+
import { docsSchema } from '@astrojs/starlight/schema';
|
|
6
|
+
|
|
7
|
+
export const collections = {
|
|
8
|
+
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
|
|
9
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { DropdownButton } from '@stainless-api/ui-primitives';
|
|
2
|
+
import { CopyIcon } from 'lucide-react';
|
|
3
|
+
import { ChatGPTIcon } from './icons/chat-gpt';
|
|
4
|
+
import { ClaudeIcon } from './icons/claude';
|
|
5
|
+
import { GeminiIcon } from './icons/gemini';
|
|
6
|
+
import { MarkdownIcon } from './icons/markdown';
|
|
7
|
+
import { CursorIcon } from './icons/cursor';
|
|
8
|
+
import React from 'react';
|
|
9
|
+
|
|
10
|
+
import { getAIDropdownOptions, type DropdownIcon } from '../../plugin/globalJs/ai-dropdown-options';
|
|
11
|
+
|
|
12
|
+
const iconMap: { [key in DropdownIcon]: React.ReactNode } = {
|
|
13
|
+
markdown: <MarkdownIcon />,
|
|
14
|
+
copy: <CopyIcon size={16} />,
|
|
15
|
+
claude: <ClaudeIcon />,
|
|
16
|
+
chatgpt: <ChatGPTIcon />,
|
|
17
|
+
gemini: <GeminiIcon />,
|
|
18
|
+
cursor: <CursorIcon />,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const { primaryAction, groups } = getAIDropdownOptions();
|
|
22
|
+
|
|
23
|
+
function ItemLabel({ label }: { label: string[] }) {
|
|
24
|
+
if (label.length > 1) {
|
|
25
|
+
return (
|
|
26
|
+
<DropdownButton.MenuItemText subtle>
|
|
27
|
+
{label[0]}
|
|
28
|
+
<strong>{label[1]}</strong>
|
|
29
|
+
</DropdownButton.MenuItemText>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<DropdownButton.MenuItemText>
|
|
35
|
+
<strong>{label[0]}</strong>
|
|
36
|
+
</DropdownButton.MenuItemText>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function AIDropdown() {
|
|
41
|
+
return (
|
|
42
|
+
<DropdownButton data-dropdown-id="ai-dropdown-button">
|
|
43
|
+
<DropdownButton.PrimaryAction>
|
|
44
|
+
{iconMap[primaryAction.icon]}
|
|
45
|
+
<DropdownButton.PrimaryActionText>{primaryAction.label}</DropdownButton.PrimaryActionText>
|
|
46
|
+
</DropdownButton.PrimaryAction>
|
|
47
|
+
<DropdownButton.Trigger />
|
|
48
|
+
<DropdownButton.Menu>
|
|
49
|
+
{groups.map((group) => (
|
|
50
|
+
<React.Fragment key={group.reactKey}>
|
|
51
|
+
{group.options.map((option) => (
|
|
52
|
+
<DropdownButton.MenuItem value={option.id} isExternalLink={option.external} key={option.id}>
|
|
53
|
+
<DropdownButton.Icon>{iconMap[option.icon]}</DropdownButton.Icon>
|
|
54
|
+
<ItemLabel label={option.label} />
|
|
55
|
+
</DropdownButton.MenuItem>
|
|
56
|
+
))}
|
|
57
|
+
{group.isLast ? null : <hr />}
|
|
58
|
+
</React.Fragment>
|
|
59
|
+
))}
|
|
60
|
+
</DropdownButton.Menu>
|
|
61
|
+
</DropdownButton>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DocsLanguage } from '@stainless-api/docs-ui/routing';
|
|
2
|
+
import AiChat, { STAINLESS_PROJECT } from 'virtual:stl-docs/components/AiChat.tsx';
|
|
3
|
+
|
|
4
|
+
export default function AiChatIsland({
|
|
5
|
+
currentLanguage,
|
|
6
|
+
siteTitle,
|
|
7
|
+
}: {
|
|
8
|
+
currentLanguage: DocsLanguage | undefined;
|
|
9
|
+
siteTitle: string | undefined;
|
|
10
|
+
}) {
|
|
11
|
+
if (!AiChat) throw new Error('AiChatIsland was rendered but could not load AiChat component');
|
|
12
|
+
if (!STAINLESS_PROJECT) return null;
|
|
13
|
+
return <AiChat projectId={STAINLESS_PROJECT} language={currentLanguage} siteTitle={siteTitle} />;
|
|
14
|
+
}
|
|
@@ -1,29 +1,26 @@
|
|
|
1
1
|
import { ChevronRight } from 'lucide-react';
|
|
2
|
-
import { Join } from '@stainless-api/docs-ui/
|
|
3
|
-
import style from '@stainless-api/docs-ui/
|
|
2
|
+
import { Join } from '@stainless-api/docs-ui/components';
|
|
3
|
+
import style from '@stainless-api/docs-ui/style';
|
|
4
4
|
import type { StarlightRouteData } from '@astrojs/starlight/route-data';
|
|
5
5
|
|
|
6
6
|
type Breadcrumb = { title: string; href: string };
|
|
7
7
|
|
|
8
|
-
// because this component is used in Stainless Docs and stl-starlight, we need to conditionally import the BASE_PATH from the virtual module
|
|
9
|
-
let basePath: string | null = null;
|
|
10
|
-
try {
|
|
11
|
-
const mod = await import('virtual:stl-starlight-virtual-module');
|
|
12
|
-
basePath = mod.BASE_PATH;
|
|
13
|
-
// eslint-disable-next-line no-empty, @typescript-eslint/no-unused-vars
|
|
14
|
-
} catch (_e) {}
|
|
15
|
-
|
|
16
8
|
// Normalize paths to avoid mismatches due to trailing slashes
|
|
17
9
|
function normalizePath(path: string) {
|
|
18
10
|
return path.endsWith('/') ? path : path + '/';
|
|
19
11
|
}
|
|
20
12
|
|
|
21
|
-
function findBreadcrumbTrail(
|
|
22
|
-
|
|
13
|
+
export function findBreadcrumbTrail(
|
|
14
|
+
sidebarEntry: StarlightRouteData['sidebar'],
|
|
23
15
|
targetPath: string,
|
|
24
16
|
includeCurrentPage: boolean,
|
|
25
17
|
trail: Breadcrumb[] = [],
|
|
26
18
|
): Breadcrumb[] | null {
|
|
19
|
+
const entries = sidebarEntry.filter((entry) => {
|
|
20
|
+
return !(
|
|
21
|
+
entry as StarlightRouteData['sidebar'][number] & { attrs?: { class?: string } }
|
|
22
|
+
).attrs?.class?.includes('stl-mobile-only-sidebar-item');
|
|
23
|
+
});
|
|
27
24
|
const normalizedTarget = normalizePath(targetPath);
|
|
28
25
|
|
|
29
26
|
for (const entry of entries) {
|
|
@@ -57,12 +54,7 @@ export function ContentBreadcrumbs({
|
|
|
57
54
|
currentPath: string;
|
|
58
55
|
sidebarEntry: StarlightRouteData['sidebar'];
|
|
59
56
|
}) {
|
|
60
|
-
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const entryWithoutTopLevelLinks = sidebarEntry.filter((entry) => entry.type !== 'link');
|
|
65
|
-
const breadcrumbs = findBreadcrumbTrail(entryWithoutTopLevelLinks, currentPath, true);
|
|
57
|
+
const breadcrumbs = findBreadcrumbTrail(sidebarEntry, currentPath, true);
|
|
66
58
|
|
|
67
59
|
if (!breadcrumbs) {
|
|
68
60
|
return null;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Default from '@astrojs/starlight/components/Head.astro';
|
|
3
|
+
|
|
4
|
+
// TODO: for users who are overriding the font stack in their own styles, how can we know that and
|
|
5
|
+
// preload their font instead of ours?
|
|
6
|
+
import geistPath from '../../assets/fonts/geist/geist-latin.woff2';
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<Default />
|
|
10
|
+
|
|
11
|
+
<link rel="preload" as="font" type="font/woff2" crossorigin="anonymous" href={geistPath} />
|
|
12
|
+
|
|
13
|
+
<script>
|
|
14
|
+
import { wireAIDropdown } from '../../plugin/globalJs/ai-dropdown-options.ts';
|
|
15
|
+
wireAIDropdown();
|
|
16
|
+
</script>
|
|
@@ -23,12 +23,9 @@ const shouldRenderSearch = !!(
|
|
|
23
23
|
|
|
24
24
|
<style is:global>
|
|
25
25
|
@layer starlight.core {
|
|
26
|
-
header
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
&.header {
|
|
30
|
-
border-bottom-color: var(--sl-color-hairline);
|
|
31
|
-
}
|
|
26
|
+
header,
|
|
27
|
+
header.header {
|
|
28
|
+
border-color: var(--stl-color-border-faint);
|
|
32
29
|
}
|
|
33
30
|
|
|
34
31
|
.header {
|
|
@@ -44,9 +41,10 @@ const shouldRenderSearch = !!(
|
|
|
44
41
|
overflow: clip;
|
|
45
42
|
/* Avoid clipping focus ring around link inside title wrapper. */
|
|
46
43
|
padding: 0.25rem;
|
|
47
|
-
padding-left: 0;
|
|
48
44
|
margin: -0.25rem;
|
|
49
45
|
min-width: 0;
|
|
46
|
+
/* Max height should match button height */
|
|
47
|
+
max-height: 32px;
|
|
50
48
|
}
|
|
51
49
|
|
|
52
50
|
.default-tabs-container {
|
|
@@ -84,7 +82,7 @@ const shouldRenderSearch = !!(
|
|
|
84
82
|
|
|
85
83
|
@media (min-width: 50rem) {
|
|
86
84
|
.default-tabs-container {
|
|
87
|
-
min-width:
|
|
85
|
+
min-width: 540px;
|
|
88
86
|
}
|
|
89
87
|
}
|
|
90
88
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Default from '@astrojs/starlight/components/PageFrame.astro';
|
|
3
|
+
import AiChat from 'virtual:stl-docs/components/AiChat.tsx'; // conditionally resolves to null if ai chat module is not injected
|
|
4
|
+
import AiChatIsland from './AiChatIsland.tsx'; // entrypoint for client island can’t be a virtual module
|
|
5
|
+
|
|
6
|
+
import starlightConfig from 'virtual:starlight/user-config';
|
|
7
|
+
const locale = Astro.currentLocale ?? starlightConfig.defaultLocale.lang;
|
|
8
|
+
const siteTitle = locale && starlightConfig.title[locale];
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<Default>
|
|
12
|
+
<slot name="header" slot="header" />
|
|
13
|
+
<slot name="sidebar" slot="sidebar" />
|
|
14
|
+
|
|
15
|
+
<slot />
|
|
16
|
+
|
|
17
|
+
{!!AiChat && <AiChatIsland client:load currentLanguage={Astro.locals.language} siteTitle={siteTitle} />}
|
|
18
|
+
</Default>
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
import {
|
|
3
|
+
ENABLE_PROSE_MARKDOWN_RENDERING,
|
|
4
|
+
ENABLE_CONTEXT_MENU,
|
|
5
|
+
RENDER_PAGE_DESCRIPTIONS,
|
|
6
|
+
} from 'virtual:stl-docs-virtual-module';
|
|
7
|
+
import type { StarlightRouteData } from '@astrojs/starlight/route-data';
|
|
8
|
+
import Default from '@astrojs/starlight/components/PageTitle.astro';
|
|
9
|
+
import { ContentBreadcrumbs } from './ContentBreadcrumbs';
|
|
10
|
+
import { AIDropdown } from './AIDropdown';
|
|
11
|
+
|
|
12
|
+
function sidebarHasEntry(sidebarEntry: StarlightRouteData['sidebar'], currentPath?: string) {
|
|
13
|
+
if (!currentPath) return false;
|
|
14
|
+
const normalizePath = (path: string) => {
|
|
15
|
+
return path.endsWith('/') ? path : path + '/';
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const normalizedCurrent = normalizePath(currentPath);
|
|
19
|
+
|
|
20
|
+
for (const entry of sidebarEntry) {
|
|
21
|
+
if (entry.type === 'link') {
|
|
22
|
+
const normalizedHref = normalizePath(entry.href);
|
|
23
|
+
if (normalizedHref === normalizedCurrent) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
} else if (entry.type === 'group') {
|
|
27
|
+
const hasInGroup = sidebarHasEntry(entry.entries, currentPath);
|
|
28
|
+
if (hasInGroup) return true;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const skipRenderingStarlightTitle = Astro.locals._stlStarlightPage?.skipRenderingStarlightTitle ?? false;
|
|
36
|
+
|
|
37
|
+
const hasMarkdownRoute = Astro.locals._stlStarlightPage?.hasMarkdownRoute ?? true;
|
|
38
|
+
// ⬆️ hopefully this is temporary. But for now, we don't have a markdown representation of the API reference overview page
|
|
39
|
+
|
|
40
|
+
const currentPath = Astro.url.pathname;
|
|
41
|
+
|
|
42
|
+
function shouldShowAIDropdown() {
|
|
43
|
+
// Hide if there is no associated sidebar entry. This applies to pages like the 404 page.
|
|
44
|
+
const hasSidebarEntry = sidebarHasEntry(Astro.locals.starlightRoute.sidebar, currentPath);
|
|
45
|
+
if (!hasSidebarEntry) return false;
|
|
46
|
+
|
|
47
|
+
if (!hasMarkdownRoute) return false;
|
|
48
|
+
|
|
49
|
+
if (!ENABLE_PROSE_MARKDOWN_RENDERING) return false;
|
|
50
|
+
if (!ENABLE_CONTEXT_MENU) return false;
|
|
51
|
+
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const showAIDropdown = shouldShowAIDropdown();
|
|
56
|
+
|
|
57
|
+
const description = Astro.locals.starlightRoute.entry.data.description;
|
|
58
|
+
const shouldRenderDescription = RENDER_PAGE_DESCRIPTIONS;
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
{
|
|
62
|
+
skipRenderingStarlightTitle ? null : (
|
|
63
|
+
<>
|
|
64
|
+
<div class="stl-ui-not-prose stl-page-nav-container stl-prose-page-nav-container">
|
|
65
|
+
<ContentBreadcrumbs currentPath={currentPath} sidebarEntry={Astro.locals.starlightRoute.sidebar} />
|
|
66
|
+
{showAIDropdown && <AIDropdown />}
|
|
67
|
+
</div>
|
|
68
|
+
<Default />
|
|
69
|
+
{!!description && shouldRenderDescription && <p class="description">{description}</p>}
|
|
70
|
+
</>
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
<style>
|
|
75
|
+
p.description {
|
|
76
|
+
font-size: var(--stl-typography-scale-xl);
|
|
77
|
+
font-weight: 400;
|
|
78
|
+
line-height: 1.4;
|
|
79
|
+
letter-spacing: -0.02em;
|
|
80
|
+
margin-top: 0.4em;
|
|
81
|
+
}
|
|
82
|
+
</style>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Default from '@astrojs/starlight/components/TableOfContents.astro';
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
<Default {...Astro.props} />
|
|
6
|
+
|
|
7
|
+
<script>
|
|
8
|
+
/**
|
|
9
|
+
* Starlight will mark TOC links as active as they are scrolled to. However, it does not mark
|
|
10
|
+
* a link as active if it cannot be scrolled to on the page. This happens for small sections at
|
|
11
|
+
* the bottom of the page which are not large enough to scroll to the top of the viewport.
|
|
12
|
+
*
|
|
13
|
+
* This script will mark a section as active if its corresponding hash is in the URL, even if
|
|
14
|
+
* it cannot be scrolled to.
|
|
15
|
+
*/
|
|
16
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
17
|
+
const tocLinks = document.querySelectorAll('starlight-toc a') as NodeListOf<HTMLAnchorElement>;
|
|
18
|
+
|
|
19
|
+
function updateAriaCurrent() {
|
|
20
|
+
const current = decodeURIComponent(window.location.hash || '');
|
|
21
|
+
tocLinks.forEach((link) => {
|
|
22
|
+
const linkHash = decodeURIComponent(link.hash || link.getAttribute('href') || '');
|
|
23
|
+
if (linkHash === current) {
|
|
24
|
+
link.setAttribute('aria-current', 'true');
|
|
25
|
+
} else {
|
|
26
|
+
link.removeAttribute('aria-current');
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
window.addEventListener('hashchange', updateAriaCurrent);
|
|
32
|
+
updateAriaCurrent();
|
|
33
|
+
});
|
|
34
|
+
</script>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{/* Inlined to avoid FOUC. All theme selects are initialized here */}
|
|
2
|
+
<script is:inline>
|
|
3
|
+
window.didInitThemePickers = window.didInitThemePickers ?? false;
|
|
4
|
+
|
|
5
|
+
// Only run once.
|
|
6
|
+
if (!window.didInitThemePickers) {
|
|
7
|
+
window.didInitThemePickers = true;
|
|
8
|
+
|
|
9
|
+
// The stored theme will be either 'auto', 'light', 'dark' or null.
|
|
10
|
+
const storedTheme = typeof localStorage !== 'undefined' && localStorage.getItem('starlight-theme');
|
|
11
|
+
|
|
12
|
+
// This theme is either 'light' or 'dark'. It's used for setting the data-theme attribute.
|
|
13
|
+
const theme =
|
|
14
|
+
!storedTheme || storedTheme === 'auto'
|
|
15
|
+
? window.matchMedia('(prefers-color-scheme: light)').matches
|
|
16
|
+
? 'light'
|
|
17
|
+
: 'dark'
|
|
18
|
+
: storedTheme;
|
|
19
|
+
|
|
20
|
+
document.documentElement.dataset.theme = theme === 'light' ? 'light' : 'dark';
|
|
21
|
+
|
|
22
|
+
const themeSelects = document.querySelectorAll('[data-theme-select]');
|
|
23
|
+
const selectedThemeValue = storedTheme || 'auto';
|
|
24
|
+
|
|
25
|
+
themeSelects.forEach((select) => {
|
|
26
|
+
const tmpl = select.querySelector(`[data-value="${selectedThemeValue}"] template`);
|
|
27
|
+
const selectedSlot = select.querySelector('[data-part="trigger-selected"]');
|
|
28
|
+
|
|
29
|
+
selectedSlot.innerHTML = '';
|
|
30
|
+
if (tmpl) {
|
|
31
|
+
selectedSlot.appendChild(tmpl.content.cloneNode(true));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
</script>
|