@stainless-api/docs 0.1.0-beta.13 → 0.1.0-beta.130
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 +1102 -0
- package/ambient.d.ts +6 -0
- package/eslint-suppressions.json +90 -0
- package/{eslint.config.js → eslint.config.ts} +0 -2
- package/locals.d.ts +17 -0
- package/package.json +62 -44
- package/playground-virtual-modules.d.ts +96 -0
- package/plugin/assets/languages/cli.svg +14 -0
- package/plugin/assets/languages/csharp.svg +1 -0
- package/plugin/assets/languages/php.svg +4 -0
- package/plugin/buildAlgoliaIndex.ts +40 -39
- package/plugin/components/MethodDescription.tsx +54 -0
- package/plugin/components/RequestBuilder/ParamEditor.tsx +55 -0
- package/plugin/components/RequestBuilder/SnippetStainlessIsland.tsx +107 -0
- package/plugin/components/RequestBuilder/index.tsx +40 -0
- package/plugin/components/RequestBuilder/props.ts +9 -0
- package/plugin/components/RequestBuilder/spec-helpers.ts +47 -0
- package/plugin/components/RequestBuilder/styles.css +67 -0
- package/plugin/components/SDKSelect.astro +18 -111
- package/plugin/components/SnippetCode.tsx +112 -70
- package/plugin/components/StainlessIslands.tsx +126 -0
- package/plugin/components/search/SearchAlgolia.astro +46 -29
- package/plugin/components/search/SearchIsland.tsx +61 -37
- package/plugin/generateAPIReferenceLink.ts +0 -40
- package/plugin/globalJs/ai-dropdown-options.ts +248 -0
- package/plugin/globalJs/code-snippets.ts +45 -16
- package/plugin/globalJs/copy.ts +115 -27
- package/plugin/globalJs/create-playground.shim.ts +3 -0
- package/plugin/globalJs/method-descriptions.ts +33 -0
- package/plugin/globalJs/navigation.ts +24 -44
- package/plugin/globalJs/playground-data.shim.ts +1 -0
- package/plugin/globalJs/playground-data.ts +14 -0
- package/plugin/globalJs/summary-selection-tweak.ts +29 -0
- package/plugin/helpers/generateDocsRoutes.ts +59 -0
- package/plugin/helpers/multiSpec.ts +8 -0
- package/plugin/index.ts +317 -141
- package/plugin/languages.ts +8 -2
- package/plugin/loadPluginConfig.ts +284 -109
- package/plugin/markdown/highlighter.ts +100 -0
- package/plugin/markdown/index.ts +39 -0
- package/plugin/middlewareBuilder/stainlessMiddleware.d.ts +3 -1
- package/plugin/react/Routing.tsx +98 -263
- package/plugin/referencePlaceholderUtils.ts +17 -14
- package/plugin/replaceSidebarPlaceholderMiddleware.ts +39 -35
- package/plugin/routes/Docs.astro +72 -111
- package/plugin/routes/DocsStatic.astro +6 -5
- package/plugin/routes/Overview.astro +46 -22
- package/plugin/routes/llms.ts +186 -0
- package/plugin/routes/markdown.ts +13 -12
- package/plugin/{cms → sidebar-utils}/sidebar-builder.ts +84 -69
- package/plugin/specs/FileCache.ts +99 -0
- package/plugin/specs/fetchSpecSSR.ts +27 -0
- package/plugin/specs/generateSpec.ts +112 -0
- package/plugin/specs/index.ts +132 -0
- package/plugin/specs/inputResolver.ts +148 -0
- package/plugin/{cms → specs}/worker.ts +82 -5
- package/plugin/vendor/preview.worker.docs.js +27121 -16890
- package/plugin/vendor/templates/cli.md +1 -0
- package/plugin/vendor/templates/go.md +4 -2
- package/plugin/vendor/templates/java.md +5 -1
- package/plugin/vendor/templates/kotlin.md +5 -1
- package/plugin/vendor/templates/node.md +4 -2
- package/plugin/vendor/templates/python.md +4 -2
- package/plugin/vendor/templates/ruby.md +4 -2
- package/plugin/vendor/templates/terraform.md +1 -1
- package/plugin/vendor/templates/typescript.md +3 -1
- package/resolveSrcFile.ts +10 -0
- package/scripts/vendor_deps.ts +5 -5
- package/shared/conditionalIntegration.ts +28 -0
- package/shared/getProsePages.ts +41 -0
- package/shared/getSharedLogger.ts +15 -0
- package/shared/terminalUtils.ts +3 -0
- package/shared/virtualModule.ts +46 -1
- package/src/content.config.ts +9 -0
- package/stl-docs/aiChatExamples.ts +95 -0
- package/stl-docs/chat/docs-chat-handler.ts +18 -0
- package/stl-docs/chat/hook.ts +215 -0
- package/stl-docs/chat/schemas.ts +70 -0
- package/stl-docs/chat/stainless-handler/index.ts +126 -0
- package/stl-docs/chat/stream-util.ts +16 -0
- package/stl-docs/chat/ui/AiChat.module.css +591 -0
- package/stl-docs/chat/ui/AiChat.tsx +188 -0
- package/stl-docs/chat/ui/Trigger.tsx +154 -0
- package/stl-docs/chat/ui/components/ChatControls.tsx +51 -0
- package/stl-docs/chat/ui/components/ChatEmpty.tsx +42 -0
- package/stl-docs/chat/ui/components/ChatLog.tsx +96 -0
- package/stl-docs/chat/ui/components/ChatMessage.tsx +47 -0
- package/stl-docs/chat/ui/components/CodeBlock.tsx +33 -0
- package/stl-docs/chat/ui/components/MessageFeedback.tsx +109 -0
- package/stl-docs/chat/ui/components/Table.tsx +15 -0
- package/stl-docs/chat/ui/components/ToolCall.tsx +34 -0
- package/stl-docs/chat/ui/components/hljs-github.css +81 -0
- package/stl-docs/chat/ui/scroll-manager.ts +86 -0
- package/stl-docs/chat/ui/types.ts +45 -0
- package/stl-docs/components/AIDropdown.tsx +63 -0
- package/stl-docs/components/AiChatIsland.tsx +16 -0
- package/stl-docs/components/{content-panel/ContentBreadcrumbs.tsx → ContentBreadcrumbs.tsx} +2 -2
- package/stl-docs/components/ContentPanel.astro +9 -0
- package/stl-docs/components/Footer.astro +89 -0
- package/stl-docs/components/Head.astro +20 -0
- package/stl-docs/components/Header.astro +3 -9
- package/stl-docs/components/PageFrame.astro +37 -0
- package/stl-docs/components/PageSidebar.astro +11 -0
- package/stl-docs/components/PageTitle.astro +82 -0
- package/stl-docs/components/StainlessLogo.svg +4 -0
- package/stl-docs/components/ThemeProvider.astro +36 -0
- package/stl-docs/components/ThemeSelect.astro +84 -146
- package/stl-docs/components/TwoColumnContent.astro +2 -0
- package/stl-docs/components/headers/DefaultHeader.astro +6 -8
- package/stl-docs/components/headers/StackedHeader.astro +10 -53
- package/stl-docs/components/icons/chat-gpt.tsx +2 -2
- 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 +1 -1
- package/stl-docs/components/index.ts +1 -0
- package/stl-docs/components/mintlify-compat/Accordion.astro +2 -2
- package/stl-docs/components/mintlify-compat/AccordionGroup.astro +0 -4
- package/stl-docs/components/mintlify-compat/Columns.astro +2 -2
- package/stl-docs/components/mintlify-compat/Frame.astro +6 -6
- package/stl-docs/components/mintlify-compat/Tab.astro +2 -2
- package/stl-docs/components/mintlify-compat/callouts/Callout.astro +2 -2
- package/stl-docs/components/mintlify-compat/callouts/Check.astro +0 -4
- package/stl-docs/components/mintlify-compat/callouts/Danger.astro +0 -4
- package/stl-docs/components/mintlify-compat/callouts/Info.astro +0 -4
- package/stl-docs/components/mintlify-compat/callouts/Note.astro +0 -4
- package/stl-docs/components/mintlify-compat/callouts/Tip.astro +0 -4
- package/stl-docs/components/mintlify-compat/callouts/Warning.astro +0 -4
- package/stl-docs/components/mintlify-compat/card.css +4 -4
- package/stl-docs/components/mintlify-compat/index.ts +2 -4
- package/stl-docs/components/nav-tabs/NavDropdown.astro +38 -77
- package/stl-docs/components/nav-tabs/NavTabs.astro +81 -81
- package/stl-docs/components/nav-tabs/SecondaryNavTabs.astro +1 -2
- package/stl-docs/components/nav-tabs/buildNavLinks.ts +5 -2
- package/stl-docs/components/pagination/HomeLink.astro +10 -0
- package/stl-docs/components/pagination/Pagination.astro +177 -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/sidebars/BaseSidebar.astro +80 -2
- package/stl-docs/components/sidebars/SidebarWithComponents.tsx +10 -0
- package/stl-docs/components/sidebars/convertAstroSidebarToStl.tsx +62 -0
- package/stl-docs/disableCalloutSyntax.ts +36 -0
- package/stl-docs/fonts.ts +186 -0
- package/stl-docs/index.ts +176 -58
- package/stl-docs/loadStlDocsConfig.ts +73 -8
- package/stl-docs/proseDocSync.test.ts +74 -0
- package/stl-docs/proseDocSync.ts +344 -0
- package/stl-docs/proseMarkdown/proseMarkdownIntegration.ts +53 -0
- package/stl-docs/proseMarkdown/proseMarkdownMiddleware.ts +41 -0
- package/stl-docs/proseMarkdown/toMarkdown.ts +158 -0
- package/stl-docs/proseSearchIndexing.ts +218 -0
- package/stl-docs/tabsMiddleware.ts +14 -5
- package/styles/code.css +53 -49
- package/styles/links.css +2 -37
- package/styles/method-descriptions.css +36 -0
- package/styles/overrides.css +28 -46
- package/styles/page.css +228 -38
- package/styles/sdk_select.css +9 -6
- package/styles/search.css +11 -21
- package/styles/sidebar.css +28 -215
- package/styles/{variables.css → sl-variables.css} +4 -8
- package/styles/stldocs-variables.css +6 -0
- package/styles/toc.css +19 -8
- package/theme.css +11 -9
- package/tsconfig.json +1 -4
- package/virtual-module.d.ts +66 -8
- package/components/variables.css +0 -112
- package/plugin/cms/client.ts +0 -62
- package/plugin/cms/server.ts +0 -268
- package/plugin/globalJs/ai-dropdown.ts +0 -57
- package/stl-docs/components/APIReferenceAIDropdown.tsx +0 -58
- package/stl-docs/components/ClientRouterHead.astro +0 -41
- package/stl-docs/components/content-panel/ContentPanel.astro +0 -69
- package/stl-docs/components/content-panel/ProseAIDropdown.tsx +0 -55
- package/stl-docs/components/headers/SplashMobileMenuToggle.astro +0 -49
- package/stl-docs/components/mintlify-compat/Step.astro +0 -56
- package/stl-docs/components/mintlify-compat/Steps.astro +0 -15
- package/styles/fonts.css +0 -68
- /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
|
@@ -13,23 +13,24 @@ document.addEventListener(getPageLoadEvent(), () => {
|
|
|
13
13
|
const panelId = (tab as HTMLButtonElement).dataset.snippetResponseTabId;
|
|
14
14
|
|
|
15
15
|
if (!panelId) {
|
|
16
|
-
console.error(`No panel found for tab: ${tab}`);
|
|
16
|
+
console.error(`No panel found for tab: ${tab.outerHTML}`);
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
document
|
|
20
20
|
.querySelectorAll(`[data-snippet-response-pane-id="${panelId}"]`)
|
|
21
21
|
.forEach((p) => p.classList.add('stldocs-snippet-response-pane-active'));
|
|
22
|
-
document
|
|
23
|
-
.
|
|
24
|
-
.
|
|
22
|
+
document.querySelectorAll(`[data-snippet-response-tab-id="${panelId}"]`).forEach((p) => {
|
|
23
|
+
p.classList.add('stldocs-snippet-response-tab-item-active');
|
|
24
|
+
p.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
|
|
25
|
+
});
|
|
25
26
|
});
|
|
26
27
|
});
|
|
27
28
|
|
|
28
29
|
document.getElementById('stl-snippet-expand-button')?.addEventListener('click', (e) => {
|
|
29
30
|
const btn = e.currentTarget as HTMLButtonElement;
|
|
30
31
|
|
|
31
|
-
const collapsedDiv = document.querySelector('.stl-snippet-code-is-collapsed')
|
|
32
|
-
const expandedDiv = document.querySelector('.stl-snippet-code-is-expanded')
|
|
32
|
+
const collapsedDiv = document.querySelector('.stl-snippet-code-is-collapsed');
|
|
33
|
+
const expandedDiv = document.querySelector('.stl-snippet-code-is-expanded');
|
|
33
34
|
|
|
34
35
|
// We need to use javascript for height animations due to having dynamic heights based on snippet size.
|
|
35
36
|
const animateHeight = (el: HTMLElement, expand: boolean) => {
|
|
@@ -43,27 +44,34 @@ document.addEventListener(getPageLoadEvent(), () => {
|
|
|
43
44
|
// This is a bit funky, but it animates pretty smooth.
|
|
44
45
|
// 1. Toggle to new state so we can measure the target height
|
|
45
46
|
// 2. Reset to starting height to trigger transition
|
|
46
|
-
|
|
47
|
+
el.style.height = '';
|
|
48
|
+
el.style.overflowY = '';
|
|
49
|
+
const startHeight = el.getBoundingClientRect().height;
|
|
47
50
|
el.classList.toggle('stl-snippet-code-is-expanded', expand);
|
|
48
51
|
el.classList.toggle('stl-snippet-code-is-collapsed', !expand);
|
|
49
52
|
|
|
50
|
-
const endHeight = el.
|
|
51
|
-
|
|
52
|
-
el.style.height = `${startHeight}px`;
|
|
53
|
-
|
|
54
|
-
requestAnimationFrame(() => {
|
|
55
|
-
el.style.height = `${endHeight}px`;
|
|
56
|
-
});
|
|
53
|
+
const endHeight = el.getBoundingClientRect().height;
|
|
57
54
|
|
|
58
55
|
const onEnd = (e: TransitionEvent) => {
|
|
59
56
|
if (e.propertyName !== 'height') return;
|
|
60
57
|
el.style.height = '';
|
|
58
|
+
el.style.overflowY = '';
|
|
61
59
|
el.removeEventListener('transitionend', onEnd);
|
|
62
60
|
};
|
|
63
61
|
el.addEventListener('transitionend', onEnd);
|
|
62
|
+
|
|
63
|
+
// Set initial height
|
|
64
|
+
el.style.height = `${startHeight}px`;
|
|
65
|
+
el.style.overflowY = 'hidden';
|
|
66
|
+
|
|
67
|
+
// Force layout recalculation
|
|
68
|
+
el.getBoundingClientRect();
|
|
69
|
+
|
|
70
|
+
// Start transition to end state
|
|
71
|
+
el.style.height = `${endHeight}px`;
|
|
64
72
|
};
|
|
65
73
|
|
|
66
|
-
if (collapsedDiv) {
|
|
74
|
+
if (collapsedDiv instanceof HTMLElement) {
|
|
67
75
|
if (collapsedDiv) {
|
|
68
76
|
collapsedDiv.querySelector('.shiki')?.setAttribute('style', `counter-reset: codeblock-line 0`);
|
|
69
77
|
}
|
|
@@ -72,7 +80,7 @@ document.addEventListener(getPageLoadEvent(), () => {
|
|
|
72
80
|
return;
|
|
73
81
|
}
|
|
74
82
|
|
|
75
|
-
if (expandedDiv) {
|
|
83
|
+
if (expandedDiv instanceof HTMLElement) {
|
|
76
84
|
const dataSnippetExpandedOffset = expandedDiv?.dataset.snippetExpandedOffset;
|
|
77
85
|
if (dataSnippetExpandedOffset) {
|
|
78
86
|
const offset = parseInt(dataSnippetExpandedOffset, 10);
|
|
@@ -84,4 +92,25 @@ document.addEventListener(getPageLoadEvent(), () => {
|
|
|
84
92
|
btn.textContent = 'Show more';
|
|
85
93
|
}
|
|
86
94
|
});
|
|
95
|
+
|
|
96
|
+
document.querySelectorAll('[data-stldocs-multi-snippet-container]').forEach((container) => {
|
|
97
|
+
const radios = container.querySelectorAll<HTMLInputElement>('input[type="radio"]');
|
|
98
|
+
const panes = container.querySelectorAll<HTMLDivElement>('[data-stldocs-multi-snippet-id]');
|
|
99
|
+
|
|
100
|
+
radios.forEach((radio) => {
|
|
101
|
+
radio.addEventListener('change', (e) => {
|
|
102
|
+
if (!(e.target instanceof HTMLInputElement)) return;
|
|
103
|
+
if (e.target.checked) {
|
|
104
|
+
const selectedIndex = e.target.value;
|
|
105
|
+
panes.forEach((pane) => {
|
|
106
|
+
pane.classList.toggle(
|
|
107
|
+
'stldocs-snippet-multi-pane-active',
|
|
108
|
+
pane.dataset.stldocsMultiSnippetId === selectedIndex,
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
e.target.parentElement?.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
});
|
|
87
116
|
});
|
package/plugin/globalJs/copy.ts
CHANGED
|
@@ -1,37 +1,125 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
RESOLVED_API_REFERENCE_PATH,
|
|
3
|
+
EXPERIMENTAL_COLLAPSIBLE_SNIPPETS,
|
|
4
|
+
} from 'virtual:stl-starlight-virtual-module';
|
|
5
|
+
import { getPageLoadEvent } from '../helpers/getPageLoadEvent';
|
|
6
|
+
import { updateSelectedLanguage } from '../languages';
|
|
7
|
+
import { navigate } from 'astro/virtual-modules/transitions-router.js';
|
|
2
8
|
const copyIcon = `<rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>`;
|
|
3
9
|
const circleAlertIcon = `<circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/>`;
|
|
4
10
|
const checkIcon = `<path d="M20 6 9 17l-5-5"/>`;
|
|
5
11
|
|
|
6
|
-
|
|
7
|
-
const
|
|
12
|
+
function getContent(button: HTMLElement, full: boolean) {
|
|
13
|
+
const isContentCollapsed = !!document.querySelector('.stldocs-snippet-code.stl-snippet-code-is-collapsed');
|
|
14
|
+
|
|
15
|
+
const content = button.closest('[data-stldocs-copy-parent]')!.querySelector('[data-stldocs-copy-content]')!;
|
|
16
|
+
|
|
17
|
+
const contentCopy = content.cloneNode(true) as HTMLElement;
|
|
18
|
+
|
|
19
|
+
contentCopy.querySelectorAll('.ellipsis').forEach((el) => el.remove());
|
|
20
|
+
if (EXPERIMENTAL_COLLAPSIBLE_SNIPPETS && isContentCollapsed && !full) {
|
|
21
|
+
contentCopy.querySelectorAll('.hidden').forEach((el) => el.remove());
|
|
22
|
+
contentCopy.querySelectorAll('.leading-ws').forEach((el) => el.remove());
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return contentCopy.textContent;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const preloadPlayground = (event: Event) => {
|
|
29
|
+
const playButton = (event.target as HTMLElement).closest('[data-stldocs-snippet-play]') as HTMLElement;
|
|
30
|
+
if (playButton) {
|
|
31
|
+
loadPlayground(playButton);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
addEventListener('mouseover', preloadPlayground);
|
|
35
|
+
addEventListener('click', (event) => {
|
|
36
|
+
if (!(event.target instanceof Element)) return;
|
|
37
|
+
const copyButton = event.target.closest('[data-stldocs-snippet-copy]');
|
|
38
|
+
if (!(copyButton instanceof HTMLElement)) return;
|
|
39
|
+
|
|
8
40
|
if (copyButton) {
|
|
9
41
|
const iconElement = copyButton.querySelector('.stldocs-icon') as SVGElement;
|
|
10
42
|
clearTimeout(copyButton.dataset.__stldocsCopyTimeout);
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
43
|
+
navigator.clipboard
|
|
44
|
+
.writeText(getContent(copyButton, false))
|
|
45
|
+
.then(() => {
|
|
46
|
+
iconElement.innerHTML = checkIcon;
|
|
47
|
+
})
|
|
48
|
+
.catch(() => {
|
|
49
|
+
iconElement.innerHTML = circleAlertIcon;
|
|
50
|
+
})
|
|
51
|
+
.finally(() => {
|
|
52
|
+
copyButton.dataset.__stldocsCopyTimeout = setTimeout(() => {
|
|
53
|
+
iconElement.innerHTML = copyIcon;
|
|
54
|
+
}).toString();
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const playButton = event.target.closest('[data-stldocs-snippet-play]');
|
|
59
|
+
if (playButton instanceof HTMLElement) {
|
|
60
|
+
showPlayground(playButton).catch(() => {
|
|
61
|
+
console.error('Failed to load playground');
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
async function showPlayground(playButton: HTMLElement) {
|
|
67
|
+
if (playButton.getAttribute('aria-disabled') === 'true') return;
|
|
68
|
+
const iconElement = playButton.querySelector('.stldocs-icon') as SVGElement;
|
|
69
|
+
try {
|
|
70
|
+
// use aria-disabled, not disabled, to avoid losing focus
|
|
71
|
+
playButton.setAttribute('aria-disabled', 'true');
|
|
72
|
+
playButton.setAttribute('aria-label', 'Loading playground...');
|
|
73
|
+
playButton.classList.add('stl-ui-button--loading');
|
|
74
|
+
const showPlayground = loadPlayground(playButton);
|
|
75
|
+
await showPlayground();
|
|
76
|
+
} catch (e) {
|
|
77
|
+
console.error(e);
|
|
78
|
+
iconElement.innerHTML = circleAlertIcon;
|
|
79
|
+
}
|
|
80
|
+
playButton.removeAttribute('aria-disabled');
|
|
81
|
+
playButton.removeAttribute('aria-label');
|
|
82
|
+
playButton.classList.remove('stl-ui-button--loading');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function loadPlayground(playButton: HTMLElement) {
|
|
86
|
+
(playButton as any).__playgroundLoadPromise ??= (async () => {
|
|
87
|
+
const container = playButton.closest('.stldocs-snippet') as HTMLElement;
|
|
88
|
+
const language = (container.querySelector('.stl-sdk-select') as HTMLElement).dataset.currentValue;
|
|
89
|
+
const code = getContent(playButton, true);
|
|
90
|
+
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
91
|
+
if (import.meta.env.DEV) {
|
|
92
|
+
const id = '/@id/astro:scripts/before-hydration.js';
|
|
93
|
+
await import(/* @vite-ignore */ id).catch(console.warn);
|
|
31
94
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
95
|
+
const { createPlayground } = await import('virtual:stl-playground/create');
|
|
96
|
+
const { default: playgroundData } = await import('virtual:stl-playground/data');
|
|
97
|
+
return createPlayground({
|
|
98
|
+
lang: language as any,
|
|
99
|
+
doc: (language === 'python' ? 'from rich import print\n' : '') + code.trimEnd(),
|
|
100
|
+
container,
|
|
101
|
+
onLanguageSelect: (value) => {
|
|
102
|
+
const originalLanguage = container.querySelector<HTMLElement>('[data-stldocs-snippet-select]')
|
|
103
|
+
?.dataset.currentValue;
|
|
104
|
+
const path: string = updateSelectedLanguage(RESOLVED_API_REFERENCE_PATH, originalLanguage, value);
|
|
105
|
+
navigate(path.replace(/(\?.+)?($|#)/, (_, str, end) => (str ? str + '&play' : '?play') + end));
|
|
106
|
+
},
|
|
107
|
+
...playgroundData,
|
|
108
|
+
});
|
|
109
|
+
})();
|
|
110
|
+
return async () => {
|
|
111
|
+
const promise = (playButton as any).__playgroundLoadPromise;
|
|
112
|
+
(playButton as any).__playgroundLoadPromise = null;
|
|
113
|
+
await ((await promise) as () => Promise<void>)();
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
document.addEventListener(getPageLoadEvent(), () => {
|
|
117
|
+
if (new URL(location.href).searchParams.has('play')) {
|
|
118
|
+
document.querySelectorAll('[data-stldocs-snippet-play]').forEach((e) => {
|
|
119
|
+
if (e instanceof HTMLElement)
|
|
120
|
+
showPlayground(e).catch(() => {
|
|
121
|
+
console.error('Failed to load playground');
|
|
122
|
+
});
|
|
123
|
+
});
|
|
36
124
|
}
|
|
37
125
|
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
2
|
+
const COLLAPSED_HEIGHT = 170;
|
|
3
|
+
|
|
4
|
+
const container = document.querySelector<HTMLElement>('[data-stldocs-property-group="method-description"]');
|
|
5
|
+
|
|
6
|
+
if (!container) return;
|
|
7
|
+
|
|
8
|
+
const toggle = document?.querySelector<HTMLButtonElement>('[data-method-description-toggle]');
|
|
9
|
+
if (!toggle) return;
|
|
10
|
+
|
|
11
|
+
// If content isn't tall enough, don't show the button
|
|
12
|
+
if (container.scrollHeight <= COLLAPSED_HEIGHT + 1) {
|
|
13
|
+
toggle.hidden = true;
|
|
14
|
+
container.dataset.collapsed = 'false';
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Only show button if content is taller than collapsed max height
|
|
19
|
+
if (container.scrollHeight > COLLAPSED_HEIGHT + 1) {
|
|
20
|
+
toggle.hidden = false;
|
|
21
|
+
} else {
|
|
22
|
+
// Not tall enough to need collapsing — show full content and hide button
|
|
23
|
+
container.dataset.collapsed = 'false';
|
|
24
|
+
toggle.hidden = true;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
toggle.addEventListener('click', function () {
|
|
29
|
+
const isCollapsed = container.dataset.collapsed !== 'false';
|
|
30
|
+
container.dataset.collapsed = isCollapsed ? 'false' : 'true';
|
|
31
|
+
toggle.textContent = isCollapsed ? 'Show less' : 'Show more';
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
import { parseRoute, scrollToPath } from '@stainless-api/docs-ui/
|
|
2
|
-
import {
|
|
1
|
+
import { parseRoute, scrollToPath } from '@stainless-api/docs-ui/routing';
|
|
2
|
+
import { RESOLVED_API_REFERENCE_PATH } from 'virtual:stl-starlight-virtual-module';
|
|
3
3
|
import { updateSelectedLanguage } from '../languages';
|
|
4
4
|
import { navigate } from 'astro:transitions/client';
|
|
5
5
|
import { getPageLoadEvent } from '../helpers/getPageLoadEvent.ts';
|
|
6
6
|
|
|
7
|
-
import { initDropdown } from '@stainless-api/docs
|
|
8
|
-
import { initDropdownButton } from '@stainless-api/ui-primitives/scripts';
|
|
9
|
-
import { copyCurrentPageAsMarkdown, onSelectAIOption } from './ai-dropdown.ts';
|
|
7
|
+
import { initDropdown } from '@stainless-api/docs/components/scripts';
|
|
10
8
|
|
|
11
9
|
history.scrollRestoration = 'auto';
|
|
12
10
|
|
|
13
11
|
function getStainlessPathForLocation() {
|
|
14
12
|
return document.location.hash
|
|
15
13
|
? decodeURI(document.location.hash)
|
|
16
|
-
: parseRoute(
|
|
14
|
+
: parseRoute(RESOLVED_API_REFERENCE_PATH, document.location.href)?.stainlessPath;
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
window.addEventListener('popstate', (ev: PopStateEvent) => {
|
|
@@ -24,57 +22,39 @@ window.addEventListener('popstate', (ev: PopStateEvent) => {
|
|
|
24
22
|
});
|
|
25
23
|
|
|
26
24
|
document.addEventListener(getPageLoadEvent(), () => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
document.querySelectorAll<HTMLElement>('[data-stldocs-snippet-select]').forEach((rootElement) => {
|
|
26
|
+
initDropdown({
|
|
27
|
+
root: rootElement,
|
|
28
|
+
onSelect: (value) => {
|
|
29
|
+
const originalLanguage = rootElement.dataset.currentValue;
|
|
30
|
+
navigate(updateSelectedLanguage(RESOLVED_API_REFERENCE_PATH, originalLanguage, value)).catch((e) => {
|
|
31
|
+
console.error('Failed to navigate to selected language', e);
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
});
|
|
33
35
|
});
|
|
34
36
|
|
|
35
37
|
const path = getStainlessPathForLocation();
|
|
36
38
|
if (path) setTimeout(() => scrollToPath(path.slice(1)), 10);
|
|
37
39
|
});
|
|
38
40
|
|
|
39
|
-
document.addEventListener(getPageLoadEvent(), () => {
|
|
40
|
-
initDropdownButton({
|
|
41
|
-
dropdownId: 'ai-dropdown-button',
|
|
42
|
-
onSelect: onSelectAIOption,
|
|
43
|
-
onPrimaryAction: (el) => {
|
|
44
|
-
copyCurrentPageAsMarkdown();
|
|
45
|
-
const innerText = el.querySelector('[data-part="primary-action-text"]');
|
|
46
|
-
if (!innerText) return;
|
|
47
|
-
|
|
48
|
-
const originalInnerHtml = innerText.innerHTML;
|
|
49
|
-
innerText.innerHTML = 'Copied!';
|
|
50
|
-
el.classList.add('disabled');
|
|
51
|
-
setTimeout(() => {
|
|
52
|
-
innerText.innerHTML = originalInnerHtml;
|
|
53
|
-
el.classList.remove('disabled');
|
|
54
|
-
}, 1000);
|
|
55
|
-
},
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
|
|
59
41
|
document.addEventListener('click', (event) => {
|
|
60
|
-
const toggle =
|
|
61
|
-
'[data-stldocs-property-toggle-expanded]
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
if (!toggle) return;
|
|
42
|
+
const toggle =
|
|
43
|
+
event.target instanceof HTMLElement && event.target.closest('[data-stldocs-property-toggle-expanded]');
|
|
44
|
+
if (!toggle || !(toggle instanceof HTMLElement)) return;
|
|
65
45
|
|
|
66
|
-
|
|
67
|
-
toggle.dataset.stldocsPropertyToggleExpanded
|
|
46
|
+
// Toggle the “expanded” state of the toggle
|
|
47
|
+
const toggleIsExpanded = toggle.dataset.stldocsPropertyToggleExpanded === 'true';
|
|
48
|
+
toggle.dataset.stldocsPropertyToggleExpanded = (!toggleIsExpanded).toString();
|
|
68
49
|
|
|
50
|
+
// Find the described “property group”
|
|
69
51
|
const targetGroup = toggle.dataset.stldocsPropertyToggleTarget;
|
|
70
52
|
if (!targetGroup) return;
|
|
71
|
-
|
|
72
53
|
const target = document.querySelector(`[data-stldocs-property-group=${targetGroup}]`);
|
|
73
54
|
if (!target) return;
|
|
74
55
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
el.open = initial === 'true' ? true : !state;
|
|
56
|
+
// Expand or collapse all <details> elements within the target group
|
|
57
|
+
[...target.getElementsByTagName('details')].forEach((el) => {
|
|
58
|
+
el.open = el.dataset.stldocsExpanderInitialState === 'true' ? true : !toggleIsExpanded;
|
|
79
59
|
});
|
|
80
60
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import wheelUrl from 'virtual:stl-playground/python/wheel.whl?url';
|
|
2
|
+
import pyTypes from 'virtual:stl-playground/python.json';
|
|
3
|
+
import tsTypes from 'virtual:stl-playground/typescript.json';
|
|
4
|
+
import authData from 'virtual:stl-playground/auth.json';
|
|
5
|
+
import { HIGHLIGHT_THEMES } from 'virtual:stl-starlight-virtual-module';
|
|
6
|
+
import { Config } from 'virtual:stl-playground/create';
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
wheelUrl,
|
|
10
|
+
pyTypes,
|
|
11
|
+
tsTypes,
|
|
12
|
+
authData,
|
|
13
|
+
HIGHLIGHT_THEMES,
|
|
14
|
+
} satisfies Config;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Let users select text in <summary> elements without toggling them
|
|
2
|
+
|
|
3
|
+
document.addEventListener(
|
|
4
|
+
'mousedown',
|
|
5
|
+
(e) => {
|
|
6
|
+
const summary = (e.target as HTMLElement).closest('summary.stldocs-expander-summary');
|
|
7
|
+
if (!summary) return;
|
|
8
|
+
const selectionOnDown = window.getSelection()?.toString() ?? '';
|
|
9
|
+
|
|
10
|
+
document.addEventListener(
|
|
11
|
+
'mouseup',
|
|
12
|
+
() => {
|
|
13
|
+
const selectionOnUp = window.getSelection()?.toString() ?? '';
|
|
14
|
+
|
|
15
|
+
if (selectionOnUp && selectionOnUp !== selectionOnDown) {
|
|
16
|
+
summary.addEventListener(
|
|
17
|
+
'click',
|
|
18
|
+
(e) => {
|
|
19
|
+
e.preventDefault();
|
|
20
|
+
},
|
|
21
|
+
{ once: true },
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
{ once: true },
|
|
26
|
+
);
|
|
27
|
+
},
|
|
28
|
+
{ capture: true },
|
|
29
|
+
);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
2
|
+
import { DocsLanguage, generateRouteList } from '@stainless-api/docs-ui/routing';
|
|
3
|
+
import { EXCLUDE_LANGUAGES } from 'virtual:stl-starlight-virtual-module';
|
|
4
|
+
import { api } from 'virtual:stainless-apis-manifest';
|
|
5
|
+
import { getSDKJSONInSSR } from '../specs/fetchSpecSSR';
|
|
6
|
+
|
|
7
|
+
export function generateDocsRoutes(spec: SDKJSON.Spec, excludeLanguages: DocsLanguage[] = EXCLUDE_LANGUAGES) {
|
|
8
|
+
const paths = generateRouteList({
|
|
9
|
+
spec,
|
|
10
|
+
excludeLanguages,
|
|
11
|
+
});
|
|
12
|
+
const readmes = Object.entries(spec.readme)
|
|
13
|
+
.filter(([language]) => language !== 'http')
|
|
14
|
+
.filter(([language]) => !excludeLanguages.includes(language as DocsLanguage))
|
|
15
|
+
.map(([language]) => ({
|
|
16
|
+
slug: language,
|
|
17
|
+
stainlessPath: null,
|
|
18
|
+
language: language as DocsLanguage,
|
|
19
|
+
title: 'Readme',
|
|
20
|
+
kind: 'readme' as const,
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
return [...paths, ...readmes].map(({ slug, stainlessPath, language, title, kind }) => {
|
|
24
|
+
return {
|
|
25
|
+
params: { slug },
|
|
26
|
+
props: { stainlessPath, language, title, kind },
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function generateAllDocsRoutes() {
|
|
32
|
+
const uniquePaths = new Set<string>();
|
|
33
|
+
|
|
34
|
+
const allRoutes = (
|
|
35
|
+
await Promise.all(
|
|
36
|
+
api.languages.map(async (entry) => {
|
|
37
|
+
const spec = await getSDKJSONInSSR(entry.language);
|
|
38
|
+
|
|
39
|
+
// this is super annoying, but preview worker _always_ generates HTTP routes
|
|
40
|
+
// so, we exclude them unless the we're explicitly told to include them
|
|
41
|
+
const excludeLanguages = [...EXCLUDE_LANGUAGES];
|
|
42
|
+
if (entry.language !== 'http') {
|
|
43
|
+
excludeLanguages.push('http');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const routes = generateDocsRoutes(spec, excludeLanguages);
|
|
47
|
+
return routes.filter((route) => {
|
|
48
|
+
if (uniquePaths.has(route.params.slug)) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
uniquePaths.add(route.params.slug);
|
|
52
|
+
return true;
|
|
53
|
+
});
|
|
54
|
+
}),
|
|
55
|
+
)
|
|
56
|
+
).flat();
|
|
57
|
+
|
|
58
|
+
return allRoutes;
|
|
59
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { api } from 'virtual:stainless-apis-manifest';
|
|
2
|
+
import { EXCLUDE_LANGUAGES } from 'virtual:stl-starlight-virtual-module';
|
|
3
|
+
|
|
4
|
+
export function getDocsLanguages() {
|
|
5
|
+
return api.languages
|
|
6
|
+
.map((language) => language.language)
|
|
7
|
+
.filter((language) => !EXCLUDE_LANGUAGES.includes(language));
|
|
8
|
+
}
|