@stainless-api/docs 0.1.0-beta.6 → 0.1.0-beta.60

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 (115) hide show
  1. package/CHANGELOG.md +476 -0
  2. package/README.md +1 -1
  3. package/eslint-suppressions.json +52 -0
  4. package/locals.d.ts +16 -0
  5. package/package.json +45 -40
  6. package/plugin/assets/languages/csharp.svg +1 -0
  7. package/plugin/buildAlgoliaIndex.ts +32 -7
  8. package/plugin/cms/server.ts +130 -58
  9. package/plugin/cms/sidebar-builder.ts +7 -26
  10. package/plugin/cms/worker.ts +83 -5
  11. package/plugin/components/MethodDescription.tsx +54 -0
  12. package/plugin/components/SDKSelect.astro +7 -87
  13. package/plugin/components/SnippetCode.tsx +53 -8
  14. package/plugin/components/search/SearchAlgolia.astro +14 -26
  15. package/plugin/components/search/SearchIsland.tsx +38 -24
  16. package/plugin/create-playground.shim.tsx +3 -0
  17. package/plugin/generateAPIReferenceLink.ts +2 -2
  18. package/plugin/globalJs/ai-dropdown-options.ts +235 -0
  19. package/plugin/globalJs/code-snippets.ts +15 -8
  20. package/plugin/globalJs/copy.ts +81 -16
  21. package/plugin/globalJs/method-descriptions.ts +33 -0
  22. package/plugin/globalJs/navigation.ts +7 -4
  23. package/plugin/index.ts +179 -35
  24. package/plugin/languages.ts +5 -2
  25. package/plugin/loadPluginConfig.ts +121 -32
  26. package/plugin/middlewareBuilder/stainlessMiddleware.d.ts +1 -1
  27. package/plugin/react/Routing.tsx +208 -104
  28. package/plugin/referencePlaceholderUtils.ts +1 -1
  29. package/plugin/replaceSidebarPlaceholderMiddleware.ts +5 -1
  30. package/plugin/routes/Docs.astro +61 -83
  31. package/plugin/routes/Overview.astro +10 -16
  32. package/plugin/routes/markdown.ts +7 -7
  33. package/plugin/vendor/preview.worker.docs.js +19768 -17702
  34. package/plugin/vendor/templates/go.md +1 -1
  35. package/plugin/vendor/templates/python.md +1 -1
  36. package/resolveSrcFile.ts +10 -0
  37. package/scripts/vendor_deps.ts +5 -5
  38. package/shared/getSharedLogger.ts +15 -0
  39. package/shared/terminalUtils.ts +3 -0
  40. package/src/content.config.ts +9 -0
  41. package/stl-docs/components/AIDropdown.tsx +63 -0
  42. package/stl-docs/components/AiChatIsland.tsx +10 -0
  43. package/stl-docs/components/{content-panel/ContentBreadcrumbs.tsx → ContentBreadcrumbs.tsx} +10 -18
  44. package/stl-docs/components/Head.astro +16 -0
  45. package/stl-docs/components/Header.astro +6 -8
  46. package/stl-docs/components/PageFrame.astro +14 -0
  47. package/stl-docs/components/PageTitle.astro +82 -0
  48. package/stl-docs/components/TableOfContents.astro +34 -0
  49. package/stl-docs/components/ThemeSelect.astro +118 -136
  50. package/stl-docs/components/content-panel/ContentPanel.astro +16 -25
  51. package/stl-docs/components/headers/SplashMobileMenuToggle.astro +17 -1
  52. package/stl-docs/components/headers/StackedHeader.astro +29 -24
  53. package/stl-docs/components/icons/chat-gpt.tsx +17 -0
  54. package/stl-docs/components/icons/claude.tsx +10 -0
  55. package/stl-docs/components/icons/cursor.tsx +10 -0
  56. package/stl-docs/components/icons/gemini.tsx +19 -0
  57. package/stl-docs/components/icons/markdown.tsx +10 -0
  58. package/stl-docs/components/index.ts +1 -0
  59. package/stl-docs/components/mintlify-compat/Accordion.astro +7 -5
  60. package/stl-docs/components/mintlify-compat/AccordionGroup.astro +7 -3
  61. package/stl-docs/components/mintlify-compat/Columns.astro +40 -42
  62. package/stl-docs/components/mintlify-compat/Frame.astro +16 -18
  63. package/stl-docs/components/mintlify-compat/Step.astro +30 -32
  64. package/stl-docs/components/mintlify-compat/Steps.astro +8 -10
  65. package/stl-docs/components/mintlify-compat/callouts/Callout.astro +1 -1
  66. package/stl-docs/components/mintlify-compat/callouts/Check.astro +1 -1
  67. package/stl-docs/components/mintlify-compat/callouts/Danger.astro +1 -1
  68. package/stl-docs/components/mintlify-compat/callouts/Info.astro +1 -1
  69. package/stl-docs/components/mintlify-compat/callouts/Note.astro +1 -1
  70. package/stl-docs/components/mintlify-compat/callouts/Tip.astro +1 -1
  71. package/stl-docs/components/mintlify-compat/callouts/Warning.astro +1 -1
  72. package/stl-docs/components/mintlify-compat/card.css +33 -35
  73. package/stl-docs/components/nav-tabs/NavDropdown.astro +31 -70
  74. package/stl-docs/components/nav-tabs/NavTabs.astro +78 -80
  75. package/stl-docs/components/nav-tabs/SecondaryNavTabs.astro +15 -8
  76. package/stl-docs/components/nav-tabs/buildNavLinks.ts +3 -2
  77. package/stl-docs/components/pagination/HomeLink.astro +10 -0
  78. package/stl-docs/components/pagination/Pagination.astro +175 -0
  79. package/stl-docs/components/pagination/PaginationLinkEmphasized.astro +22 -0
  80. package/stl-docs/components/pagination/PaginationLinkQuiet.astro +13 -0
  81. package/stl-docs/components/pagination/util.ts +71 -0
  82. package/stl-docs/components/scripts.ts +1 -0
  83. package/stl-docs/disableCalloutSyntax.ts +36 -0
  84. package/stl-docs/index.ts +121 -48
  85. package/stl-docs/loadStlDocsConfig.ts +44 -4
  86. package/stl-docs/proseMarkdown/proseMarkdownIntegration.ts +64 -0
  87. package/stl-docs/proseMarkdown/proseMarkdownMiddleware.ts +34 -0
  88. package/stl-docs/proseMarkdown/toMarkdown.ts +158 -0
  89. package/stl-docs/proseSearchIndexing.ts +113 -0
  90. package/stl-docs/tabsMiddleware.ts +11 -3
  91. package/styles/code.css +108 -140
  92. package/styles/fonts.css +32 -17
  93. package/styles/links.css +11 -48
  94. package/styles/method-descriptions.css +36 -0
  95. package/styles/overrides.css +48 -60
  96. package/styles/page.css +92 -52
  97. package/styles/sdk_select.css +9 -7
  98. package/styles/search.css +58 -69
  99. package/styles/sidebar.css +211 -131
  100. package/styles/{variables.css → sl-variables.css} +3 -2
  101. package/styles/stldocs-variables.css +6 -0
  102. package/styles/toc.css +41 -34
  103. package/theme.css +10 -10
  104. package/tsconfig.json +2 -5
  105. package/virtual-module.d.ts +23 -3
  106. package/components/variables.css +0 -135
  107. /package/{plugin/assets → assets}/fonts/geist/OFL.txt +0 -0
  108. /package/{plugin/assets → assets}/fonts/geist/geist-italic-latin-ext.woff2 +0 -0
  109. /package/{plugin/assets → assets}/fonts/geist/geist-italic-latin.woff2 +0 -0
  110. /package/{plugin/assets → assets}/fonts/geist/geist-latin-ext.woff2 +0 -0
  111. /package/{plugin/assets → assets}/fonts/geist/geist-latin.woff2 +0 -0
  112. /package/{plugin/assets → assets}/fonts/geist/geist-mono-italic-latin-ext.woff2 +0 -0
  113. /package/{plugin/assets → assets}/fonts/geist/geist-mono-italic-latin.woff2 +0 -0
  114. /package/{plugin/assets → assets}/fonts/geist/geist-mono-latin-ext.woff2 +0 -0
  115. /package/{plugin/assets → assets}/fonts/geist/geist-mono-latin.woff2 +0 -0
