@writedocs/generator 0.4.6 → 0.4.8
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/astro.config.mjs +37 -3
- package/package.json +1 -1
- package/src/components/Accordion.astro +22 -5
- package/src/components/AppIcon.astro +5 -0
- package/src/components/Callout.astro +15 -5
- package/src/components/Card.astro +64 -13
- package/src/components/Check.astro +13 -0
- package/src/components/Color.astro +61 -0
- package/src/components/ColorItem.astro +93 -0
- package/src/components/ColorRow.astro +39 -0
- package/src/components/Columns.astro +11 -0
- package/src/components/Frame.astro +10 -1
- package/src/components/GitHubRepo.astro +156 -0
- package/src/components/Hint.astro +50 -4
- package/src/components/Panel.astro +11 -0
- package/src/components/ParamField.astro +25 -0
- package/src/components/Parameter.astro +41 -4
- package/src/components/Prompt.astro +143 -0
- package/src/components/ResponseField.astro +18 -0
- package/src/components/Step.astro +22 -3
- package/src/components/Steps.astro +22 -0
- package/src/components/Tab.astro +7 -1
- package/src/components/Tabs.astro +27 -4
- package/src/components/Tile.astro +65 -0
- package/src/components/Tooltip.astro +13 -0
- package/src/components/Tree.astro +213 -0
- package/src/components/TreeFile.astro +17 -0
- package/src/components/TreeFolder.astro +28 -0
- package/src/components/Update.astro +171 -0
- package/src/components/View.astro +214 -0
- package/src/components/Visibility.astro +11 -0
- package/src/components/compound.ts +21 -0
- package/src/components/index.ts +12 -0
- package/src/content.config.ts +68 -2
- package/src/layout/components/NavTree.astro +34 -0
- package/src/layout/styles/base.css +12 -0
- package/src/lib/config.ts +1412 -1306
- package/src/lib/inline-markdown.js +29 -0
- package/src/lib/mdx-inject-builtins.js +20 -2
- package/src/lib/mdx-mintlify.js +99 -0
- package/src/lib/mdx-title-anchor-ids.js +7 -2
- package/src/lib/shiki-code-block.js +140 -26
- package/src/lib/visibility.js +29 -0
- package/src/pages/[...slug].astro +110 -7
- package/src/pages/[...slug].md.ts +7 -1
- package/src/pages/llms-full.txt.ts +5 -1
- package/src/pages/llms.txt.ts +3 -0
- package/src/styles/global.css +10 -0
package/astro.config.mjs
CHANGED
|
@@ -26,6 +26,7 @@ import { remarkAutoHydrateSnippets } from './src/lib/mdx-auto-hydrate.js';
|
|
|
26
26
|
import { remarkInjectBuiltinComponents } from './src/lib/mdx-inject-builtins.js';
|
|
27
27
|
import { remarkTitleAnchorIds } from './src/lib/mdx-title-anchor-ids.js';
|
|
28
28
|
import { remarkSubstituteVariables } from './src/lib/mdx-substitute-variables.js';
|
|
29
|
+
import { remarkMintlifyTreeLists, remarkMintlifyPromptText } from './src/lib/mdx-mintlify.js';
|
|
29
30
|
import { writedocsTempDir, writedocsBuildStagingDir } from './src/lib/writedocs-temp-dir.js';
|
|
30
31
|
import { stylesAssetFallback } from './src/lib/styles-asset-integration.js';
|
|
31
32
|
import {
|
|
@@ -131,7 +132,12 @@ function collectNoindexIds(rootContentDir) {
|
|
|
131
132
|
for (const relativeId of findAllPages(rootContentDir)) {
|
|
132
133
|
const file = path.join(rootContentDir, relativeId);
|
|
133
134
|
const { data } = matter(fs.readFileSync(file, 'utf-8'));
|
|
134
|
-
|
|
135
|
+
// Top-level `noindex` is Mintlify's spelling, and a Mintlify `hidden`
|
|
136
|
+
// page is noindexed too - content.config.ts folds both into
|
|
137
|
+
// `seo.noindex` the same way (an explicit value wins).
|
|
138
|
+
// A frontmatter `url` page's route only redirects to that link, so it
|
|
139
|
+
// doesn't belong in the sitemap either.
|
|
140
|
+
if (!(data?.seo?.noindex ?? data?.noindex ?? data?.hidden === true) && !data?.url) continue;
|
|
135
141
|
const fallbackId = relativeId.replace(/\.mdx?$/i, '').replace(/\/index$/, '');
|
|
136
142
|
ids.add(normalizeEntryId(data.slug ?? fallbackId));
|
|
137
143
|
}
|
|
@@ -140,7 +146,7 @@ function collectNoindexIds(rootContentDir) {
|
|
|
140
146
|
// to the way there is for a hand-written page.
|
|
141
147
|
for (const file of walkMdFiles(generatedDocsDir)) {
|
|
142
148
|
const { data } = matter(fs.readFileSync(file, 'utf-8'));
|
|
143
|
-
if (data?.seo?.noindex && data.slug) ids.add(normalizeEntryId(data.slug));
|
|
149
|
+
if ((data?.seo?.noindex ?? data?.noindex ?? data?.hidden === true) && data.slug) ids.add(normalizeEntryId(data.slug));
|
|
144
150
|
}
|
|
145
151
|
return ids;
|
|
146
152
|
}
|
|
@@ -192,6 +198,25 @@ function singleSitemapFile() {
|
|
|
192
198
|
// of only opting into a feature's config surface when it's actually used.
|
|
193
199
|
const redirectsConfig = Object.fromEntries(docsConfig.redirects.map((r) => [r.source, r.destination]));
|
|
194
200
|
|
|
201
|
+
/** Tailwind only scans the Vite root for class names - this package, not
|
|
202
|
+
* the site being built, which is usually somewhere else entirely - so a
|
|
203
|
+
* utility class written in a site's own MDX or snippet (Mintlify content
|
|
204
|
+
* uses them freely, e.g. className="block dark:hidden") never got
|
|
205
|
+
* generated. Appends an @source for the site's content files to
|
|
206
|
+
* global.css before Tailwind compiles it. Forward slashes, since
|
|
207
|
+
* Tailwind reads the path as a glob. */
|
|
208
|
+
function contentTailwindSource() {
|
|
209
|
+
const sourceGlob = `${contentDir.split(path.sep).join('/')}/**/*.{md,mdx,jsx,tsx}`;
|
|
210
|
+
return {
|
|
211
|
+
name: 'writedocs:content-tailwind-source',
|
|
212
|
+
enforce: 'pre',
|
|
213
|
+
transform(code, id) {
|
|
214
|
+
if (!id.split('?')[0].replace(/\\/g, '/').endsWith('/src/styles/global.css')) return null;
|
|
215
|
+
return { code: `${code}\n@source ${JSON.stringify(sourceGlob)};\n`, map: null };
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
195
220
|
export default defineConfig({
|
|
196
221
|
...(siteUrl ? { site: siteUrl } : {}),
|
|
197
222
|
...(docsConfig.redirects.length ? { redirects: redirectsConfig } : {}),
|
|
@@ -339,6 +364,12 @@ export default defineConfig({
|
|
|
339
364
|
// as raw text first.
|
|
340
365
|
remarkPlugins: [
|
|
341
366
|
remarkMath,
|
|
367
|
+
// Mintlify's Markdown-list <Tree> and <Prompt> source text - see
|
|
368
|
+
// lib/mdx-mintlify.js. Before remarkInjectBuiltinComponents, so
|
|
369
|
+
// the <Tree.Folder>/<Tree.File> elements they add are already in
|
|
370
|
+
// the tree when it looks for components to import.
|
|
371
|
+
remarkMintlifyTreeLists,
|
|
372
|
+
remarkMintlifyPromptText,
|
|
342
373
|
remarkInjectBuiltinComponents,
|
|
343
374
|
// Runs after remarkInjectBuiltinComponents (order doesn't actually
|
|
344
375
|
// matter between them - that plugin only ever prepends an import
|
|
@@ -404,7 +435,10 @@ export default defineConfig({
|
|
|
404
435
|
// working. See src/styles/global.css for the one @import that wires
|
|
405
436
|
// Tailwind's utilities in.
|
|
406
437
|
vite: {
|
|
407
|
-
|
|
438
|
+
// contentTailwindSource() must come before tailwindcss(): both are
|
|
439
|
+
// enforce: 'pre' transforms, which Vite runs in array order, and
|
|
440
|
+
// Tailwind has to see the added @source when it compiles global.css.
|
|
441
|
+
plugins: [contentTailwindSource(), tailwindcss()],
|
|
408
442
|
resolve: {
|
|
409
443
|
alias: [
|
|
410
444
|
// Lets a page's MDX write `import Foo from '/snippets/foo.mdx'`
|
package/package.json
CHANGED
|
@@ -4,6 +4,10 @@ import AppIcon from "./AppIcon.astro";
|
|
|
4
4
|
interface Props {
|
|
5
5
|
title: string;
|
|
6
6
|
icon?: string;
|
|
7
|
+
// Mintlify parity: `description` is a muted second line under the title,
|
|
8
|
+
// `defaultOpen` renders the accordion already expanded.
|
|
9
|
+
description?: string;
|
|
10
|
+
defaultOpen?: boolean;
|
|
7
11
|
// Set automatically by remarkTitleAnchorIds (src/lib/mdx-title-anchor-ids.js)
|
|
8
12
|
// for every <Accordion title="..."> it finds in an .mdx file's own JSX,
|
|
9
13
|
// already deduped (-2, -3, ...) against every other Accordion/Callout
|
|
@@ -14,7 +18,7 @@ interface Props {
|
|
|
14
18
|
// title={expr}, or this component used directly from a .astro file).
|
|
15
19
|
_titleId?: string;
|
|
16
20
|
}
|
|
17
|
-
const { title, icon, _titleId } = Astro.props as Props;
|
|
21
|
+
const { title, icon, description, defaultOpen = false, _titleId } = Astro.props as Props;
|
|
18
22
|
// Astro's own heading-id slugging (github-slugger, via the markdown
|
|
19
23
|
// pipeline) never sees this - `title` is a component prop, not a markdown
|
|
20
24
|
// heading, so it gets no id unless we make one ourselves. Same slugify
|
|
@@ -28,13 +32,16 @@ function slugify(value: string): string {
|
|
|
28
32
|
const titleId = _titleId ?? slugify(title);
|
|
29
33
|
---
|
|
30
34
|
|
|
31
|
-
<details class="wd-accordion">
|
|
35
|
+
<details class="wd-accordion" open={defaultOpen}>
|
|
32
36
|
<summary>
|
|
33
37
|
<span class="wd-accordion-heading">
|
|
34
38
|
{icon && <AppIcon icon={icon} class="wd-accordion-icon" />}
|
|
35
|
-
<span class="wd-accordion-
|
|
36
|
-
{
|
|
37
|
-
|
|
39
|
+
<span class="wd-accordion-text">
|
|
40
|
+
<span class="wd-accordion-title" id={titleId}>
|
|
41
|
+
{title}
|
|
42
|
+
<a class="wd-heading-anchor" href={`#${titleId}`} aria-label="Link to this section"> # </a>
|
|
43
|
+
</span>
|
|
44
|
+
{description && <span class="wd-accordion-description">{description}</span>}
|
|
38
45
|
</span>
|
|
39
46
|
</span>
|
|
40
47
|
{
|
|
@@ -128,6 +135,16 @@ const titleId = _titleId ?? slugify(title);
|
|
|
128
135
|
flex-shrink: 0;
|
|
129
136
|
color: var(--wd-text-muted);
|
|
130
137
|
}
|
|
138
|
+
.wd-accordion-text {
|
|
139
|
+
display: flex;
|
|
140
|
+
flex-direction: column;
|
|
141
|
+
gap: 0.15rem;
|
|
142
|
+
min-width: 0;
|
|
143
|
+
}
|
|
144
|
+
.wd-accordion-description {
|
|
145
|
+
font-size: 0.85rem;
|
|
146
|
+
color: var(--wd-text-muted);
|
|
147
|
+
}
|
|
131
148
|
.wd-accordion-title {
|
|
132
149
|
font-weight: 700;
|
|
133
150
|
color: var(--wd-text);
|
|
@@ -26,6 +26,11 @@ const resolved = icon ? resolveIcon(icon) : null;
|
|
|
26
26
|
{resolved && (
|
|
27
27
|
resolved.kind === 'iconify' ? (
|
|
28
28
|
<Icon name={resolved.name} class={className} style={style} />
|
|
29
|
+
) : resolved.kind === 'image' ? (
|
|
30
|
+
// Wrapped in the same <span> text icons use, so each caller's own
|
|
31
|
+
// span.<class> rule (font-size, spacing) sizes it; the image fills
|
|
32
|
+
// 1em of that (img.wd-icon-img in layout/styles/base.css).
|
|
33
|
+
<span class={className} style={style}><img src={resolved.src} alt="" class="wd-icon-img" /></span>
|
|
29
34
|
) : (
|
|
30
35
|
<span class={className} style={style}>{resolved.value}</span>
|
|
31
36
|
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
// See src/components/{Note,Tip,Warning,Danger,Info}.astro - one thin
|
|
2
|
+
// See src/components/{Note,Tip,Warning,Danger,Info,Check}.astro - one thin
|
|
3
3
|
// wrapper per `type` below, each just `<Callout type="x">` under the
|
|
4
4
|
// hood, so a page can write either `<Callout type="info">` or the
|
|
5
5
|
// shorthand `<Info>` and get an identical result. Both forms take the
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import AppIcon from "./AppIcon.astro";
|
|
8
8
|
|
|
9
9
|
interface Props {
|
|
10
|
-
type?: "note" | "tip" | "warning" | "danger" | "info";
|
|
10
|
+
type?: "note" | "tip" | "warning" | "danger" | "info" | "check";
|
|
11
11
|
title?: string;
|
|
12
12
|
// Set automatically by remarkCalloutAnchorIds (src/lib/mdx-callout-anchor-ids.js)
|
|
13
13
|
// for every <Callout title="...">/<Note title="...">/etc. it finds in an
|
|
@@ -19,8 +19,14 @@ interface Props {
|
|
|
19
19
|
// dynamic `title={expr}`, or this component used directly from a .astro
|
|
20
20
|
// file rather than through MDX).
|
|
21
21
|
_titleId?: string;
|
|
22
|
+
// Mintlify's custom callout: `icon` replaces the type's own icon (any
|
|
23
|
+
// icon string AppIcon accepts), `color` replaces its accent color - the
|
|
24
|
+
// border, tint, icon and title all derive from that one value.
|
|
25
|
+
icon?: string;
|
|
26
|
+
color?: string;
|
|
22
27
|
}
|
|
23
|
-
const { type = "note", title, _titleId } = Astro.props as Props;
|
|
28
|
+
const { type = "note", title, _titleId, icon, color } = Astro.props as Props;
|
|
29
|
+
const accentStyle = color ? `--wd-callout-accent: ${color}` : undefined;
|
|
24
30
|
// FontAwesome Solid (fa6-solid, already an installed @iconify-json/*
|
|
25
31
|
// collection - see astro.config.mjs's own comment on icon() needing no
|
|
26
32
|
// allowlist) rather than a literal emoji, so every callout gets a real,
|
|
@@ -31,6 +37,7 @@ const icons: Record<string, string> = {
|
|
|
31
37
|
tip: "fa6-solid:lightbulb",
|
|
32
38
|
warning: "fa6-solid:triangle-exclamation",
|
|
33
39
|
danger: "fa6-solid:circle-xmark",
|
|
40
|
+
check: "fa6-solid:circle-check",
|
|
34
41
|
};
|
|
35
42
|
// Astro's own heading-id slugging (github-slugger, via the markdown
|
|
36
43
|
// pipeline) never sees this - `title` is a component prop, not a
|
|
@@ -44,8 +51,8 @@ function slugify(value: string): string {
|
|
|
44
51
|
const titleId = title ? (_titleId ?? slugify(title)) : undefined;
|
|
45
52
|
---
|
|
46
53
|
|
|
47
|
-
<div class:list={["wd-callout", `wd-callout-${type}`, { "wd-callout-titled": Boolean(title) }]}>
|
|
48
|
-
<AppIcon icon={icons[type]} class="wd-callout-icon" />
|
|
54
|
+
<div class:list={["wd-callout", `wd-callout-${type}`, { "wd-callout-titled": Boolean(title) }]} style={accentStyle}>
|
|
55
|
+
<AppIcon icon={icon ?? icons[type]} class="wd-callout-icon" />
|
|
49
56
|
<div class="wd-callout-content">
|
|
50
57
|
{
|
|
51
58
|
title && (
|
|
@@ -165,4 +172,7 @@ const titleId = title ? (_titleId ?? slugify(title)) : undefined;
|
|
|
165
172
|
.wd-callout-danger {
|
|
166
173
|
--wd-callout-accent: #dc2626;
|
|
167
174
|
}
|
|
175
|
+
.wd-callout-check {
|
|
176
|
+
--wd-callout-accent: #059669;
|
|
177
|
+
}
|
|
168
178
|
</style>
|
|
@@ -26,27 +26,40 @@ interface Props {
|
|
|
26
26
|
// generic component over a handful of literal hex values).
|
|
27
27
|
method?: string;
|
|
28
28
|
href?: string;
|
|
29
|
+
// Mintlify's Card props: `color` tints the icon, `horizontal` puts the
|
|
30
|
+
// icon beside the text instead of above it, `cta` adds a call-to-action
|
|
31
|
+
// line at the bottom, and `arrow` marks a linked card with an arrow in
|
|
32
|
+
// its corner.
|
|
33
|
+
color?: string;
|
|
34
|
+
horizontal?: boolean;
|
|
35
|
+
cta?: string;
|
|
36
|
+
arrow?: boolean;
|
|
29
37
|
}
|
|
30
|
-
const { title, icon, img, method, href } = Astro.props as Props;
|
|
38
|
+
const { title, icon, img, method, href, color, horizontal = false, cta, arrow = false } = Astro.props as Props;
|
|
39
|
+
const iconStyle = color ? `color: ${color}` : undefined;
|
|
31
40
|
const Tag = href ? 'a' : 'div';
|
|
32
41
|
const KNOWN_METHODS = ['get', 'post', 'put', 'patch', 'delete'];
|
|
33
42
|
const methodLower = method?.toLowerCase();
|
|
34
43
|
const methodClass = methodLower && KNOWN_METHODS.includes(methodLower) ? methodLower : 'other';
|
|
35
44
|
---
|
|
36
|
-
<Tag class=
|
|
45
|
+
<Tag class:list={['wd-card', { 'wd-card-horizontal': horizontal, 'wd-card-has-arrow': arrow && href }]} href={href}>
|
|
37
46
|
{img && <img src={img} alt="" class="wd-card-image" />}
|
|
38
|
-
{!img && <AppIcon icon={icon} class="wd-card-icon" />}
|
|
39
|
-
<div class="wd-card-
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
{method
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
{!img && <AppIcon icon={icon} class="wd-card-icon" style={iconStyle} />}
|
|
48
|
+
<div class="wd-card-text">
|
|
49
|
+
<div class="wd-card-title-row">
|
|
50
|
+
<h3 class="wd-card-title">{title}</h3>
|
|
51
|
+
{
|
|
52
|
+
method && (
|
|
53
|
+
<span class:list={['wd-card-method', `wd-card-method-${methodClass}`]}>
|
|
54
|
+
{method.toUpperCase()}
|
|
55
|
+
</span>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
</div>
|
|
59
|
+
<div class="wd-card-body"><slot /></div>
|
|
60
|
+
{cta && <span class="wd-card-cta">{cta} <span aria-hidden="true">→</span></span>}
|
|
48
61
|
</div>
|
|
49
|
-
<
|
|
62
|
+
{arrow && href && <span class="wd-card-arrow" aria-hidden="true">↗</span>}
|
|
50
63
|
</Tag>
|
|
51
64
|
<style>
|
|
52
65
|
.wd-card {
|
|
@@ -133,4 +146,42 @@ const methodClass = methodLower && KNOWN_METHODS.includes(methodLower) ? methodL
|
|
|
133
146
|
.wd-card-body :global(p) {
|
|
134
147
|
margin: 0;
|
|
135
148
|
}
|
|
149
|
+
/* Icon in its own column beside the title/body, both vertically
|
|
150
|
+
centered - Mintlify's compact horizontal card. */
|
|
151
|
+
.wd-card-horizontal {
|
|
152
|
+
display: flex;
|
|
153
|
+
align-items: center;
|
|
154
|
+
gap: 0.9rem;
|
|
155
|
+
}
|
|
156
|
+
.wd-card-horizontal .wd-card-title-row {
|
|
157
|
+
margin-top: 0;
|
|
158
|
+
}
|
|
159
|
+
.wd-card-text {
|
|
160
|
+
min-width: 0;
|
|
161
|
+
flex: 1;
|
|
162
|
+
}
|
|
163
|
+
.wd-card-cta {
|
|
164
|
+
display: inline-block;
|
|
165
|
+
margin-top: 0.7rem;
|
|
166
|
+
font-size: 0.85rem;
|
|
167
|
+
font-weight: 600;
|
|
168
|
+
color: var(--wd-primary);
|
|
169
|
+
}
|
|
170
|
+
/* Only a card that shows the arrow becomes a positioning context -
|
|
171
|
+
setting it on every card changed how existing cards' text was
|
|
172
|
+
antialiased, for no layout reason. */
|
|
173
|
+
.wd-card-has-arrow {
|
|
174
|
+
position: relative;
|
|
175
|
+
}
|
|
176
|
+
.wd-card-arrow {
|
|
177
|
+
position: absolute;
|
|
178
|
+
top: 0.8rem;
|
|
179
|
+
right: 0.9rem;
|
|
180
|
+
color: var(--wd-text-muted);
|
|
181
|
+
font-size: 0.95rem;
|
|
182
|
+
line-height: 1;
|
|
183
|
+
}
|
|
184
|
+
a.wd-card:hover .wd-card-arrow {
|
|
185
|
+
color: var(--wd-primary);
|
|
186
|
+
}
|
|
136
187
|
</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Shorthand for <Callout type="check"> - Mintlify's <Check> ("this worked",
|
|
3
|
+
// "you're done"). See Callout.astro's own comment.
|
|
4
|
+
import Callout from './Callout.astro';
|
|
5
|
+
interface Props {
|
|
6
|
+
title?: string;
|
|
7
|
+
// See Callout.astro's own comment - set automatically by
|
|
8
|
+
// remarkCalloutAnchorIds, not meant to be passed by hand.
|
|
9
|
+
_titleId?: string;
|
|
10
|
+
}
|
|
11
|
+
const { title, _titleId } = Astro.props as Props;
|
|
12
|
+
---
|
|
13
|
+
<Callout type="check" title={title} _titleId={_titleId}><slot /></Callout>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Mintlify's <Color> - a palette of <Color.Item> swatches. `variant`:
|
|
3
|
+
// compact (default) - one grid of swatches.
|
|
4
|
+
// table - <Color.Row title="..."> rows, each a titled line of
|
|
5
|
+
// swatches.
|
|
6
|
+
// Color.Row/Color.Item are ColorRow.astro/ColorItem.astro, attached as
|
|
7
|
+
// properties in components/compound.ts so the dotted names resolve in MDX.
|
|
8
|
+
interface Props {
|
|
9
|
+
variant?: 'compact' | 'table';
|
|
10
|
+
}
|
|
11
|
+
const { variant = 'compact' } = Astro.props as Props;
|
|
12
|
+
---
|
|
13
|
+
<div class:list={['wd-color', `wd-color-${variant}`]}><slot /></div>
|
|
14
|
+
<script>
|
|
15
|
+
// Click (or Enter/Space) on a swatch copies the value currently shown -
|
|
16
|
+
// for a light/dark pair, the one matching the site's theme right now.
|
|
17
|
+
function initColorCopy(root: ParentNode) {
|
|
18
|
+
root.querySelectorAll<HTMLElement>('.wd-color-item[data-light]').forEach((item) => {
|
|
19
|
+
if (item.dataset.wdInit) return;
|
|
20
|
+
item.dataset.wdInit = 'true';
|
|
21
|
+
const copy = async () => {
|
|
22
|
+
const dark = document.documentElement.dataset.theme === 'dark';
|
|
23
|
+
const value = (dark ? item.dataset.dark : item.dataset.light) ?? '';
|
|
24
|
+
const label = item.querySelector<HTMLElement>('.wd-color-copied');
|
|
25
|
+
try {
|
|
26
|
+
await navigator.clipboard.writeText(value);
|
|
27
|
+
if (label) label.textContent = 'Copied';
|
|
28
|
+
} catch {
|
|
29
|
+
if (label) label.textContent = 'Copy failed';
|
|
30
|
+
}
|
|
31
|
+
setTimeout(() => label && (label.textContent = ''), 1200);
|
|
32
|
+
};
|
|
33
|
+
item.addEventListener('click', copy);
|
|
34
|
+
item.addEventListener('keydown', (e) => {
|
|
35
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
36
|
+
e.preventDefault();
|
|
37
|
+
copy();
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
initColorCopy(document);
|
|
43
|
+
document.addEventListener('astro:page-load', () => initColorCopy(document));
|
|
44
|
+
</script>
|
|
45
|
+
<style>
|
|
46
|
+
.wd-color {
|
|
47
|
+
margin: 1.25rem 0;
|
|
48
|
+
}
|
|
49
|
+
.wd-color-compact {
|
|
50
|
+
display: grid;
|
|
51
|
+
grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
|
|
52
|
+
gap: 1rem;
|
|
53
|
+
}
|
|
54
|
+
.wd-color-table {
|
|
55
|
+
display: flex;
|
|
56
|
+
flex-direction: column;
|
|
57
|
+
border: 1px solid var(--wd-border);
|
|
58
|
+
border-radius: 0.6rem;
|
|
59
|
+
overflow: hidden;
|
|
60
|
+
}
|
|
61
|
+
</style>
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Mintlify's <Color.Item name="..." value="..."> - one swatch. `value` is
|
|
3
|
+
// any CSS color, or { light, dark } for a theme-aware pair: the swatch and
|
|
4
|
+
// the value text switch with the site's theme toggle ([data-theme] on
|
|
5
|
+
// <html>), via the two custom properties below. Click copies the value
|
|
6
|
+
// (Color.astro's script).
|
|
7
|
+
interface Props {
|
|
8
|
+
name?: string;
|
|
9
|
+
value?: string | { light: string; dark: string };
|
|
10
|
+
}
|
|
11
|
+
const { name, value } = Astro.props as Props;
|
|
12
|
+
const light = typeof value === 'string' ? value : value?.light;
|
|
13
|
+
const dark = typeof value === 'string' ? value : value?.dark;
|
|
14
|
+
const themed = typeof value === 'object' && value !== null && light !== dark;
|
|
15
|
+
const style = light ? `--wd-swatch-light: ${light}; --wd-swatch-dark: ${dark ?? light}` : undefined;
|
|
16
|
+
---
|
|
17
|
+
<div
|
|
18
|
+
class="wd-color-item"
|
|
19
|
+
data-light={light}
|
|
20
|
+
data-dark={dark}
|
|
21
|
+
role={light ? 'button' : undefined}
|
|
22
|
+
tabindex={light ? 0 : undefined}
|
|
23
|
+
title={light ? 'Copy value' : undefined}
|
|
24
|
+
style={style}
|
|
25
|
+
>
|
|
26
|
+
<div class="wd-color-swatch"></div>
|
|
27
|
+
<div class="wd-color-name">{name}</div>
|
|
28
|
+
{light && (
|
|
29
|
+
<div class="wd-color-value">
|
|
30
|
+
{themed ? (
|
|
31
|
+
<>
|
|
32
|
+
<span class="wd-color-value-light">{light}</span>
|
|
33
|
+
<span class="wd-color-value-dark">{dark}</span>
|
|
34
|
+
</>
|
|
35
|
+
) : (
|
|
36
|
+
light
|
|
37
|
+
)}
|
|
38
|
+
<span class="wd-color-copied" aria-live="polite"></span>
|
|
39
|
+
</div>
|
|
40
|
+
)}
|
|
41
|
+
</div>
|
|
42
|
+
<style>
|
|
43
|
+
.wd-color-item {
|
|
44
|
+
min-width: 0;
|
|
45
|
+
}
|
|
46
|
+
.wd-color-item[role='button'] {
|
|
47
|
+
cursor: pointer;
|
|
48
|
+
}
|
|
49
|
+
/* A checkerboard under the swatch, so a translucent color (rgba, hsla)
|
|
50
|
+
reads as translucent rather than as a lighter solid. */
|
|
51
|
+
.wd-color-swatch {
|
|
52
|
+
height: 3.5rem;
|
|
53
|
+
border: 1px solid var(--wd-border);
|
|
54
|
+
border-radius: 0.5rem;
|
|
55
|
+
background:
|
|
56
|
+
linear-gradient(var(--wd-swatch-light, transparent), var(--wd-swatch-light, transparent)),
|
|
57
|
+
repeating-conic-gradient(var(--wd-surface) 0% 25%, var(--wd-background) 0% 50%) 0 0 / 12px 12px;
|
|
58
|
+
}
|
|
59
|
+
:global([data-theme='dark']) .wd-color-swatch {
|
|
60
|
+
background:
|
|
61
|
+
linear-gradient(var(--wd-swatch-dark, transparent), var(--wd-swatch-dark, transparent)),
|
|
62
|
+
repeating-conic-gradient(var(--wd-surface) 0% 25%, var(--wd-background) 0% 50%) 0 0 / 12px 12px;
|
|
63
|
+
}
|
|
64
|
+
.wd-color-item[role='button']:hover .wd-color-swatch,
|
|
65
|
+
.wd-color-item[role='button']:focus-visible .wd-color-swatch {
|
|
66
|
+
border-color: var(--wd-primary);
|
|
67
|
+
}
|
|
68
|
+
.wd-color-name {
|
|
69
|
+
margin-top: 0.4rem;
|
|
70
|
+
font-size: 0.85rem;
|
|
71
|
+
font-weight: 600;
|
|
72
|
+
overflow-wrap: anywhere;
|
|
73
|
+
}
|
|
74
|
+
.wd-color-value {
|
|
75
|
+
font-family: monospace;
|
|
76
|
+
font-size: 0.75rem;
|
|
77
|
+
color: var(--wd-text-muted);
|
|
78
|
+
overflow-wrap: anywhere;
|
|
79
|
+
}
|
|
80
|
+
.wd-color-value-dark {
|
|
81
|
+
display: none;
|
|
82
|
+
}
|
|
83
|
+
:global([data-theme='dark']) .wd-color-value-light {
|
|
84
|
+
display: none;
|
|
85
|
+
}
|
|
86
|
+
:global([data-theme='dark']) .wd-color-value-dark {
|
|
87
|
+
display: inline;
|
|
88
|
+
}
|
|
89
|
+
.wd-color-copied {
|
|
90
|
+
margin-left: 0.35rem;
|
|
91
|
+
color: var(--wd-primary);
|
|
92
|
+
}
|
|
93
|
+
</style>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Mintlify's <Color.Row title="..."> - one titled row inside
|
|
3
|
+
// <Color variant="table">. `title` takes inline Markdown.
|
|
4
|
+
import { inlineMarkdown } from '../lib/inline-markdown.js';
|
|
5
|
+
interface Props {
|
|
6
|
+
title?: string;
|
|
7
|
+
}
|
|
8
|
+
const { title } = Astro.props as Props;
|
|
9
|
+
---
|
|
10
|
+
<div class="wd-color-row">
|
|
11
|
+
<div class="wd-color-row-title" set:html={inlineMarkdown(title ?? '')} />
|
|
12
|
+
<div class="wd-color-row-items"><slot /></div>
|
|
13
|
+
</div>
|
|
14
|
+
<style>
|
|
15
|
+
.wd-color-row {
|
|
16
|
+
display: grid;
|
|
17
|
+
grid-template-columns: 9rem minmax(0, 1fr);
|
|
18
|
+
gap: 1rem;
|
|
19
|
+
align-items: center;
|
|
20
|
+
padding: 1rem;
|
|
21
|
+
}
|
|
22
|
+
.wd-color-row + .wd-color-row {
|
|
23
|
+
border-top: 1px solid var(--wd-border);
|
|
24
|
+
}
|
|
25
|
+
.wd-color-row-title {
|
|
26
|
+
font-weight: 600;
|
|
27
|
+
font-size: 0.9rem;
|
|
28
|
+
}
|
|
29
|
+
.wd-color-row-items {
|
|
30
|
+
display: grid;
|
|
31
|
+
grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr));
|
|
32
|
+
gap: 1rem;
|
|
33
|
+
}
|
|
34
|
+
@media (max-width: 640px) {
|
|
35
|
+
.wd-color-row {
|
|
36
|
+
grid-template-columns: minmax(0, 1fr);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Mintlify's <Columns cols={n}> - the grid Mintlify now uses around Cards
|
|
3
|
+
// (its docs moved from <CardGroup> to this). Same grid as CardGroup.astro,
|
|
4
|
+
// which already lays out any children, not only Cards.
|
|
5
|
+
import CardGroup from './CardGroup.astro';
|
|
6
|
+
interface Props {
|
|
7
|
+
cols?: number;
|
|
8
|
+
}
|
|
9
|
+
const { cols } = Astro.props as Props;
|
|
10
|
+
---
|
|
11
|
+
<CardGroup cols={cols}><slot /></CardGroup>
|
|
@@ -12,13 +12,17 @@
|
|
|
12
12
|
// component's name collides with frontmatter's own `mode: "frame"`
|
|
13
13
|
// page-rendering option (BaseLayout.astro) - that's an unrelated,
|
|
14
14
|
// page-level concept keyed off a plain string, not a JSX component.
|
|
15
|
+
// `hint` is Mintlify's: a short line shown above the framed content, as
|
|
16
|
+
// opposed to `caption` below it.
|
|
15
17
|
interface Props {
|
|
16
18
|
caption?: string;
|
|
19
|
+
hint?: string;
|
|
17
20
|
}
|
|
18
|
-
const { caption } = Astro.props as Props;
|
|
21
|
+
const { caption, hint } = Astro.props as Props;
|
|
19
22
|
---
|
|
20
23
|
|
|
21
24
|
<figure class="wd-frame">
|
|
25
|
+
{hint && <p class="wd-frame-hint">{hint}</p>}
|
|
22
26
|
<div class="wd-frame-content">
|
|
23
27
|
<slot />
|
|
24
28
|
</div>
|
|
@@ -93,6 +97,11 @@ const { caption } = Astro.props as Props;
|
|
|
93
97
|
.wd-frame-content :global(p) {
|
|
94
98
|
display: contents;
|
|
95
99
|
}
|
|
100
|
+
.wd-frame-hint {
|
|
101
|
+
margin: 0.1rem 0.25rem 0.5rem;
|
|
102
|
+
color: var(--wd-text-muted);
|
|
103
|
+
font-size: 0.8rem;
|
|
104
|
+
}
|
|
96
105
|
.wd-frame-caption {
|
|
97
106
|
margin: 0.6rem 0 0;
|
|
98
107
|
text-align: center;
|