@writedocs/generator 0.1.0
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/LICENSE +15 -0
- package/README.md +17 -0
- package/astro.config.mjs +419 -0
- package/bin/writedocs.js +73 -0
- package/package.json +79 -0
- package/src/assets/wd_watermark.png +0 -0
- package/src/assets/wd_watermark_dark.png +0 -0
- package/src/cli/build-auth.js +53 -0
- package/src/cli/build.js +40 -0
- package/src/cli/dev.js +12 -0
- package/src/cli/generate-api-pages.js +359 -0
- package/src/cli/init.js +81 -0
- package/src/cli/preflight.js +40 -0
- package/src/cli/run-astro.js +57 -0
- package/src/cli/run-pagefind.js +66 -0
- package/src/cli/write-redirects-file.js +80 -0
- package/src/components/Accordion.astro +164 -0
- package/src/components/AccordionGroup.astro +40 -0
- package/src/components/ApiLangSelect.astro +168 -0
- package/src/components/ApiPlayground.astro +281 -0
- package/src/components/ApiReferencePanel.astro +1754 -0
- package/src/components/ApiSchemaField.astro +54 -0
- package/src/components/AppIcon.astro +32 -0
- package/src/components/Badge.astro +128 -0
- package/src/components/Callout.astro +168 -0
- package/src/components/Card.astro +136 -0
- package/src/components/CardGroup.astro +20 -0
- package/src/components/CodeGroup.astro +184 -0
- package/src/components/CopyPageMenu.astro +246 -0
- package/src/components/Danger.astro +12 -0
- package/src/components/Expandable.astro +126 -0
- package/src/components/Frame.astro +102 -0
- package/src/components/Hint.astro +99 -0
- package/src/components/Icon.astro +70 -0
- package/src/components/Image.astro +147 -0
- package/src/components/Info.astro +12 -0
- package/src/components/Note.astro +12 -0
- package/src/components/Parameter.astro +119 -0
- package/src/components/RequestExample.astro +33 -0
- package/src/components/ResponseExample.astro +19 -0
- package/src/components/Searchbar.astro +117 -0
- package/src/components/Step.astro +10 -0
- package/src/components/Steps.astro +32 -0
- package/src/components/Tab.astro +9 -0
- package/src/components/Tabs.astro +52 -0
- package/src/components/Tip.astro +12 -0
- package/src/components/Video.astro +135 -0
- package/src/components/Warning.astro +12 -0
- package/src/components/index.ts +48 -0
- package/src/content.config.ts +223 -0
- package/src/layout/BaseLayout.astro +750 -0
- package/src/layout/components/AnalyticsScripts.astro +77 -0
- package/src/layout/components/AskAiWidget.astro +37 -0
- package/src/layout/components/Breadcrumbs.astro +97 -0
- package/src/layout/components/ImageZoom.astro +19 -0
- package/src/layout/components/MobileMenu.astro +200 -0
- package/src/layout/components/NavTree.astro +351 -0
- package/src/layout/components/SearchModal.astro +42 -0
- package/src/layout/components/Sidebar.astro +122 -0
- package/src/layout/components/SiteFooter.astro +85 -0
- package/src/layout/components/TableOfContents.astro +117 -0
- package/src/layout/components/TopBar.astro +311 -0
- package/src/layout/styles/banner.css +44 -0
- package/src/layout/styles/base.css +234 -0
- package/src/layout/styles/dropdown.css +133 -0
- package/src/layout/styles/footer.css +108 -0
- package/src/layout/styles/image-zoom.css +50 -0
- package/src/layout/styles/mobile-menu.css +258 -0
- package/src/layout/styles/search-modal.css +122 -0
- package/src/layout/styles/topbar.css +437 -0
- package/src/lib/config.ts +2131 -0
- package/src/lib/mdx-auto-hydrate.js +70 -0
- package/src/lib/mdx-inject-builtins.js +87 -0
- package/src/lib/mdx-substitute-variables.js +66 -0
- package/src/lib/mdx-title-anchor-ids.js +84 -0
- package/src/lib/mermaid-rehype.js +72 -0
- package/src/lib/openapi-render.ts +479 -0
- package/src/lib/shiki-code-block.js +102 -0
- package/src/lib/shiki-copy-button.js +45 -0
- package/src/lib/styles-asset-integration.js +210 -0
- package/src/lib/writedocs-temp-dir.js +93 -0
- package/src/pages/404.astro +62 -0
- package/src/pages/[...slug].astro +1270 -0
- package/src/pages/[...slug].md.ts +78 -0
- package/src/pages/llms-full.txt.ts +71 -0
- package/src/pages/llms.txt.ts +141 -0
- package/src/scripts/banner.ts +20 -0
- package/src/scripts/dropdowns.ts +61 -0
- package/src/scripts/image-zoom.ts +66 -0
- package/src/scripts/mobile-menu.ts +55 -0
- package/src/scripts/search.ts +155 -0
- package/src/scripts/sidebar-scroll.ts +65 -0
- package/src/scripts/theme-toggle.ts +35 -0
- package/src/scripts/topbar-offset.ts +141 -0
- package/src/styles/global.css +18 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Inline, text-level component - unlike every other built-in here
|
|
3
|
+
// (Callout, Card, Accordion, ...), which are all block-level and get
|
|
4
|
+
// their own line, a Hint sits mid-sentence: `word <Hint tip="...">this
|
|
5
|
+
// bit</Hint> continues`. That's why this renders a <span>, not a <div>,
|
|
6
|
+
// and why its own trigger area is exactly its slotted text - no icon,
|
|
7
|
+
// no padding box drawing attention to itself the way a Callout does.
|
|
8
|
+
//
|
|
9
|
+
// tip is a plain string prop (not a slot) deliberately - the tooltip
|
|
10
|
+
// bubble itself needs to be one line of plain text CSS can center/
|
|
11
|
+
// position predictably; a second <slot> would let an author put
|
|
12
|
+
// arbitrary markup (another Hint, a link, a whole paragraph) in there,
|
|
13
|
+
// which the hover-bubble layout below was never built to hold.
|
|
14
|
+
interface Props {
|
|
15
|
+
tip: string;
|
|
16
|
+
}
|
|
17
|
+
const { tip } = Astro.props as Props;
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
<span class="wd-hint" tabindex="0">
|
|
21
|
+
<span class="wd-hint-trigger"><slot /></span>
|
|
22
|
+
<span class="wd-hint-tooltip" role="tooltip">{tip}</span>
|
|
23
|
+
</span>
|
|
24
|
+
<style>
|
|
25
|
+
.wd-hint {
|
|
26
|
+
position: relative;
|
|
27
|
+
/* display: inline, not inline-block - this needs to be able to wrap
|
|
28
|
+
across a line break exactly like the plain text around it would
|
|
29
|
+
(it's often a whole sentence, not one short word), which
|
|
30
|
+
inline-block would prevent by forcing the whole span to stay on
|
|
31
|
+
one line or break as a single rigid box. */
|
|
32
|
+
display: inline;
|
|
33
|
+
/* tabindex above + :focus-visible below make this reachable and
|
|
34
|
+
revealable by keyboard, not just a mouse hover - the underline
|
|
35
|
+
and cursor: help both double as the visual cue that there's a
|
|
36
|
+
hint here at all, since nothing about plain underlined text
|
|
37
|
+
otherwise signals "hover me" the way an icon or button would. */
|
|
38
|
+
cursor: help;
|
|
39
|
+
border-bottom: 1px solid var(--wd-text);
|
|
40
|
+
}
|
|
41
|
+
.wd-hint-tooltip {
|
|
42
|
+
position: absolute;
|
|
43
|
+
bottom: calc(100% + 0.55rem);
|
|
44
|
+
left: 50%;
|
|
45
|
+
transform: translateX(-50%) translateY(4px);
|
|
46
|
+
/* Fixed dark-on-light regardless of [data-theme] - deliberately not
|
|
47
|
+
var(--wd-text)/var(--wd-background) (which flip a Hint's own
|
|
48
|
+
tooltip to light-on-dark in dark mode) since the bubble needs to
|
|
49
|
+
read as "a label floating above the page", the same fixed
|
|
50
|
+
look in both themes, not as page content that itself follows the
|
|
51
|
+
theme - the same reasoning Card.astro's method badges already
|
|
52
|
+
settled on for their own always-colored, never-theme-flipping
|
|
53
|
+
backgrounds. */
|
|
54
|
+
background: #18181b;
|
|
55
|
+
color: #fff;
|
|
56
|
+
padding: 0.45rem 0.75rem;
|
|
57
|
+
border-radius: 0.4rem;
|
|
58
|
+
font-size: 0.75rem;
|
|
59
|
+
font-weight: 700;
|
|
60
|
+
line-height: 1.3;
|
|
61
|
+
/* No white-space: nowrap - a long tip (a UUID example, a full
|
|
62
|
+
sentence) needs to actually wrap onto a second line within
|
|
63
|
+
max-width; nowrap combined with max-width caps the *box* but
|
|
64
|
+
leaves overflow: visible's default behavior letting the text
|
|
65
|
+
itself spill out past the painted background/border-radius
|
|
66
|
+
instead of wrapping inside it - exactly the "text sticking out
|
|
67
|
+
past the dark bubble" bug a real screenshot caught. Wrapping
|
|
68
|
+
normally keeps the background sized to whatever it's actually
|
|
69
|
+
covering, at the cost of a short tip's box no longer perfectly
|
|
70
|
+
hugging one line's width (an intentional trade - a tip that's
|
|
71
|
+
readable matters more than one that's minimally-sized). */
|
|
72
|
+
max-width: 16rem;
|
|
73
|
+
width: max-content;
|
|
74
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
|
|
75
|
+
opacity: 0;
|
|
76
|
+
visibility: hidden;
|
|
77
|
+
pointer-events: none;
|
|
78
|
+
transition:
|
|
79
|
+
opacity 0.15s ease,
|
|
80
|
+
transform 0.15s ease,
|
|
81
|
+
visibility 0.15s;
|
|
82
|
+
z-index: 30;
|
|
83
|
+
}
|
|
84
|
+
.wd-hint-tooltip::after {
|
|
85
|
+
content: "";
|
|
86
|
+
position: absolute;
|
|
87
|
+
top: 100%;
|
|
88
|
+
left: 50%;
|
|
89
|
+
transform: translateX(-50%);
|
|
90
|
+
border: 5px solid transparent;
|
|
91
|
+
border-top-color: #18181b;
|
|
92
|
+
}
|
|
93
|
+
.wd-hint:hover .wd-hint-tooltip,
|
|
94
|
+
.wd-hint:focus-visible .wd-hint-tooltip {
|
|
95
|
+
opacity: 1;
|
|
96
|
+
visibility: visible;
|
|
97
|
+
transform: translateX(-50%) translateY(0);
|
|
98
|
+
}
|
|
99
|
+
</style>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Renders either a real icon (via `icon`) or a custom image (via
|
|
3
|
+
// `src`) inline with surrounding text - modeled on Mintlify's own Icon
|
|
4
|
+
// (https://www.mintlify.com/docs/components/icons), which documents
|
|
5
|
+
// exactly this "one of `icon` or `src`" split. `icon` reuses
|
|
6
|
+
// AppIcon.astro - the same Lucide/Iconify/literal-text resolution
|
|
7
|
+
// every other icon prop on this site already goes through (Card,
|
|
8
|
+
// Badge, writedocs.json's own tab/dropdown/product icons) - so this
|
|
9
|
+
// component's `icon` prop behaves identically to theirs, just laid out
|
|
10
|
+
// for inline text flow instead of block/flex placement.
|
|
11
|
+
//
|
|
12
|
+
// The `src` branch is a second, independent code path (a plain <img>,
|
|
13
|
+
// not AppIcon) since it isn't resolving an icon set at all - it's
|
|
14
|
+
// dropping in an arbitrary image (a project-local file or an external
|
|
15
|
+
// URL) and just needs to sit inline at a controlled height, the exact
|
|
16
|
+
// behavior of the InlineImage React component this was modeled on
|
|
17
|
+
// (display: inline, a `height` prop controlling size, no margin).
|
|
18
|
+
import AppIcon from './AppIcon.astro';
|
|
19
|
+
|
|
20
|
+
interface Props {
|
|
21
|
+
icon?: string;
|
|
22
|
+
src?: string;
|
|
23
|
+
alt?: string;
|
|
24
|
+
// Only meaningful for the `icon` branch - a pixel size (Mintlify's
|
|
25
|
+
// own `size` prop is a number, not a CSS length) and a CSS color,
|
|
26
|
+
// applied as an inline style since these are arbitrary per-instance
|
|
27
|
+
// values, not a fixed set of classes.
|
|
28
|
+
size?: number;
|
|
29
|
+
color?: string;
|
|
30
|
+
// Only meaningful for the `src` branch - a CSS length string (not a
|
|
31
|
+
// bare number, unlike `size` above), matching the InlineImage
|
|
32
|
+
// reference component's own `height` prop and its "1.6em" default.
|
|
33
|
+
height?: string;
|
|
34
|
+
}
|
|
35
|
+
const { icon, src, alt = '', size, color, height = '1.6em' } = Astro.props as Props;
|
|
36
|
+
|
|
37
|
+
const iconStyle =
|
|
38
|
+
[size ? `width:${size}px` : null, size ? `height:${size}px` : null, color ? `color:${color}` : null]
|
|
39
|
+
.filter(Boolean)
|
|
40
|
+
.join(';') || undefined;
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
{
|
|
44
|
+
src ? (
|
|
45
|
+
<img src={src} alt={alt} class="wd-icon-image" style={`height:${height}`} />
|
|
46
|
+
) : icon ? (
|
|
47
|
+
<AppIcon icon={icon} class="wd-icon-inline" style={iconStyle} />
|
|
48
|
+
) : null
|
|
49
|
+
}
|
|
50
|
+
<style>
|
|
51
|
+
.wd-icon-image {
|
|
52
|
+
display: inline;
|
|
53
|
+
vertical-align: middle;
|
|
54
|
+
height: 1.6em;
|
|
55
|
+
margin: 0;
|
|
56
|
+
}
|
|
57
|
+
/* :global() is load-bearing, same reason as every other AppIcon
|
|
58
|
+
consumer's identical comment (Card.astro, Badge.astro): AppIcon
|
|
59
|
+
renders this span/svg, not Icon.astro, so it never carries this
|
|
60
|
+
component's own scope attribute. 1em default (overridden inline
|
|
61
|
+
via the `size` prop's style attribute when set) keeps an
|
|
62
|
+
unsized icon proportional to its surrounding text, the same way a
|
|
63
|
+
real glyph would be. */
|
|
64
|
+
:global(.wd-icon-inline) {
|
|
65
|
+
display: inline;
|
|
66
|
+
vertical-align: middle;
|
|
67
|
+
width: 1em;
|
|
68
|
+
height: 1em;
|
|
69
|
+
}
|
|
70
|
+
</style>
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Block-level (own line, centered) - unlike Hint (inline/text-level),
|
|
3
|
+
// this is meant to be dropped in on its own the way Callout/Card are.
|
|
4
|
+
//
|
|
5
|
+
// src/srcDark render as two separate <img> tags, both always in the
|
|
6
|
+
// markup, CSS shows only the one matching the active [data-theme] - the
|
|
7
|
+
// exact same dual light/dark-asset pattern base.css's own .wd-logo-light/
|
|
8
|
+
// .wd-logo-dark rules already establish for TopBar/MobileMenu/SiteFooter's
|
|
9
|
+
// logo (see that comment there) - base.css's own comment on those rules
|
|
10
|
+
// spells out exactly why they get to write [data-theme='dark'] .wd-logo-x
|
|
11
|
+
// completely unscoped: base.css is a *plain imported* .css file, never run
|
|
12
|
+
// through Astro's scoped-CSS compiler at all, unlike this component's own
|
|
13
|
+
// <style> block below. [data-theme] lives on <html>, set by BaseLayout's
|
|
14
|
+
// anti-FOUC script - nowhere near this component's own template - so
|
|
15
|
+
// inside a *scoped* <style> (this one) that ancestor selector has to be
|
|
16
|
+
// wrapped in :global() or Astro's compiler appends this component's own
|
|
17
|
+
// scope attribute onto it too, requiring <html> to carry that attribute,
|
|
18
|
+
// which it never will. .wd-image-light/.wd-image-dark themselves don't
|
|
19
|
+
// need :global() - unlike AppIcon-rendered markup (Card/Accordion's own
|
|
20
|
+
// icon rules), both <img> tags here are rendered directly by *this*
|
|
21
|
+
// component's own template, so they already carry its scope attribute
|
|
22
|
+
// normally.
|
|
23
|
+
interface Props {
|
|
24
|
+
src: string;
|
|
25
|
+
srcDark?: string;
|
|
26
|
+
// Width at full (unconstrained) viewport width - a raw CSS length or
|
|
27
|
+
// percentage string ("80%", "480px", "40rem", ...), passed straight
|
|
28
|
+
// through as a custom property with no parsing/validation, the same
|
|
29
|
+
// "trust the site author, this is their writedocs.json/content" latitude
|
|
30
|
+
// every other pass-through string prop here already gets (Card's
|
|
31
|
+
// icon, Callout's title, ...). Applied to the *figure* (see below),
|
|
32
|
+
// not the <img> tags directly - an earlier version set it on the img
|
|
33
|
+
// instead, which left the figure itself (and, when caption is set,
|
|
34
|
+
// its whole bordered card) always full-width regardless of `size`,
|
|
35
|
+
// so a size="70%" image ended up sitting inside a card twice as wide
|
|
36
|
+
// as it needed to be, with a large empty gap on both sides - caught
|
|
37
|
+
// via a real screenshot showing exactly that gap. max-width: 100%
|
|
38
|
+
// below is what actually makes this shrink on a narrower viewport
|
|
39
|
+
// instead of overflowing it, regardless of which form `size` takes -
|
|
40
|
+
// a percentage already scales with its container on its own, but a
|
|
41
|
+
// fixed px/rem value doesn't, and needs that separate cap to behave
|
|
42
|
+
// the same way.
|
|
43
|
+
size?: string;
|
|
44
|
+
alt?: string;
|
|
45
|
+
// Optional caption shown below the image. Set it and the whole thing
|
|
46
|
+
// gains the same bordered/rounded "card" background Frame's own
|
|
47
|
+
// caption case uses (border + background + padding, image inset
|
|
48
|
+
// inside it) - deliberately conditional on caption being set rather
|
|
49
|
+
// than always-on: without a caption this needs to render exactly as
|
|
50
|
+
// it always has (a plain image, no chrome), so an existing
|
|
51
|
+
// <Image src="..." /> with no caption keeps its current look with
|
|
52
|
+
// zero visual change - only opting a page into the card look actually
|
|
53
|
+
// opts it in.
|
|
54
|
+
caption?: string;
|
|
55
|
+
// Opts this image out of the site-wide click-to-zoom lightbox (see
|
|
56
|
+
// src/scripts/image-zoom.ts) - rendered as a bare `nozoom` attribute
|
|
57
|
+
// on both <img> tags, the same attribute a raw
|
|
58
|
+
// `<img nozoom src="..." />` written directly in MDX would carry, so
|
|
59
|
+
// one selector in image-zoom.ts handles both cases identically rather
|
|
60
|
+
// than needing to special-case this component.
|
|
61
|
+
noZoom?: boolean;
|
|
62
|
+
}
|
|
63
|
+
const { src, srcDark, size, alt = "", caption, noZoom } = Astro.props as Props;
|
|
64
|
+
const sizeStyle = size ? `--wd-image-size:${size}` : undefined;
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
<figure
|
|
68
|
+
class:list={["wd-image-figure", caption && "wd-image-figure-framed", srcDark && "wd-image-has-dark"]}
|
|
69
|
+
style={sizeStyle}
|
|
70
|
+
>
|
|
71
|
+
<img src={src} alt={alt} class="wd-image wd-image-light" nozoom={noZoom || undefined} />
|
|
72
|
+
{srcDark && <img src={srcDark} alt={alt} class="wd-image wd-image-dark" nozoom={noZoom || undefined} />}
|
|
73
|
+
{caption && <figcaption class="wd-image-caption">{caption}</figcaption>}
|
|
74
|
+
</figure>
|
|
75
|
+
<style>
|
|
76
|
+
/* width: var(--wd-image-size, 100%) here (not on the img - see the
|
|
77
|
+
`size` prop's own comment above) is what makes the *whole figure*,
|
|
78
|
+
card background and all, actually match the image's own size
|
|
79
|
+
instead of always spanning the full content column. margin: ...
|
|
80
|
+
auto only has anything to center once this has a definite width
|
|
81
|
+
smaller than its container - at the 100% default it's a no-op,
|
|
82
|
+
same as before this prop existed. */
|
|
83
|
+
.wd-image-figure {
|
|
84
|
+
width: var(--wd-image-size, 100%);
|
|
85
|
+
max-width: 100%;
|
|
86
|
+
margin: 1.25rem auto;
|
|
87
|
+
}
|
|
88
|
+
/* Same card language as Frame's own bordered case (border + rounded +
|
|
89
|
+
surface background + padding) - deliberately duplicated here rather
|
|
90
|
+
than shared, the same way Card/Callout/Accordion each carry their
|
|
91
|
+
own near-identical CSS rather than a shared base class; Astro's
|
|
92
|
+
scoped <style> blocks are per-component anyway, so there's no
|
|
93
|
+
lighter-weight way to share this without introducing a global
|
|
94
|
+
stylesheet dependency neither component otherwise needs. Padding
|
|
95
|
+
is what creates the "image inset within the card" look - the img's
|
|
96
|
+
own width: 100% below resolves against this padded content box,
|
|
97
|
+
not the figure's own outer edge.
|
|
98
|
+
box-shadow is a deliberate belt-and-suspenders addition on top of
|
|
99
|
+
the border - var(--wd-border)/var(--wd-surface) are both very
|
|
100
|
+
light, low-contrast tokens by default (see BaseLayout.astro's own
|
|
101
|
+
--wd-border/--wd-surface light-mode values), so on a page whose own
|
|
102
|
+
background is similarly pale (or, worse, uses the literal same
|
|
103
|
+
image asset as its background - confirmed as the actual root cause
|
|
104
|
+
of a real earlier "the card is invisible" report), the border alone
|
|
105
|
+
can end up nearly imperceptible even though it's genuinely being
|
|
106
|
+
applied. A soft shadow gives the card a second, independent visual
|
|
107
|
+
cue that doesn't depend on border/surface contrast against
|
|
108
|
+
whatever the page happens to look like. */
|
|
109
|
+
.wd-image-figure-framed {
|
|
110
|
+
border: 1px solid var(--wd-border);
|
|
111
|
+
border-radius: 0.75rem;
|
|
112
|
+
background: var(--wd-surface);
|
|
113
|
+
padding: 0.5rem;
|
|
114
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
|
|
115
|
+
}
|
|
116
|
+
.wd-image {
|
|
117
|
+
display: block;
|
|
118
|
+
width: 100%;
|
|
119
|
+
height: auto;
|
|
120
|
+
border-radius: 0.75rem;
|
|
121
|
+
}
|
|
122
|
+
.wd-image-dark {
|
|
123
|
+
display: none;
|
|
124
|
+
}
|
|
125
|
+
/* .wd-image-light only hides in dark mode when a dark variant is
|
|
126
|
+
actually there to replace it - .wd-image-has-dark only gets added
|
|
127
|
+
to the figure when srcDark is set (see the frontmatter above); with
|
|
128
|
+
no srcDark, there's no second <img> in the markup at all, so
|
|
129
|
+
unconditionally hiding the light one (an earlier version of this
|
|
130
|
+
rule had no such scoping) left dark mode with literally nothing to
|
|
131
|
+
show - a real user report caught exactly that: light-only Image
|
|
132
|
+
usages went blank in dark mode instead of just keeping the one
|
|
133
|
+
image they had, same as base.css's own dual-logo comment already
|
|
134
|
+
notes for a site that only configures one logo. */
|
|
135
|
+
:global([data-theme="dark"]) .wd-image-figure.wd-image-has-dark .wd-image-light {
|
|
136
|
+
display: none;
|
|
137
|
+
}
|
|
138
|
+
:global([data-theme="dark"]) .wd-image-dark {
|
|
139
|
+
display: block;
|
|
140
|
+
}
|
|
141
|
+
.wd-image-caption {
|
|
142
|
+
margin-top: 0.6rem;
|
|
143
|
+
text-align: center;
|
|
144
|
+
color: var(--wd-text-muted);
|
|
145
|
+
font-size: 0.75rem;
|
|
146
|
+
}
|
|
147
|
+
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Shorthand for <Callout type="info">. See Callout.astro's own comment.
|
|
3
|
+
import Callout from './Callout.astro';
|
|
4
|
+
interface Props {
|
|
5
|
+
title?: string;
|
|
6
|
+
// See Callout.astro's own comment - set automatically by
|
|
7
|
+
// remarkCalloutAnchorIds, not meant to be passed by hand.
|
|
8
|
+
_titleId?: string;
|
|
9
|
+
}
|
|
10
|
+
const { title, _titleId } = Astro.props as Props;
|
|
11
|
+
---
|
|
12
|
+
<Callout type="info" title={title} _titleId={_titleId}><slot /></Callout>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Shorthand for <Callout type="note">. See Callout.astro's own comment.
|
|
3
|
+
import Callout from './Callout.astro';
|
|
4
|
+
interface Props {
|
|
5
|
+
title?: string;
|
|
6
|
+
// See Callout.astro's own comment - set automatically by
|
|
7
|
+
// remarkCalloutAnchorIds, not meant to be passed by hand.
|
|
8
|
+
_titleId?: string;
|
|
9
|
+
}
|
|
10
|
+
const { title, _titleId } = Astro.props as Props;
|
|
11
|
+
---
|
|
12
|
+
<Callout type="note" title={title} _titleId={_titleId}><slot /></Callout>
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
---
|
|
2
|
+
// The name+type+description row used throughout API reference content -
|
|
3
|
+
// modeled directly on Mintlify's own ParamField/ResponseField
|
|
4
|
+
// (https://www.mintlify.com/docs/components/expandables), which this
|
|
5
|
+
// was explicitly asked to match. Deliberately one component covering
|
|
6
|
+
// both "this is a request parameter" and "this is a response field"
|
|
7
|
+
// use cases (Mintlify itself ships two near-identical components for
|
|
8
|
+
// that split) - nothing here actually depends on which direction the
|
|
9
|
+
// data flows, so there was no real reason to duplicate it.
|
|
10
|
+
//
|
|
11
|
+
// Only `name` is required - `type` is optional (a parameter's shape is
|
|
12
|
+
// sometimes obvious from context, or genuinely untyped), so its badge
|
|
13
|
+
// only renders when passed.
|
|
14
|
+
//
|
|
15
|
+
// Nests naturally: a Parameter's own slot can contain plain description
|
|
16
|
+
// text, an <Expandable> wrapping more Parameters for a nested object's
|
|
17
|
+
// own properties, or both - see Expandable.astro's own comment for that
|
|
18
|
+
// half of the pattern.
|
|
19
|
+
interface Props {
|
|
20
|
+
name: string;
|
|
21
|
+
type?: string;
|
|
22
|
+
required?: boolean;
|
|
23
|
+
default?: string;
|
|
24
|
+
}
|
|
25
|
+
const { name, type, required = false, default: defaultValue } = Astro.props as Props;
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
<div class="wd-parameter">
|
|
29
|
+
<div class="wd-parameter-head">
|
|
30
|
+
<span class="wd-parameter-name">{name}</span>
|
|
31
|
+
{type && <span class="wd-parameter-type">{type}</span>}
|
|
32
|
+
{required && <span class="wd-parameter-required">required</span>}
|
|
33
|
+
{defaultValue && <span class="wd-parameter-default">default: {defaultValue}</span>}
|
|
34
|
+
</div>
|
|
35
|
+
<div class="wd-parameter-body">
|
|
36
|
+
<slot />
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
<style>
|
|
40
|
+
.wd-parameter {
|
|
41
|
+
padding: 0.9rem 0;
|
|
42
|
+
}
|
|
43
|
+
/* Divider between consecutive fields, not around the group as a
|
|
44
|
+
whole - a first-child Parameter (the common case: the very first
|
|
45
|
+
field in a list, or the only field passed to Expandable) shouldn't
|
|
46
|
+
render a line above itself with nothing there to separate it
|
|
47
|
+
from. */
|
|
48
|
+
.wd-parameter + .wd-parameter {
|
|
49
|
+
border-top: 1px solid var(--wd-border);
|
|
50
|
+
}
|
|
51
|
+
.wd-parameter-head {
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
flex-wrap: wrap;
|
|
55
|
+
gap: 0.5rem;
|
|
56
|
+
margin-bottom: 0.4rem;
|
|
57
|
+
}
|
|
58
|
+
.wd-parameter-name {
|
|
59
|
+
font-family: monospace;
|
|
60
|
+
font-weight: 700;
|
|
61
|
+
color: var(--wd-primary);
|
|
62
|
+
}
|
|
63
|
+
/* border/background/border-radius match base.css's own global inline
|
|
64
|
+
<code> pill exactly (var(--wd-surface)/var(--wd-border)/0.35em) -
|
|
65
|
+
reusing those instead of inventing new chip colors is the actual
|
|
66
|
+
"apply the same styles as our api pages" part of the request: a
|
|
67
|
+
type name here should read as the same kind of chip a reader
|
|
68
|
+
already sees for inline `code` anywhere else in this site's
|
|
69
|
+
content. font-family: monospace is added on top (base.css's own
|
|
70
|
+
inline code doesn't force one, it inherits the body font) - every
|
|
71
|
+
other API-page element that reads as "code" (ApiPlayground's param
|
|
72
|
+
inputs, CodeGroup's tab labels, ApiReferencePanel's own field
|
|
73
|
+
labels) already sets it explicitly the same way, and the reference
|
|
74
|
+
screenshot this was built from clearly renders field names/types
|
|
75
|
+
in a monospace face too. */
|
|
76
|
+
.wd-parameter-type {
|
|
77
|
+
font-family: monospace;
|
|
78
|
+
font-size: 0.8rem;
|
|
79
|
+
background: var(--wd-surface);
|
|
80
|
+
border: 1px solid var(--wd-border);
|
|
81
|
+
border-radius: 0.35em;
|
|
82
|
+
padding: 0.1em 0.5em;
|
|
83
|
+
color: var(--wd-text-muted);
|
|
84
|
+
}
|
|
85
|
+
/* Same chip shape as .wd-parameter-type (border/radius/padding/
|
|
86
|
+
font-family), just recolored red - matches the reference
|
|
87
|
+
screenshot, where "required" reads as the same kind of badge as
|
|
88
|
+
the type chip next to it, not a plain-text label. */
|
|
89
|
+
.wd-parameter-required {
|
|
90
|
+
font-family: monospace;
|
|
91
|
+
font-size: 0.8rem;
|
|
92
|
+
font-weight: 600;
|
|
93
|
+
background: color-mix(in srgb, #dc2626 8%, var(--wd-surface));
|
|
94
|
+
border: 1px solid color-mix(in srgb, #dc2626 35%, var(--wd-border));
|
|
95
|
+
border-radius: 0.35em;
|
|
96
|
+
padding: 0.1em 0.5em;
|
|
97
|
+
color: #dc2626;
|
|
98
|
+
}
|
|
99
|
+
.wd-parameter-default {
|
|
100
|
+
font-size: 0.78rem;
|
|
101
|
+
color: var(--wd-text-muted);
|
|
102
|
+
}
|
|
103
|
+
.wd-parameter-body {
|
|
104
|
+
color: var(--wd-text-muted);
|
|
105
|
+
}
|
|
106
|
+
.wd-parameter-body :global(p:first-child) {
|
|
107
|
+
margin-top: 0;
|
|
108
|
+
}
|
|
109
|
+
.wd-parameter-body :global(p:last-child) {
|
|
110
|
+
margin-bottom: 0;
|
|
111
|
+
}
|
|
112
|
+
/* A nested <Expandable> (see its own comment) sits inside this same
|
|
113
|
+
body slot, right below the description text - a little breathing
|
|
114
|
+
room above it so it doesn't crowd directly against the last line
|
|
115
|
+
of description. */
|
|
116
|
+
.wd-parameter-body :global(.wd-expandable) {
|
|
117
|
+
margin-top: 0.75rem;
|
|
118
|
+
}
|
|
119
|
+
</style>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Pins its code example(s) in the right sidebar - in place of the page's
|
|
3
|
+
// normal table of contents - on desktop; falls back to a plain in-place
|
|
4
|
+
// CodeGroup on narrower viewports where that sidebar column doesn't
|
|
5
|
+
// render at all. Modeled on Mintlify's own RequestExample/
|
|
6
|
+
// ResponseExample (https://www.mintlify.com/docs/components/examples):
|
|
7
|
+
// "work similarly to CodeGroup... but display the code in the sidebar
|
|
8
|
+
// instead of inline" - reuses CodeGroup.astro itself internally (tabs
|
|
9
|
+
// by default, or its own `dropdown` prop for a <select> switcher
|
|
10
|
+
// instead) rather than reimplementing that tab/dropdown-switching logic
|
|
11
|
+
// a second time.
|
|
12
|
+
//
|
|
13
|
+
// The actual relocation into the sidebar is handled entirely by
|
|
14
|
+
// src/scripts/example-panels.ts, mounted once from [...slug].astro - see
|
|
15
|
+
// its own comment for why a client-side DOM move (rather than an
|
|
16
|
+
// Astro-slot/build-time split) is what this needs: MDX compiles this
|
|
17
|
+
// component's children into one single content flow, with no way for a
|
|
18
|
+
// build-time render to place part of that flow into a *different*
|
|
19
|
+
// column's own slot output.
|
|
20
|
+
//
|
|
21
|
+
// wd-example-panel is the marker class that script looks for; it's
|
|
22
|
+
// otherwise a completely plain wrapper.
|
|
23
|
+
import CodeGroup from './CodeGroup.astro';
|
|
24
|
+
interface Props {
|
|
25
|
+
dropdown?: boolean;
|
|
26
|
+
}
|
|
27
|
+
const { dropdown = false } = Astro.props as Props;
|
|
28
|
+
---
|
|
29
|
+
<div class="wd-example-panel wd-request-example">
|
|
30
|
+
<CodeGroup dropdown={dropdown}>
|
|
31
|
+
<slot />
|
|
32
|
+
</CodeGroup>
|
|
33
|
+
</div>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
// See RequestExample.astro's own comment - identical in every respect
|
|
3
|
+
// except the marker class (wd-response-example vs wd-request-example),
|
|
4
|
+
// which src/scripts/example-panels.ts uses to always dock Response
|
|
5
|
+
// panels below Request panels in the sidebar regardless of which order
|
|
6
|
+
// they're written in a page's own MDX, matching Mintlify's own stated
|
|
7
|
+
// behavior ("ResponseExample... pins code examples in the right sidebar
|
|
8
|
+
// beneath any RequestExample content on the same page").
|
|
9
|
+
import CodeGroup from './CodeGroup.astro';
|
|
10
|
+
interface Props {
|
|
11
|
+
dropdown?: boolean;
|
|
12
|
+
}
|
|
13
|
+
const { dropdown = false } = Astro.props as Props;
|
|
14
|
+
---
|
|
15
|
+
<div class="wd-example-panel wd-response-example">
|
|
16
|
+
<CodeGroup dropdown={dropdown}>
|
|
17
|
+
<slot />
|
|
18
|
+
</CodeGroup>
|
|
19
|
+
</div>
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Wraps a GFM table (or any other block-level slot content, though a
|
|
3
|
+
// table is the intended/primary use case) with a text input above it
|
|
4
|
+
// that live-filters rows by their own text content - "let users filter
|
|
5
|
+
// the content inside the wrapper" per the request that spawned this.
|
|
6
|
+
//
|
|
7
|
+
// A markdown table always lands as a *direct* child of .wd-article
|
|
8
|
+
// (see [...slug].astro's own comment on this at its `<style is:global>`
|
|
9
|
+
// block), which is what its own global table CSS rule
|
|
10
|
+
// (`.wd-article > table`) deliberately targets - once wrapped in this
|
|
11
|
+
// component's own .wd-searchbar-content div, that table is no longer a
|
|
12
|
+
// direct child of .wd-article, so that rule's ">" combinator stops
|
|
13
|
+
// matching it. Rather than loosening that combinator sitewide (it's
|
|
14
|
+
// intentionally direct-child-only - see its own comment for why), the
|
|
15
|
+
// exact same declarations are duplicated here, scoped to
|
|
16
|
+
// .wd-searchbar-content instead, so a wrapped table still renders
|
|
17
|
+
// identically to every unwrapped one.
|
|
18
|
+
interface Props {
|
|
19
|
+
placeholder?: string;
|
|
20
|
+
}
|
|
21
|
+
const { placeholder = "Search..." } = Astro.props as Props;
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
<div class="wd-searchbar">
|
|
25
|
+
<input type="text" class="wd-searchbar-input" placeholder={placeholder} aria-label={placeholder} />
|
|
26
|
+
<div class="wd-searchbar-content">
|
|
27
|
+
<slot />
|
|
28
|
+
</div>
|
|
29
|
+
<p class="wd-searchbar-empty">No results found.</p>
|
|
30
|
+
</div>
|
|
31
|
+
<script>
|
|
32
|
+
// Filters by each <tbody> row's own full text content - simplest
|
|
33
|
+
// approach that works regardless of column count/order, and needs no
|
|
34
|
+
// knowledge of the table's shape. Only <tbody> rows are ever
|
|
35
|
+
// filtered (querySelector scopes to "table tbody tr"), so the
|
|
36
|
+
// header row is never a candidate for hiding.
|
|
37
|
+
function initSearchbars(root: ParentNode) {
|
|
38
|
+
root.querySelectorAll<HTMLElement>(".wd-searchbar").forEach((wrapper) => {
|
|
39
|
+
if (wrapper.dataset.wdInit) return;
|
|
40
|
+
wrapper.dataset.wdInit = "true";
|
|
41
|
+
const input = wrapper.querySelector<HTMLInputElement>(".wd-searchbar-input");
|
|
42
|
+
const empty = wrapper.querySelector<HTMLElement>(".wd-searchbar-empty");
|
|
43
|
+
const rows = Array.from(wrapper.querySelectorAll<HTMLTableRowElement>(".wd-searchbar-content table tbody tr"));
|
|
44
|
+
if (!input || rows.length === 0) return;
|
|
45
|
+
input.addEventListener("input", () => {
|
|
46
|
+
const query = input.value.trim().toLowerCase();
|
|
47
|
+
let visibleCount = 0;
|
|
48
|
+
rows.forEach((row) => {
|
|
49
|
+
const isMatch = !query || (row.textContent ?? "").toLowerCase().includes(query);
|
|
50
|
+
row.style.display = isMatch ? "" : "none";
|
|
51
|
+
if (isMatch) visibleCount++;
|
|
52
|
+
});
|
|
53
|
+
if (empty) empty.style.display = visibleCount === 0 ? "block" : "none";
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
initSearchbars(document);
|
|
58
|
+
document.addEventListener("astro:page-load", () => initSearchbars(document));
|
|
59
|
+
</script>
|
|
60
|
+
<style>
|
|
61
|
+
.wd-searchbar {
|
|
62
|
+
margin: 1.25rem 0;
|
|
63
|
+
}
|
|
64
|
+
.wd-searchbar-input {
|
|
65
|
+
box-sizing: border-box;
|
|
66
|
+
width: 100%;
|
|
67
|
+
border: 1px solid var(--wd-border);
|
|
68
|
+
border-radius: 0.6rem;
|
|
69
|
+
padding: 0.6rem 1rem;
|
|
70
|
+
margin-bottom: 1rem;
|
|
71
|
+
color: var(--wd-text);
|
|
72
|
+
background: var(--wd-background);
|
|
73
|
+
font-size: 0.9rem;
|
|
74
|
+
font-family: inherit;
|
|
75
|
+
}
|
|
76
|
+
.wd-searchbar-input::placeholder {
|
|
77
|
+
color: var(--wd-text-muted);
|
|
78
|
+
}
|
|
79
|
+
.wd-searchbar-input:focus {
|
|
80
|
+
outline: none;
|
|
81
|
+
border-color: var(--wd-primary);
|
|
82
|
+
}
|
|
83
|
+
/* Matches .wd-article > table's own global styling exactly (see this
|
|
84
|
+
file's own top comment for why it has to be duplicated here rather
|
|
85
|
+
than reused directly) - width/border-collapse/font-size on the
|
|
86
|
+
table itself, cell padding/border/alignment on th and td, and the
|
|
87
|
+
muted uppercase treatment on th. :global() throughout since slot
|
|
88
|
+
content (the author's own MDX table) never carries this
|
|
89
|
+
component's own scope attribute. */
|
|
90
|
+
.wd-searchbar-content :global(table) {
|
|
91
|
+
width: 100%;
|
|
92
|
+
border-collapse: collapse;
|
|
93
|
+
margin: 0;
|
|
94
|
+
font-size: 0.9rem;
|
|
95
|
+
}
|
|
96
|
+
.wd-searchbar-content :global(th),
|
|
97
|
+
.wd-searchbar-content :global(td) {
|
|
98
|
+
text-align: left;
|
|
99
|
+
padding: 0.55rem 0.75rem;
|
|
100
|
+
border-bottom: 1px solid var(--wd-border);
|
|
101
|
+
vertical-align: top;
|
|
102
|
+
}
|
|
103
|
+
.wd-searchbar-content :global(th) {
|
|
104
|
+
color: var(--wd-text-muted);
|
|
105
|
+
font-weight: 600;
|
|
106
|
+
font-size: 0.8rem;
|
|
107
|
+
text-transform: uppercase;
|
|
108
|
+
letter-spacing: 0.03em;
|
|
109
|
+
}
|
|
110
|
+
.wd-searchbar-empty {
|
|
111
|
+
display: none;
|
|
112
|
+
padding: 1.5rem 0;
|
|
113
|
+
text-align: center;
|
|
114
|
+
color: var(--wd-text-muted);
|
|
115
|
+
font-size: 0.9rem;
|
|
116
|
+
}
|
|
117
|
+
</style>
|