@@ -31,7 +31,7 @@ SDK_ReleasePleaseMarkdownBlockEnd
31
31
 
32
32
  ## Requirements
33
33
 
34
- This library requires Go 1.18+.
34
+ This library requires Go 1.22+.
35
35
 
36
36
  ## Usage
37
37
 
@@ -242,7 +242,7 @@ print(SDK_PythonPackageImportName.__version__)
242
242
 
243
243
  ## Requirements
244
244
 
245
- Python 3.8 or higher.
245
+ Python 3.9 or higher.
246
246
 
247
247
  ## Contributing
248
248
 
@@ -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
+ }
@@ -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/src/routing';
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
- STAINLESS_MONOREPO_PATH: z.string(),
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.STAINLESS_MONOREPO_PATH}`);
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.STAINLESS_MONOREPO_PATH,
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.STAINLESS_MONOREPO_PATH, '/legacy-dir-root/templates');
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,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,3 @@
1
+ export function bold(text: string) {
2
+ return `\x1b[1m${text}\x1b[0m`;
3
+ }
@@ -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,10 @@
1
+ import type { DocsLanguage } from '@stainless-api/docs-ui/routing';
2
+ import AiChat from 'virtual:stl-docs/components/AiChat.tsx';
3
+ // right now loading AiChat without API reference plugin is unsupported
4
+ // because the AiChat is for talking about the SDKs
5
+ import { STAINLESS_PROJECT } from 'virtual:stl-starlight-virtual-module';
6
+
7
+ export default function AiChatIsland({ currentLanguage }: { currentLanguage: DocsLanguage | undefined }) {
8
+ if (!AiChat) throw new Error('AiChatIsland was rendered but could not load AiChat component');
9
+ return <AiChat projectId={STAINLESS_PROJECT} language={currentLanguage} />;
10
+ }
@@ -1,29 +1,26 @@
1
1
  import { ChevronRight } from 'lucide-react';
2
- import { Join } from '@stainless-api/docs-ui/src/components';
3
- import style from '@stainless-api/docs-ui/src/style';
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
- entries: StarlightRouteData['sidebar'],
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
- if (basePath && currentPath.startsWith(basePath)) {
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
- border-color: var(--sl-color-hairline);
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: 440px;
85
+ min-width: 540px;
88
86
  }
89
87
  }
90
88
  }
@@ -0,0 +1,14 @@
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
+
7
+ <Default>
8
+ <slot name="header" slot="header" />
9
+ <slot name="sidebar" slot="sidebar" />
10
+
11
+ <slot />
12
+
13
+ {!!AiChat && <AiChatIsland client:load currentLanguage={Astro.locals.language} />}
14
+ </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>